Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <classes/menumanager.hxx>
21 : #include <framework/menuconfiguration.hxx>
22 : #include <framework/bmkmenu.hxx>
23 : #include <framework/addonmenu.hxx>
24 : #include <framework/imageproducer.hxx>
25 : #include <threadhelp/resetableguard.hxx>
26 : #include "framework/addonsoptions.hxx"
27 : #include <classes/fwkresid.hxx>
28 : #include <services.h>
29 : #include "classes/resource.hrc"
30 :
31 : #include <com/sun/star/frame/XDispatchProvider.hpp>
32 : #include <com/sun/star/frame/XDispatch.hpp>
33 : #include <com/sun/star/util/URLTransformer.hpp>
34 : #include <com/sun/star/util/XURLTransformer.hpp>
35 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 : #include <com/sun/star/beans/XPropertySet.hpp>
37 : #include <com/sun/star/frame/XFramesSupplier.hpp>
38 : #include <com/sun/star/frame/XDesktop.hpp>
39 : #include <com/sun/star/container/XEnumeration.hpp>
40 : #include <com/sun/star/util/XStringWidth.hpp>
41 :
42 : #include <comphelper/processfactory.hxx>
43 :
44 : #include <comphelper/extract.hxx>
45 : #include <svtools/menuoptions.hxx>
46 : #include <unotools/historyoptions.hxx>
47 : #include <unotools/pathoptions.hxx>
48 : #include <unotools/localfilehelper.hxx>
49 :
50 : #include <toolkit/unohlp.hxx>
51 : #include <tools/urlobj.hxx>
52 :
53 : #include <vcl/svapp.hxx>
54 : #include <vcl/window.hxx>
55 : #include <osl/mutex.hxx>
56 : #include <vcl/svapp.hxx>
57 : #include <osl/file.hxx>
58 : #include <cppuhelper/implbase1.hxx>
59 :
60 : using namespace ::cppu;
61 : using namespace ::com::sun::star::uno;
62 : using namespace ::com::sun::star::util;
63 : using namespace ::com::sun::star::beans;
64 : using namespace ::com::sun::star::frame;
65 : using namespace ::com::sun::star::lang;
66 : using namespace ::com::sun::star::container;
67 :
68 :
69 : class StringLength : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XStringWidth >
70 : {
71 : public:
72 0 : StringLength() {}
73 0 : virtual ~StringLength() {}
74 :
75 : // XStringWidth
76 0 : sal_Int32 SAL_CALL queryStringWidth( const ::rtl::OUString& aString )
77 : throw (::com::sun::star::uno::RuntimeException)
78 : {
79 0 : return aString.getLength();
80 : }
81 : };
82 :
83 : namespace framework
84 : {
85 :
86 : // special menu ids/command ids for dynamic popup menus
87 : #define SID_SFX_START 5000
88 : #define SID_NEWDOCDIRECT (SID_SFX_START + 537)
89 : #define SID_AUTOPILOTMENU (SID_SFX_START + 1381)
90 : #define SID_PICKLIST (SID_SFX_START + 510)
91 : #define SID_MDIWINDOWLIST (SID_SFX_START + 610)
92 : #define SID_ADDONLIST (SID_SFX_START + 1677)
93 : #define SID_HELPMENU (SID_SFX_START + 410)
94 :
95 : #define SFX_REFERER_USER "private:user"
96 :
97 : #define aSlotNewDocDirect "slot:5537"
98 : #define aSlotAutoPilot "slot:6381"
99 :
100 : #define aSpecialFileMenu "file"
101 : #define aSpecialWindowMenu "window"
102 : #define aSlotSpecialFileMenu "slot:5510"
103 : #define aSlotSpecialWindowMenu "slot:5610"
104 : #define aSlotSpecialToolsMenu "slot:6677"
105 :
106 : // special uno commands for picklist and window list
107 : #define aSpecialFileCommand "PickList"
108 : #define aSpecialWindowCommand "WindowList"
109 :
110 : const char UNO_COMMAND[] = ".uno:";
111 :
112 0 : MenuManager::MenuManager(
113 : const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,
114 : REFERENCE< XFRAME >& rFrame, Menu* pMenu, sal_Bool bDelete, sal_Bool bDeleteChildren )
115 : :
116 0 : ThreadHelpBase( &Application::GetSolarMutex() ),
117 0 : mxServiceFactory(xServiceFactory)
118 : {
119 0 : m_bActive = sal_False;
120 0 : m_bDeleteMenu = bDelete;
121 0 : m_bDeleteChildren = bDeleteChildren;
122 0 : m_pVCLMenu = pMenu;
123 0 : m_xFrame = rFrame;
124 0 : m_bInitialized = sal_False;
125 0 : m_bIsBookmarkMenu = sal_False;
126 0 : acquire();
127 0 : const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
128 0 : m_bShowMenuImages = rSettings.GetUseImagesInMenus();
129 :
130 0 : sal_Int32 nAddonsURLPrefixLength = ADDONSPOPUPMENU_URL_PREFIX.getLength();
131 :
132 :
133 0 : sal_uInt16 nItemCount = pMenu->GetItemCount();
134 0 : m_aMenuItemHandlerVector.reserve(nItemCount);
135 0 : ::rtl::OUString aItemCommand;
136 0 : for ( sal_uInt16 i = 0; i < nItemCount; i++ )
137 : {
138 0 : sal_uInt16 nItemId = FillItemCommand(aItemCommand,pMenu, i );
139 0 : bool bShowMenuImages( m_bShowMenuImages );
140 :
141 : // overwrite the show icons on menu option?
142 0 : if (!bShowMenuImages)
143 : {
144 0 : MenuItemBits nBits = pMenu->GetItemBits( nItemId );
145 0 : bShowMenuImages = ( ( nBits & MIB_ICON ) == MIB_ICON );
146 : }
147 :
148 0 : PopupMenu* pPopupMenu = pMenu->GetPopupMenu( nItemId );
149 0 : if ( pPopupMenu )
150 : {
151 0 : AddMenu(pPopupMenu,aItemCommand,nItemId,bDeleteChildren,bDeleteChildren);
152 0 : if (! (( aItemCommand.getLength() > nAddonsURLPrefixLength ) &&
153 0 : ( aItemCommand.indexOf( ADDONSPOPUPMENU_URL_PREFIX ) == 0 )) )
154 : {
155 :
156 : // Create addon popup menu if there exist elements and this is the tools popup menu
157 0 : if ( ( nItemId == SID_ADDONLIST || aItemCommand == aSlotSpecialToolsMenu )
158 0 : && AddonMenuManager::HasAddonMenuElements() )
159 : {
160 0 : AddonMenu* pSubMenu = AddonMenuManager::CreateAddonMenu( rFrame );
161 0 : if ( pSubMenu && ( pSubMenu->GetItemCount() > 0 ))
162 : {
163 0 : sal_uInt16 nCount = 0;
164 0 : if ( pPopupMenu->GetItemType( nCount-1 ) != MENUITEM_SEPARATOR )
165 0 : pPopupMenu->InsertSeparator();
166 :
167 : // Use resource to load popup menu title
168 0 : String aAddonsStrRes = String( FwkResId( STR_MENU_ADDONS ));
169 0 : pPopupMenu->InsertItem( ITEMID_ADDONLIST, aAddonsStrRes );
170 0 : pPopupMenu->SetPopupMenu( ITEMID_ADDONLIST, pSubMenu );
171 :
172 : // Set item command for popup menu to enable it for GetImageFromURL
173 0 : const static ::rtl::OUString aSlotString( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
174 0 : aItemCommand = aSlotString;
175 0 : aItemCommand += ::rtl::OUString::valueOf( (sal_Int32)ITEMID_ADDONLIST );
176 0 : pPopupMenu->SetItemCommand( ITEMID_ADDONLIST, aItemCommand );
177 :
178 0 : AddMenu(pSubMenu,::rtl::OUString(),nItemId,sal_True,sal_False);
179 : // Set image for the addon popup menu item
180 0 : if ( bShowMenuImages && !pPopupMenu->GetItemImage( ITEMID_ADDONLIST ))
181 : {
182 0 : Image aImage = GetImageFromURL( rFrame, aItemCommand, false );
183 0 : if ( !!aImage )
184 0 : pPopupMenu->SetItemImage( ITEMID_ADDONLIST, aImage );
185 0 : }
186 : }
187 : else
188 0 : delete pSubMenu;
189 : }
190 : }
191 : }
192 : else
193 : {
194 0 : if ( nItemId == SID_NEWDOCDIRECT || aItemCommand == aSlotNewDocDirect )
195 : {
196 0 : MenuConfiguration aMenuCfg( getServiceFactory() );
197 0 : BmkMenu* pSubMenu = (BmkMenu*)aMenuCfg.CreateBookmarkMenu( rFrame, BOOKMARK_NEWMENU );
198 0 : pMenu->SetPopupMenu( nItemId, pSubMenu );
199 :
200 0 : AddMenu(pSubMenu,::rtl::OUString(),nItemId,sal_True,sal_False);
201 0 : if ( bShowMenuImages && !pMenu->GetItemImage( nItemId ))
202 : {
203 0 : Image aImage = GetImageFromURL( rFrame, aItemCommand, false );
204 0 : if ( !!aImage )
205 0 : pMenu->SetItemImage( nItemId, aImage );
206 0 : }
207 : }
208 0 : else if ( nItemId == SID_AUTOPILOTMENU || aItemCommand == aSlotAutoPilot )
209 : {
210 0 : MenuConfiguration aMenuCfg( getServiceFactory() );
211 0 : BmkMenu* pSubMenu = (BmkMenu*)aMenuCfg.CreateBookmarkMenu( rFrame, BOOKMARK_WIZARDMENU );
212 0 : pMenu->SetPopupMenu( nItemId, pSubMenu );
213 :
214 0 : AddMenu(pSubMenu,::rtl::OUString(),nItemId,sal_True,sal_False);
215 :
216 :
217 0 : if ( bShowMenuImages && !pMenu->GetItemImage( nItemId ))
218 : {
219 0 : Image aImage = GetImageFromURL( rFrame, aItemCommand, false );
220 0 : if ( !!aImage )
221 0 : pMenu->SetItemImage( nItemId, aImage );
222 0 : }
223 : }
224 0 : else if ( pMenu->GetItemType( i ) != MENUITEM_SEPARATOR )
225 : {
226 0 : if ( bShowMenuImages )
227 : {
228 0 : if ( AddonMenuManager::IsAddonMenuId( nItemId ))
229 : {
230 : // Add-Ons uses a images from different places
231 0 : Image aImage;
232 0 : rtl::OUString aImageId;
233 :
234 : MenuConfiguration::Attributes* pMenuAttributes =
235 0 : (MenuConfiguration::Attributes*)pMenu->GetUserValue( nItemId );
236 :
237 0 : if ( pMenuAttributes && !pMenuAttributes->aImageId.isEmpty() )
238 : {
239 : // Retrieve image id from menu attributes
240 0 : aImage = GetImageFromURL( rFrame, aImageId, false );
241 : }
242 :
243 0 : if ( !aImage )
244 : {
245 0 : aImage = GetImageFromURL( rFrame, aItemCommand, false );
246 0 : if ( !aImage )
247 0 : aImage = AddonsOptions().GetImageFromURL( aItemCommand, false );
248 : }
249 :
250 0 : if ( !!aImage )
251 0 : pMenu->SetItemImage( nItemId, aImage );
252 : }
253 0 : else if ( !pMenu->GetItemImage( nItemId ))
254 : {
255 0 : Image aImage = GetImageFromURL( rFrame, aItemCommand, false );
256 0 : if ( !!aImage )
257 0 : pMenu->SetItemImage( nItemId, aImage );
258 : }
259 : }
260 :
261 0 : REFERENCE< XDISPATCH > aXDispatchRef;
262 0 : m_aMenuItemHandlerVector.push_back( new MenuItemHandler( nItemId, NULL, aXDispatchRef ));
263 :
264 : }
265 : }
266 : }
267 :
268 : // retrieve label information for all menu items without item text
269 :
270 0 : SetHdl();
271 0 : }
272 :
273 :
274 0 : void MenuManager::SetHdl()
275 : {
276 0 : m_pVCLMenu->SetHighlightHdl( LINK( this, MenuManager, Highlight ));
277 0 : m_pVCLMenu->SetActivateHdl( LINK( this, MenuManager, Activate ));
278 0 : m_pVCLMenu->SetDeactivateHdl( LINK( this, MenuManager, Deactivate ));
279 0 : m_pVCLMenu->SetSelectHdl( LINK( this, MenuManager, Select ));
280 :
281 0 : if ( mxServiceFactory.is() )
282 0 : m_xURLTransformer.set( URLTransformer::create(::comphelper::getComponentContext(mxServiceFactory)) );
283 0 : }
284 :
285 0 : MenuManager::~MenuManager()
286 : {
287 0 : std::vector< MenuItemHandler* >::iterator p;
288 0 : for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
289 : {
290 0 : MenuItemHandler* pItemHandler = *p;
291 0 : pItemHandler->xMenuItemDispatch.clear();
292 0 : if ( pItemHandler->pSubMenuManager )
293 0 : (static_cast< ::com::sun::star::uno::XInterface* >((OWeakObject*)pItemHandler->pSubMenuManager))->release();
294 0 : delete pItemHandler;
295 : }
296 :
297 0 : if ( m_bDeleteMenu )
298 0 : delete m_pVCLMenu;
299 0 : }
300 :
301 :
302 0 : MenuManager::MenuItemHandler* MenuManager::GetMenuItemHandler( sal_uInt16 nItemId )
303 : {
304 0 : ResetableGuard aGuard( m_aLock );
305 :
306 0 : std::vector< MenuItemHandler* >::iterator p;
307 0 : for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
308 : {
309 0 : MenuItemHandler* pItemHandler = *p;
310 0 : if ( pItemHandler->nItemId == nItemId )
311 0 : return pItemHandler;
312 : }
313 :
314 0 : return 0;
315 : }
316 :
317 :
318 0 : void SAL_CALL MenuManager::statusChanged( const FEATURSTATEEVENT& Event )
319 : throw ( RuntimeException )
320 : {
321 0 : ::rtl::OUString aFeatureURL = Event.FeatureURL.Complete;
322 0 : MenuItemHandler* pStatusChangedMenu = NULL;
323 :
324 : {
325 0 : ResetableGuard aGuard( m_aLock );
326 :
327 0 : std::vector< MenuItemHandler* >::iterator p;
328 0 : for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
329 : {
330 0 : MenuItemHandler* pMenuItemHandler = *p;
331 0 : if ( pMenuItemHandler->aMenuItemURL == aFeatureURL )
332 : {
333 0 : pStatusChangedMenu = pMenuItemHandler;
334 0 : break;
335 : }
336 0 : }
337 : }
338 :
339 0 : if ( pStatusChangedMenu )
340 : {
341 0 : SolarMutexGuard aSolarGuard;
342 : {
343 0 : ResetableGuard aGuard( m_aLock );
344 :
345 0 : sal_Bool bSetCheckmark = sal_False;
346 0 : sal_Bool bCheckmark = sal_False;
347 0 : sal_Bool bMenuItemEnabled = m_pVCLMenu->IsItemEnabled( pStatusChangedMenu->nItemId );
348 :
349 0 : if ( Event.IsEnabled != bMenuItemEnabled )
350 0 : m_pVCLMenu->EnableItem( pStatusChangedMenu->nItemId, Event.IsEnabled );
351 :
352 0 : if ( Event.State >>= bCheckmark )
353 0 : bSetCheckmark = sal_True;
354 :
355 0 : if ( bSetCheckmark )
356 0 : m_pVCLMenu->CheckItem( pStatusChangedMenu->nItemId, bCheckmark );
357 : }
358 :
359 0 : if ( Event.Requery )
360 : {
361 0 : URL aTargetURL;
362 0 : aTargetURL.Complete = pStatusChangedMenu->aMenuItemURL;
363 :
364 0 : m_xURLTransformer->parseStrict( aTargetURL );
365 :
366 0 : REFERENCE< XDISPATCHPROVIDER > xDispatchProvider( m_xFrame, UNO_QUERY );
367 0 : REFERENCE< XDISPATCH > xMenuItemDispatch = xDispatchProvider->queryDispatch(
368 0 : aTargetURL, ::rtl::OUString(), 0 );
369 :
370 0 : if ( xMenuItemDispatch.is() )
371 : {
372 0 : pStatusChangedMenu->xMenuItemDispatch = xMenuItemDispatch;
373 0 : pStatusChangedMenu->aMenuItemURL = aTargetURL.Complete;
374 0 : xMenuItemDispatch->addStatusListener( (static_cast< XSTATUSLISTENER* >(this)), aTargetURL );
375 0 : }
376 0 : }
377 0 : }
378 0 : }
379 :
380 :
381 0 : void MenuManager::RemoveListener()
382 : {
383 0 : ResetableGuard aGuard( m_aLock );
384 0 : ClearMenuDispatch();
385 0 : }
386 :
387 0 : void MenuManager::ClearMenuDispatch(const EVENTOBJECT& Source,bool _bRemoveOnly)
388 : {
389 : // disposing called from parent dispatcher
390 : // remove all listener to prepare shutdown
391 :
392 0 : std::vector< MenuItemHandler* >::iterator p;
393 0 : for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
394 : {
395 0 : MenuItemHandler* pItemHandler = *p;
396 0 : if ( pItemHandler->xMenuItemDispatch.is() )
397 : {
398 0 : URL aTargetURL;
399 0 : aTargetURL.Complete = pItemHandler->aMenuItemURL;
400 0 : m_xURLTransformer->parseStrict( aTargetURL );
401 :
402 0 : pItemHandler->xMenuItemDispatch->removeStatusListener(
403 0 : (static_cast< XSTATUSLISTENER* >(this)), aTargetURL );
404 : }
405 :
406 0 : pItemHandler->xMenuItemDispatch.clear();
407 0 : if ( pItemHandler->pSubMenuManager )
408 : {
409 0 : if ( _bRemoveOnly )
410 0 : pItemHandler->pSubMenuManager->RemoveListener();
411 : else
412 0 : pItemHandler->pSubMenuManager->disposing( Source );
413 : }
414 : }
415 0 : }
416 :
417 :
418 0 : void SAL_CALL MenuManager::disposing( const EVENTOBJECT& Source ) throw ( RUNTIMEEXCEPTION )
419 : {
420 0 : if ( Source.Source == m_xFrame )
421 : {
422 0 : ResetableGuard aGuard( m_aLock );
423 0 : ClearMenuDispatch(Source,false);
424 : }
425 : else
426 : {
427 : // disposing called from menu item dispatcher, remove listener
428 0 : MenuItemHandler* pMenuItemDisposing = NULL;
429 :
430 : {
431 0 : ResetableGuard aGuard( m_aLock );
432 :
433 0 : std::vector< MenuItemHandler* >::iterator p;
434 0 : for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
435 : {
436 0 : MenuItemHandler* pMenuItemHandler = *p;
437 0 : if ( pMenuItemHandler->xMenuItemDispatch == Source.Source )
438 : {
439 0 : pMenuItemDisposing = pMenuItemHandler;
440 0 : break;
441 : }
442 : }
443 :
444 0 : if ( pMenuItemDisposing )
445 : {
446 0 : URL aTargetURL;
447 0 : aTargetURL.Complete = pMenuItemDisposing->aMenuItemURL;
448 :
449 0 : m_xURLTransformer->parseStrict( aTargetURL );
450 :
451 0 : pMenuItemDisposing->xMenuItemDispatch->removeStatusListener((static_cast< XSTATUSLISTENER* >(this)), aTargetURL );
452 0 : pMenuItemDisposing->xMenuItemDispatch.clear();
453 0 : }
454 : }
455 : }
456 0 : }
457 :
458 :
459 0 : void MenuManager::UpdateSpecialFileMenu( Menu* pMenu )
460 : {
461 : // update picklist
462 0 : Sequence< Sequence< PropertyValue > > aHistoryList = SvtHistoryOptions().GetList( ePICKLIST );
463 0 : ::std::vector< MenuItemHandler* > aNewPickVector;
464 0 : Reference< XStringWidth > xStringLength( new StringLength );
465 :
466 0 : sal_uInt16 nPickItemId = START_ITEMID_PICKLIST;
467 0 : int nPickListMenuItems = ( aHistoryList.getLength() > 99 ) ? 99 : aHistoryList.getLength();
468 :
469 0 : aNewPickVector.reserve(nPickListMenuItems);
470 0 : for ( int i = 0; i < nPickListMenuItems; i++ )
471 : {
472 0 : Sequence< PropertyValue > aPickListEntry = aHistoryList[i];
473 :
474 0 : REFERENCE< XDISPATCH > aXDispatchRef;
475 : MenuItemHandler* pNewMenuItemHandler = new MenuItemHandler(
476 : nPickItemId++,
477 : NULL,
478 0 : aXDispatchRef );
479 :
480 0 : for ( int j = 0; j < aPickListEntry.getLength(); j++ )
481 : {
482 0 : Any a = aPickListEntry[j].Value;
483 :
484 0 : if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_URL )
485 0 : a >>= pNewMenuItemHandler->aMenuItemURL;
486 0 : else if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_FILTER )
487 0 : a >>= pNewMenuItemHandler->aFilter;
488 0 : else if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_TITLE )
489 0 : a >>= pNewMenuItemHandler->aTitle;
490 0 : else if ( aPickListEntry[j].Name == HISTORY_PROPERTYNAME_PASSWORD )
491 0 : a >>= pNewMenuItemHandler->aPassword;
492 0 : }
493 :
494 0 : aNewPickVector.push_back( pNewMenuItemHandler );
495 0 : }
496 :
497 0 : if ( !aNewPickVector.empty() )
498 : {
499 0 : URL aTargetURL;
500 0 : REFERENCE< XDISPATCHPROVIDER > xDispatchProvider( m_xFrame, UNO_QUERY );
501 :
502 0 : REFERENCE< XDISPATCH > xMenuItemDispatch;
503 :
504 0 : static const ::rtl::OUString s_sDefault(RTL_CONSTASCII_USTRINGPARAM("_default"));
505 : // query for dispatcher
506 0 : std::vector< MenuItemHandler* >::iterator p;
507 0 : for ( p = aNewPickVector.begin(); p != aNewPickVector.end(); ++p )
508 : {
509 0 : MenuItemHandler* pMenuItemHandler = *p;
510 :
511 0 : aTargetURL.Complete = pMenuItemHandler->aMenuItemURL;
512 0 : m_xURLTransformer->parseStrict( aTargetURL );
513 :
514 0 : if ( !xMenuItemDispatch.is() )
515 : {
516 : // attention: this code assume that "_blank" can only be consumed by desktop service
517 0 : xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, s_sDefault, 0 );
518 : }
519 :
520 0 : if ( xMenuItemDispatch.is() )
521 : {
522 0 : pMenuItemHandler->xMenuItemDispatch = xMenuItemDispatch;
523 0 : pMenuItemHandler->aMenuItemURL = aTargetURL.Complete;
524 : }
525 : }
526 :
527 : {
528 0 : ResetableGuard aGuard( m_aLock );
529 :
530 0 : int nRemoveItemCount = 0;
531 0 : int nItemCount = pMenu->GetItemCount();
532 :
533 0 : if ( nItemCount > 0 )
534 : {
535 : // remove all old picklist entries from menu
536 0 : sal_uInt16 nPos = pMenu->GetItemPos( START_ITEMID_PICKLIST );
537 0 : for ( sal_uInt16 n = nPos; n < pMenu->GetItemCount(); )
538 : {
539 0 : pMenu->RemoveItem( n );
540 0 : ++nRemoveItemCount;
541 : }
542 :
543 0 : if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MENUITEM_SEPARATOR )
544 0 : pMenu->RemoveItem( pMenu->GetItemCount()-1 );
545 :
546 : // remove all old picklist entries from menu handler
547 0 : if ( nRemoveItemCount > 0 )
548 : {
549 0 : for( sal_uInt32 nIndex = m_aMenuItemHandlerVector.size() - nRemoveItemCount;
550 0 : nIndex < m_aMenuItemHandlerVector.size(); )
551 : {
552 0 : delete m_aMenuItemHandlerVector.at( nIndex );
553 0 : m_aMenuItemHandlerVector.erase( m_aMenuItemHandlerVector.begin() + nIndex );
554 : }
555 : }
556 : }
557 :
558 : // append new picklist menu entries
559 0 : aNewPickVector.reserve(aNewPickVector.size());
560 0 : pMenu->InsertSeparator();
561 0 : const sal_uInt32 nCount = aNewPickVector.size();
562 0 : for ( sal_uInt32 i = 0; i < nCount; i++ )
563 : {
564 0 : char menuShortCut[5] = "~n: ";
565 :
566 0 : ::rtl::OUString aMenuShortCut;
567 0 : if ( i <= 9 )
568 : {
569 0 : if ( i == 9 )
570 0 : aMenuShortCut = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "1~0: " ));
571 : else
572 : {
573 0 : menuShortCut[1] = (char)( '1' + i );
574 0 : aMenuShortCut = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( menuShortCut ));
575 : }
576 : }
577 : else
578 : {
579 0 : aMenuShortCut = rtl::OUString::valueOf((sal_Int32)( i + 1 ));
580 0 : aMenuShortCut += rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ": " ));
581 : }
582 :
583 : // Abbreviate URL
584 0 : rtl::OUString aURLString( aNewPickVector.at( i )->aMenuItemURL );
585 0 : rtl::OUString aTipHelpText;
586 0 : rtl::OUString aMenuTitle;
587 0 : INetURLObject aURL( aURLString );
588 :
589 0 : if ( aURL.GetProtocol() == INET_PROT_FILE )
590 : {
591 : // Do handle file URL differently => convert it to a system
592 : // path and abbreviate it with a special function:
593 0 : String aFileSystemPath( aURL.getFSysPath( INetURLObject::FSYS_DETECT ) );
594 :
595 0 : ::rtl::OUString aSystemPath( aFileSystemPath );
596 0 : ::rtl::OUString aCompactedSystemPath;
597 :
598 0 : aTipHelpText = aSystemPath;
599 0 : oslFileError nError = osl_abbreviateSystemPath( aSystemPath.pData, &aCompactedSystemPath.pData, 46, NULL );
600 0 : if ( !nError )
601 0 : aMenuTitle = String( aCompactedSystemPath );
602 : else
603 0 : aMenuTitle = aSystemPath;
604 : }
605 : else
606 : {
607 : // Use INetURLObject to abbreviate all other URLs
608 0 : String aShortURL;
609 0 : aShortURL = aURL.getAbbreviated( xStringLength, 46, INetURLObject::DECODE_UNAMBIGUOUS );
610 0 : aMenuTitle += aShortURL;
611 0 : aTipHelpText = aURLString;
612 : }
613 :
614 0 : ::rtl::OUString aTitle( aMenuShortCut + aMenuTitle );
615 :
616 0 : MenuItemHandler* pMenuItemHandler = aNewPickVector.at( i );
617 0 : pMenu->InsertItem( pMenuItemHandler->nItemId, aTitle );
618 0 : pMenu->SetTipHelpText( pMenuItemHandler->nItemId, aTipHelpText );
619 0 : m_aMenuItemHandlerVector.push_back( pMenuItemHandler );
620 0 : }
621 0 : }
622 0 : }
623 0 : }
624 :
625 0 : void MenuManager::UpdateSpecialWindowMenu( Menu* pMenu,const Reference< XMultiServiceFactory >& xServiceFactory,framework::IMutex& _rMutex )
626 : {
627 : // update window list
628 0 : ::std::vector< ::rtl::OUString > aNewWindowListVector;
629 :
630 0 : Reference< XDesktop > xDesktop( xServiceFactory->createInstance( SERVICENAME_DESKTOP ), UNO_QUERY );
631 :
632 0 : sal_uInt16 nActiveItemId = 0;
633 0 : sal_uInt16 nItemId = START_ITEMID_WINDOWLIST;
634 :
635 0 : if ( xDesktop.is() )
636 : {
637 0 : Reference< XFramesSupplier > xTasksSupplier( xDesktop, UNO_QUERY );
638 0 : Reference< XFrame > xCurrentFrame = xDesktop->getCurrentFrame();
639 0 : Reference< XIndexAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY );
640 0 : sal_Int32 nCount = xList->getCount();
641 0 : aNewWindowListVector.reserve(nCount);
642 0 : for (sal_Int32 i=0; i<nCount; ++i )
643 : {
644 0 : Reference< XFrame > xFrame;
645 0 : xList->getByIndex(i) >>= xFrame;
646 :
647 0 : if (xFrame.is())
648 : {
649 0 : if ( xFrame == xCurrentFrame )
650 0 : nActiveItemId = nItemId;
651 :
652 0 : Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
653 0 : if ( pWin && pWin->IsVisible() )
654 : {
655 0 : aNewWindowListVector.push_back( pWin->GetText() );
656 0 : ++nItemId;
657 : }
658 : }
659 0 : }
660 : }
661 :
662 : {
663 0 : ResetableGuard aGuard( _rMutex );
664 :
665 0 : int nItemCount = pMenu->GetItemCount();
666 :
667 0 : if ( nItemCount > 0 )
668 : {
669 : // remove all old window list entries from menu
670 0 : sal_uInt16 nPos = pMenu->GetItemPos( START_ITEMID_WINDOWLIST );
671 0 : for ( sal_uInt16 n = nPos; n < pMenu->GetItemCount(); )
672 0 : pMenu->RemoveItem( n );
673 :
674 0 : if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MENUITEM_SEPARATOR )
675 0 : pMenu->RemoveItem( pMenu->GetItemCount()-1 );
676 : }
677 :
678 0 : if ( !aNewWindowListVector.empty() )
679 : {
680 : // append new window list entries to menu
681 0 : pMenu->InsertSeparator();
682 0 : nItemId = START_ITEMID_WINDOWLIST;
683 0 : const sal_uInt32 nCount = aNewWindowListVector.size();
684 0 : for ( sal_uInt32 i = 0; i < nCount; i++ )
685 : {
686 0 : pMenu->InsertItem( nItemId, aNewWindowListVector.at( i ), MIB_RADIOCHECK );
687 0 : if ( nItemId == nActiveItemId )
688 0 : pMenu->CheckItem( nItemId );
689 0 : ++nItemId;
690 : }
691 0 : }
692 0 : }
693 0 : }
694 :
695 :
696 0 : void MenuManager::CreatePicklistArguments( Sequence< PropertyValue >& aArgsList, const MenuItemHandler* pMenuItemHandler )
697 : {
698 0 : int NUM_OF_PICKLIST_ARGS = 3;
699 :
700 0 : Any a;
701 0 : aArgsList.realloc( NUM_OF_PICKLIST_ARGS );
702 :
703 0 : aArgsList[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FileName" ));
704 0 : a <<= pMenuItemHandler->aMenuItemURL;
705 0 : aArgsList[0].Value = a;
706 :
707 0 : aArgsList[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Referer" ));
708 0 : a <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SFX_REFERER_USER ));
709 0 : aArgsList[1].Value = a;
710 :
711 0 : ::rtl::OUString aFilter( pMenuItemHandler->aFilter );
712 :
713 0 : sal_Int32 nPos = aFilter.indexOf( '|' );
714 0 : if ( nPos >= 0 )
715 : {
716 0 : ::rtl::OUString aFilterOptions;
717 :
718 0 : if ( nPos < ( aFilter.getLength() - 1 ) )
719 0 : aFilterOptions = aFilter.copy( nPos+1 );
720 :
721 0 : aArgsList[2].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterOptions" ));
722 0 : a <<= aFilterOptions;
723 0 : aArgsList[2].Value = a;
724 :
725 0 : aFilter = aFilter.copy( 0, nPos-1 );
726 0 : aArgsList.realloc( ++NUM_OF_PICKLIST_ARGS );
727 : }
728 :
729 0 : aArgsList[NUM_OF_PICKLIST_ARGS-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ));
730 0 : a <<= aFilter;
731 0 : aArgsList[NUM_OF_PICKLIST_ARGS-1].Value = a;
732 0 : }
733 :
734 :
735 : //_________________________________________________________________________________________________________________
736 : // vcl handler
737 : //_________________________________________________________________________________________________________________
738 :
739 0 : IMPL_LINK( MenuManager, Activate, Menu *, pMenu )
740 : {
741 0 : if ( pMenu == m_pVCLMenu )
742 : {
743 : // set/unset hiding disabled menu entries
744 0 : sal_Bool bDontHide = SvtMenuOptions().IsEntryHidingEnabled();
745 0 : const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
746 0 : sal_Bool bShowMenuImages = rSettings.GetUseImagesInMenus();
747 :
748 0 : sal_uInt16 nFlag = pMenu->GetMenuFlags();
749 0 : if ( bDontHide )
750 0 : nFlag &= ~MENU_FLAG_HIDEDISABLEDENTRIES;
751 : else
752 0 : nFlag |= MENU_FLAG_HIDEDISABLEDENTRIES;
753 0 : pMenu->SetMenuFlags( nFlag );
754 :
755 0 : if ( m_bActive )
756 0 : return 0;
757 :
758 0 : m_bActive = sal_True;
759 :
760 0 : ::rtl::OUString aCommand( m_aMenuItemCommand );
761 0 : if (m_aMenuItemCommand.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM(UNO_COMMAND)))
762 : {
763 : // Remove protocol part from command so we can use an easier comparision method
764 0 : aCommand = aCommand.copy(RTL_CONSTASCII_LENGTH(UNO_COMMAND));
765 : }
766 :
767 0 : if ( m_aMenuItemCommand == aSpecialFileMenu || m_aMenuItemCommand == aSlotSpecialFileMenu || aCommand == aSpecialFileCommand )
768 0 : UpdateSpecialFileMenu( pMenu );
769 0 : else if ( m_aMenuItemCommand == aSpecialWindowMenu || m_aMenuItemCommand == aSlotSpecialWindowMenu || aCommand == aSpecialWindowCommand )
770 0 : UpdateSpecialWindowMenu( pMenu, getServiceFactory(), m_aLock );
771 :
772 : // Check if some modes have changed so we have to update our menu images
773 0 : if ( bShowMenuImages != m_bShowMenuImages )
774 : {
775 : // The mode changed so we have to replace all images
776 0 : m_bShowMenuImages = bShowMenuImages;
777 0 : FillMenuImages( m_xFrame, pMenu, bShowMenuImages );
778 : }
779 :
780 0 : if ( m_bInitialized )
781 0 : return 0;
782 : else
783 : {
784 0 : URL aTargetURL;
785 :
786 0 : ResetableGuard aGuard( m_aLock );
787 :
788 0 : REFERENCE< XDISPATCHPROVIDER > xDispatchProvider( m_xFrame, UNO_QUERY );
789 0 : if ( xDispatchProvider.is() )
790 : {
791 0 : std::vector< MenuItemHandler* >::iterator p;
792 0 : for ( p = m_aMenuItemHandlerVector.begin(); p != m_aMenuItemHandlerVector.end(); ++p )
793 : {
794 0 : MenuItemHandler* pMenuItemHandler = *p;
795 0 : if ( pMenuItemHandler &&
796 : pMenuItemHandler->pSubMenuManager == 0 &&
797 0 : !pMenuItemHandler->xMenuItemDispatch.is() )
798 : {
799 : // There is no dispatch mechanism for the special window list menu items,
800 : // because they are handled directly through XFrame->activate!!!
801 0 : if ( pMenuItemHandler->nItemId < START_ITEMID_WINDOWLIST ||
802 : pMenuItemHandler->nItemId > END_ITEMID_WINDOWLIST )
803 : {
804 0 : ::rtl::OUString aItemCommand = pMenu->GetItemCommand( pMenuItemHandler->nItemId );
805 0 : if ( aItemCommand.isEmpty() )
806 : {
807 0 : const static ::rtl::OUString aSlotString( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
808 0 : aItemCommand = aSlotString;
809 0 : aItemCommand += ::rtl::OUString::valueOf( (sal_Int32)pMenuItemHandler->nItemId );
810 0 : pMenu->SetItemCommand( pMenuItemHandler->nItemId, aItemCommand );
811 : }
812 :
813 0 : aTargetURL.Complete = aItemCommand;
814 :
815 0 : m_xURLTransformer->parseStrict( aTargetURL );
816 :
817 0 : REFERENCE< XDISPATCH > xMenuItemDispatch;
818 0 : if ( m_bIsBookmarkMenu )
819 0 : xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, pMenuItemHandler->aTargetFrame, 0 );
820 : else
821 0 : xMenuItemDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
822 :
823 0 : if ( xMenuItemDispatch.is() )
824 : {
825 0 : pMenuItemHandler->xMenuItemDispatch = xMenuItemDispatch;
826 0 : pMenuItemHandler->aMenuItemURL = aTargetURL.Complete;
827 0 : xMenuItemDispatch->addStatusListener( (static_cast< XSTATUSLISTENER* >(this)), aTargetURL );
828 : }
829 : else
830 0 : pMenu->EnableItem( pMenuItemHandler->nItemId, sal_False );
831 : }
832 : }
833 : }
834 0 : }
835 0 : }
836 : }
837 :
838 0 : return 1;
839 : }
840 :
841 :
842 0 : IMPL_LINK( MenuManager, Deactivate, Menu *, pMenu )
843 : {
844 0 : if ( pMenu == m_pVCLMenu )
845 0 : m_bActive = sal_False;
846 :
847 0 : return 1;
848 : }
849 :
850 :
851 0 : IMPL_LINK( MenuManager, Select, Menu *, pMenu )
852 : {
853 0 : URL aTargetURL;
854 0 : Sequence<PropertyValue> aArgs;
855 0 : REFERENCE< XDISPATCH > xDispatch;
856 :
857 : {
858 0 : ResetableGuard aGuard( m_aLock );
859 :
860 0 : sal_uInt16 nCurItemId = pMenu->GetCurItemId();
861 0 : if ( pMenu == m_pVCLMenu &&
862 0 : pMenu->GetItemType( nCurItemId ) != MENUITEM_SEPARATOR )
863 : {
864 0 : if ( nCurItemId >= START_ITEMID_WINDOWLIST &&
865 : nCurItemId <= END_ITEMID_WINDOWLIST )
866 : {
867 : // window list menu item selected
868 :
869 0 : Reference< XFramesSupplier > xDesktop( getServiceFactory()->createInstance( SERVICENAME_DESKTOP ), UNO_QUERY );
870 :
871 0 : if ( xDesktop.is() )
872 : {
873 0 : sal_uInt16 nTaskId = START_ITEMID_WINDOWLIST;
874 0 : Reference< XIndexAccess > xList( xDesktop->getFrames(), UNO_QUERY );
875 0 : sal_Int32 nCount = xList->getCount();
876 0 : for ( sal_Int32 i=0; i<nCount; ++i )
877 : {
878 0 : Reference< XFrame > xFrame;
879 0 : xList->getByIndex(i) >>= xFrame;
880 :
881 0 : if ( xFrame.is() && nTaskId == nCurItemId )
882 : {
883 0 : Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
884 0 : pWin->GrabFocus();
885 0 : pWin->ToTop( TOTOP_RESTOREWHENMIN );
886 : break;
887 : }
888 :
889 0 : nTaskId++;
890 0 : }
891 0 : }
892 : }
893 : else
894 : {
895 0 : MenuItemHandler* pMenuItemHandler = GetMenuItemHandler( nCurItemId );
896 0 : if ( pMenuItemHandler && pMenuItemHandler->xMenuItemDispatch.is() )
897 : {
898 0 : aTargetURL.Complete = pMenuItemHandler->aMenuItemURL;
899 0 : m_xURLTransformer->parseStrict( aTargetURL );
900 :
901 0 : if ( nCurItemId >= START_ITEMID_PICKLIST &&
902 : nCurItemId < START_ITEMID_WINDOWLIST )
903 : {
904 : // picklist menu item selected
905 0 : CreatePicklistArguments( aArgs, pMenuItemHandler );
906 : }
907 0 : else if ( m_bIsBookmarkMenu )
908 : {
909 : // bookmark menu item selected
910 0 : aArgs.realloc( 1 );
911 0 : aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Referer" ));
912 0 : aArgs[0].Value <<= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SFX_REFERER_USER ));
913 : }
914 :
915 0 : xDispatch = pMenuItemHandler->xMenuItemDispatch;
916 : }
917 : }
918 0 : }
919 : }
920 :
921 0 : if ( xDispatch.is() )
922 0 : xDispatch->dispatch( aTargetURL, aArgs );
923 :
924 0 : return 1;
925 : }
926 :
927 :
928 0 : IMPL_LINK_NOARG(MenuManager, Highlight)
929 : {
930 0 : return 0;
931 : }
932 :
933 0 : const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& MenuManager::getServiceFactory()
934 : {
935 0 : return mxServiceFactory;
936 : }
937 :
938 0 : void MenuManager::AddMenu(PopupMenu* _pPopupMenu,const ::rtl::OUString& _sItemCommand,sal_uInt16 _nItemId,sal_Bool _bDelete,sal_Bool _bDeleteChildren)
939 : {
940 0 : MenuManager* pSubMenuManager = new MenuManager( getServiceFactory(), m_xFrame, _pPopupMenu, _bDelete, _bDeleteChildren );
941 :
942 : // store menu item command as we later have to know which menu is active (see Activate handler)
943 0 : pSubMenuManager->m_aMenuItemCommand = _sItemCommand;
944 :
945 0 : REFERENCE< XDISPATCH > aXDispatchRef;
946 : MenuItemHandler* pMenuItemHandler = new MenuItemHandler(
947 : _nItemId,
948 : pSubMenuManager,
949 0 : aXDispatchRef );
950 0 : m_aMenuItemHandlerVector.push_back( pMenuItemHandler );
951 0 : }
952 :
953 0 : sal_uInt16 MenuManager::FillItemCommand(::rtl::OUString& _rItemCommand, Menu* _pMenu,sal_uInt16 _nIndex) const
954 : {
955 0 : sal_uInt16 nItemId = _pMenu->GetItemId( _nIndex );
956 :
957 0 : _rItemCommand = _pMenu->GetItemCommand( nItemId );
958 0 : if ( _rItemCommand.isEmpty() )
959 : {
960 0 : const static ::rtl::OUString aSlotString( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
961 0 : _rItemCommand = aSlotString;
962 0 : _rItemCommand += ::rtl::OUString::valueOf( (sal_Int32)nItemId );
963 0 : _pMenu->SetItemCommand( nItemId, _rItemCommand );
964 : }
965 0 : return nItemId;
966 : }
967 0 : void MenuManager::FillMenuImages(Reference< XFrame >& _xFrame, Menu* _pMenu,sal_Bool bShowMenuImages)
968 : {
969 0 : AddonsOptions aAddonOptions;
970 :
971 0 : for ( sal_uInt16 nPos = 0; nPos < _pMenu->GetItemCount(); nPos++ )
972 : {
973 0 : sal_uInt16 nId = _pMenu->GetItemId( nPos );
974 0 : if ( _pMenu->GetItemType( nPos ) != MENUITEM_SEPARATOR )
975 : {
976 0 : bool bTmpShowMenuImages( bShowMenuImages );
977 : // overwrite the show icons on menu option?
978 0 : if (!bTmpShowMenuImages)
979 : {
980 0 : MenuItemBits nBits = _pMenu->GetItemBits( nId );
981 0 : bTmpShowMenuImages = ( ( nBits & MIB_ICON ) == MIB_ICON );
982 : }
983 :
984 0 : if ( bTmpShowMenuImages )
985 : {
986 0 : sal_Bool bImageSet = sal_False;
987 0 : ::rtl::OUString aImageId;
988 :
989 : ::framework::MenuConfiguration::Attributes* pMenuAttributes =
990 0 : (::framework::MenuConfiguration::Attributes*)_pMenu->GetUserValue( nId );
991 :
992 0 : if ( pMenuAttributes )
993 0 : aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes
994 :
995 0 : if ( !aImageId.isEmpty() )
996 : {
997 0 : Image aImage = GetImageFromURL( _xFrame, aImageId, false );
998 0 : if ( !!aImage )
999 : {
1000 0 : bImageSet = sal_True;
1001 0 : _pMenu->SetItemImage( nId, aImage );
1002 0 : }
1003 : }
1004 :
1005 0 : if ( !bImageSet )
1006 : {
1007 0 : rtl::OUString aMenuItemCommand = _pMenu->GetItemCommand( nId );
1008 0 : Image aImage = GetImageFromURL( _xFrame, aMenuItemCommand, false );
1009 0 : if ( !aImage )
1010 0 : aImage = aAddonOptions.GetImageFromURL( aMenuItemCommand, false );
1011 :
1012 0 : _pMenu->SetItemImage( nId, aImage );
1013 0 : }
1014 : }
1015 : else
1016 0 : _pMenu->SetItemImage( nId, Image() );
1017 : }
1018 0 : }
1019 0 : }
1020 : }
1021 :
1022 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|