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 :
21 : #include <sot/factory.hxx>
22 : #include <svtools/menuoptions.hxx>
23 : #include <svtools/imagemgr.hxx>
24 : #include <svl/imageitm.hxx>
25 : #include <com/sun/star/container/XEnumeration.hpp>
26 : #include <com/sun/star/frame/Desktop.hpp>
27 : #include <com/sun/star/frame/XFramesSupplier.hpp>
28 : #include <comphelper/processfactory.hxx>
29 : #include <toolkit/helper/vclunohelper.hxx>
30 :
31 : #include "virtmenu.hxx"
32 : #include <sfx2/msgpool.hxx>
33 : #include "statcach.hxx"
34 : #include <sfx2/msg.hxx>
35 : #include "idpool.hxx"
36 : #include <sfx2/mnuitem.hxx>
37 : #include <sfx2/mnumgr.hxx>
38 : #include <sfx2/bindings.hxx>
39 : #include <sfx2/dispatch.hxx>
40 : #include <sfx2/app.hxx>
41 : #include "sfxtypes.hxx"
42 : #include "arrdecl.hxx"
43 : #include <sfx2/sfx.hrc>
44 : #include <sfx2/viewsh.hxx>
45 : #include "sfxpicklist.hxx"
46 : #include <sfx2/sfxresid.hxx>
47 : #include "menu.hrc"
48 : #include <sfx2/imagemgr.hxx>
49 : #include <sfx2/viewfrm.hxx>
50 : #include <sfx2/objsh.hxx>
51 : #include <framework/addonsoptions.hxx>
52 :
53 : #include <framework/addonmenu.hxx>
54 : #include <framework/menuconfiguration.hxx>
55 : #include <vcl/settings.hxx>
56 :
57 : using namespace ::com::sun::star::container;
58 : using namespace ::com::sun::star::frame;
59 : using namespace ::com::sun::star::uno;
60 :
61 0 : class SfxMenuImageControl_Impl : public SfxControllerItem
62 : {
63 : SfxVirtualMenu* pMenu;
64 : long lRotation;
65 : bool bIsMirrored;
66 :
67 : protected:
68 : virtual void StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState ) SAL_OVERRIDE;
69 : public:
70 0 : SfxMenuImageControl_Impl( sal_uInt16 nSlotId, SfxBindings& rBindings, SfxVirtualMenu* pVMenu )
71 : : SfxControllerItem( nSlotId, rBindings )
72 : , pMenu( pVMenu )
73 : , lRotation( 0 )
74 0 : , bIsMirrored( false )
75 0 : {}
76 : void Update();
77 : };
78 :
79 0 : void SfxMenuImageControl_Impl::StateChanged( sal_uInt16 /*nSID*/, SfxItemState /*eState*/, const SfxPoolItem* pState )
80 : {
81 0 : const SfxImageItem* pItem = PTR_CAST( SfxImageItem, pState );
82 0 : if ( pItem )
83 : {
84 0 : lRotation = pItem->GetRotation();
85 0 : bIsMirrored = pItem->IsMirrored();
86 0 : Update();
87 : }
88 0 : }
89 :
90 0 : void SfxMenuImageControl_Impl::Update()
91 : {
92 0 : SfxViewFrame* pViewFrame = GetBindings().GetDispatcher_Impl()->GetFrame();
93 0 : SfxModule* pModule = pViewFrame->GetObjectShell()->GetModule();
94 0 : SfxSlotPool* pPool = pModule->GetSlotPool();
95 0 : Menu* pSVMenu = pMenu->GetSVMenu();
96 0 : for (sal_uInt16 nPos = 0; nPos<pSVMenu->GetItemCount(); nPos++)
97 : {
98 0 : sal_uInt16 nslotId = pSVMenu->GetItemId( nPos );
99 0 : const SfxSlot* pSlot = pPool->GetSlot( nslotId );
100 0 : if ( pSlot && pSlot->IsMode( SFX_SLOT_IMAGEROTATION ) )
101 : {
102 0 : pSVMenu->SetItemImageMirrorMode( nslotId, false );
103 0 : pSVMenu->SetItemImageAngle( nslotId, lRotation );
104 : }
105 :
106 0 : if ( pSlot && pSlot->IsMode( SFX_SLOT_IMAGEREFLECTION ) )
107 0 : pSVMenu->SetItemImageMirrorMode( nslotId, bIsMirrored );
108 : }
109 0 : }
110 :
111 :
112 :
113 0 : static Image RetrieveAddOnImage( Reference< com::sun::star::frame::XFrame >& rFrame,
114 : const OUString& aImageId,
115 : const OUString& aURL,
116 : bool bBigImage
117 : )
118 : {
119 0 : Image aImage;
120 :
121 0 : if ( !aImageId.isEmpty() )
122 : {
123 0 : aImage = GetImage( rFrame, aImageId, bBigImage );
124 0 : if ( !!aImage )
125 0 : return aImage;
126 : }
127 :
128 0 : aImage = GetImage( rFrame, aURL, bBigImage );
129 0 : if ( !aImage )
130 0 : aImage = framework::AddonsOptions().GetImageFromURL( aURL, bBigImage );
131 :
132 0 : return aImage;
133 : }
134 :
135 :
136 :
137 : /* This helper function checks whether a Slot-id in the current application
138 : status is visible or not. This relates to the application status to see
139 : if the OLE server application exist or not.
140 : */
141 :
142 0 : bool IsItemHidden_Impl( sal_uInt16 nItemId, int bOleServer, int bMac )
143 : {
144 0 : return ( bMac &&
145 0 : ( nItemId == SID_MINIMIZED ) ) ||
146 0 : ( bOleServer &&
147 0 : ( nItemId == SID_QUITAPP || nItemId == SID_SAVEDOC ||
148 0 : nItemId == SID_OPENDOC || nItemId == SID_SAVEASDOC ||
149 0 : nItemId == SID_NEWDOC ) ) ||
150 0 : ( !bOleServer &&
151 0 : ( nItemId == SID_EXITANDRETURN || nItemId == SID_UPDATEDOC ) );
152 : }
153 :
154 :
155 :
156 0 : void SfxVirtualMenu::Construct_Impl()
157 : {
158 0 : pSVMenu->SetHighlightHdl( LINK(this, SfxVirtualMenu, Highlight) );
159 0 : pSVMenu->SetActivateHdl( LINK(this, SfxVirtualMenu, Activate) );
160 0 : pSVMenu->SetDeactivateHdl( LINK(this, SfxVirtualMenu, Deactivate) );
161 0 : pSVMenu->SetSelectHdl( LINK(this, SfxVirtualMenu, Select) );
162 :
163 0 : if ( !pResMgr && pParent )
164 0 : pResMgr = pParent->pResMgr;
165 0 : }
166 :
167 :
168 :
169 0 : SfxVirtualMenu::SfxVirtualMenu( sal_uInt16 nOwnId,
170 : SfxVirtualMenu* pOwnParent, Menu& rMenu, bool bWithHelp,
171 : SfxBindings &rBindings, bool bOLEServer, bool bRes, bool bIsAddonMenu ):
172 : pItems(0),
173 : pImageControl(0),
174 : pBindings(&rBindings),
175 : pResMgr(0),
176 : nLocks(0),
177 : bHelpInitialized( bWithHelp ),
178 0 : bIsAddonPopupMenu( bIsAddonMenu )
179 : {
180 0 : pSVMenu = &rMenu;
181 :
182 0 : bResCtor = bRes;
183 0 : bOLE = bOLEServer;
184 0 : nId = nOwnId;
185 0 : pParent = pOwnParent;
186 0 : nVisibleItems = 0;
187 0 : pAppCtrl = 0;
188 0 : pWindowMenu = NULL;
189 0 : pPickMenu = NULL;
190 0 : pAddonsMenu = NULL;
191 0 : bIsActive = false;
192 0 : bControllersUnBound = false;
193 0 : CreateFromSVMenu();
194 0 : Construct_Impl();
195 0 : bHelpInitialized = false;
196 0 : }
197 :
198 :
199 :
200 : // creates a virtual menu from a StarView MenuBar or PopupMenu
201 :
202 0 : SfxVirtualMenu::SfxVirtualMenu( Menu *pStarViewMenu, bool bWithHelp,
203 : SfxBindings &rBindings, bool bOLEServer, bool bRes, bool bIsAddonMenu ):
204 : pItems(0),
205 : pImageControl(0),
206 : pBindings(&rBindings),
207 : pResMgr(0),
208 : nLocks(0),
209 : bHelpInitialized( bWithHelp ),
210 0 : bIsAddonPopupMenu( bIsAddonMenu )
211 : {
212 :
213 0 : pSVMenu = pStarViewMenu;
214 :
215 0 : bResCtor = bRes;
216 0 : bOLE = bOLEServer;
217 0 : nId = 0;
218 0 : pParent = 0;
219 0 : pAppCtrl = 0;
220 0 : nVisibleItems = 0;
221 0 : pWindowMenu = NULL;
222 0 : pPickMenu = NULL;
223 0 : pAddonsMenu = NULL;
224 0 : bIsActive = false;
225 0 : bControllersUnBound = false;
226 0 : CreateFromSVMenu();
227 0 : Construct_Impl();
228 0 : bHelpInitialized = false;
229 0 : }
230 :
231 :
232 :
233 : /* The destructor of the class SfxVirtualMenu releases bounded items and
234 : the associated StarView-PopupMenu is released from its parent.
235 : If it is related to the Pickmenu or the MDI-menu, it is unregistered here.
236 : */
237 :
238 0 : SfxVirtualMenu::~SfxVirtualMenu()
239 : {
240 :
241 0 : DELETEZ( pImageControl );
242 0 : SvtMenuOptions().RemoveListenerLink( LINK( this, SfxVirtualMenu, SettingsChanged ) );
243 :
244 0 : if ( bIsActive )
245 : {
246 0 : pBindings->LEAVEREGISTRATIONS(); --nLocks; bIsActive = false;
247 : }
248 :
249 0 : if (pItems)
250 : {
251 0 : delete [] pItems;
252 : }
253 :
254 0 : delete pAppCtrl;
255 0 : pBindings = 0;
256 :
257 : // All the menus, which were created by SV, will also be there deleted
258 : // again (i.e. created by loading them from the resource)
259 : // The top-level menu is never deleted by SV, since the allocation
260 : // in done in the SFX
261 0 : if ( !bResCtor || !pParent)
262 : {
263 0 : if ( pParent )
264 : {
265 0 : if( pParent->pSVMenu->GetItemPos( nId ) != MENU_ITEM_NOTFOUND )
266 0 : pParent->pSVMenu->SetPopupMenu( nId, 0 );
267 0 : if ( pParent->pPickMenu == pSVMenu )
268 0 : pParent->pPickMenu = 0;
269 0 : if ( pParent->pWindowMenu == pSVMenu)
270 0 : pParent->pWindowMenu = 0;
271 0 : if ( pParent->pAddonsMenu == pSVMenu )
272 0 : pParent->pAddonsMenu = 0;
273 : }
274 :
275 0 : delete pSVMenu;
276 : }
277 :
278 : SAL_INFO("sfx", "SfxVirtualMenu " << this << " destroyed");
279 : DBG_ASSERT( !nLocks, "destroying active menu" );
280 0 : }
281 :
282 : // internal: creates the virtual menu from the pSVMenu
283 :
284 0 : void SfxVirtualMenu::CreateFromSVMenu()
285 : {
286 :
287 : // Merge Addon popup menus into the SV Menu
288 0 : SfxViewFrame* pViewFrame = pBindings->GetDispatcher()->GetFrame();
289 0 : Reference< com::sun::star::frame::XFrame > xFrame( pViewFrame->GetFrame().GetFrameInterface() );
290 :
291 0 : if ( pSVMenu->IsMenuBar() )
292 : {
293 0 : sal_uInt16 nPos = pSVMenu->GetItemPos( SID_MDIWINDOWLIST );
294 0 : if ( nPos != MENU_ITEM_NOTFOUND && xFrame.is() )
295 : {
296 : // Retrieve addon popup menus and add them to our menu bar
297 0 : Reference< com::sun::star::frame::XModel > xModel;
298 0 : Reference< com::sun::star::frame::XController > xController( xFrame->getController(), UNO_QUERY );
299 0 : if ( xController.is() )
300 0 : xModel = Reference< com::sun::star::frame::XModel >( xController->getModel(), UNO_QUERY );
301 0 : framework::AddonMenuManager::MergeAddonPopupMenus( xFrame, xModel, nPos, (MenuBar *)pSVMenu );
302 : }
303 :
304 : // Merge the Add-Ons help menu items into the Office help menu
305 0 : if ( xFrame.is() )
306 0 : framework::AddonMenuManager::MergeAddonHelpMenu( xFrame, (MenuBar *)pSVMenu );
307 :
308 : // Set addon menu pointer here to avoid problems. When accessibility is enabled, the whole menu
309 : // is created immediately!
310 0 : pAddonsMenu = pSVMenu->GetPopupMenu( SID_ADDONLIST );
311 : }
312 0 : else if ( pParent )
313 : {
314 0 : if ( pSVMenu == pParent->pAddonsMenu &&
315 0 : framework::AddonsOptions().HasAddonsMenu() &&
316 0 : !pSVMenu->GetPopupMenu( SID_ADDONS ) )
317 : {
318 : // Create menu item at the end of the tools popup menu for the addons popup menu
319 0 : InsertAddOnsMenuItem( pSVMenu );
320 : }
321 : }
322 :
323 : // get and store the number of items
324 0 : nCount = pSVMenu->GetItemCount();
325 :
326 : // Note: only this time it is guaranteed that nCount and the ItemCount
327 : // the SV-menus match; later on the SvMenu can have more entries
328 : // (Pick list!)
329 0 : if (nCount)
330 0 : pItems = new SfxMenuControl[nCount];
331 :
332 : // remember some values
333 0 : SFX_APP();
334 0 : const int bOleServer = sal_False;
335 0 : const int bMac = sal_False;
336 0 : SvtMenuOptions aOptions;
337 0 : aOptions.AddListenerLink( LINK( this, SfxVirtualMenu, SettingsChanged ) );
338 :
339 : // iterate through the items
340 0 : pBindings->ENTERREGISTRATIONS(); ++nLocks;
341 0 : pImageControl = new SfxMenuImageControl_Impl( SID_IMAGE_ORIENTATION, *pBindings, this );
342 :
343 0 : sal_uInt16 nSVPos = 0;
344 0 : for ( sal_uInt16 nPos=0; nPos<nCount; ++nPos, ++nSVPos )
345 : {
346 0 : sal_uInt16 nSlotId = pSVMenu->GetItemId(nSVPos);
347 0 : PopupMenu* pPopup = pSVMenu->GetPopupMenu(nSlotId);
348 0 : if( pPopup && nSlotId >= SID_OBJECTMENU0 && nSlotId <= SID_OBJECTMENU_LAST )
349 : {
350 : // artefact in XML menuconfig: every entry in root menu must have a popup!
351 0 : pSVMenu->SetPopupMenu( nSlotId, NULL );
352 0 : DELETEZ( pPopup );
353 : }
354 :
355 0 : const OUString sItemText = pSVMenu->GetItemText(nSlotId);
356 :
357 0 : if ( pPopup )
358 : {
359 :
360 : SfxMenuControl *pMnuCtrl =
361 0 : SfxMenuControl::CreateControl(nSlotId, *pPopup, *pBindings);
362 :
363 0 : if ( pMnuCtrl )
364 : {
365 : // The pop was obviously not "real" and such are never loaded
366 : // from the resource and need thus to be explicitly deleted.
367 0 : if ( pSVMenu->GetPopupMenu( nSlotId ) == pPopup )
368 0 : pSVMenu->SetPopupMenu( nSlotId, NULL );
369 0 : delete pPopup;
370 0 : pPopup = 0;
371 :
372 0 : SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl();
373 0 : rCtrlArr.push_back(pMnuCtrl);
374 0 : (pItems+nPos)->Bind( 0, nSlotId, sItemText, *pBindings);
375 0 : pMnuCtrl->Bind( this, nSlotId, sItemText, *pBindings);
376 :
377 0 : if ( Application::GetSettings().GetStyleSettings().GetUseImagesInMenus() )
378 : {
379 0 : OUString aSlotURL( "slot:" );
380 0 : aSlotURL += OUString::number( nSlotId);
381 0 : Image aImage = GetImage( xFrame, aSlotURL, false );
382 0 : pSVMenu->SetItemImage( nSlotId, aImage );
383 : }
384 : }
385 : else
386 : {
387 0 : pMnuCtrl = pItems+nPos;
388 :
389 : // Normally only now in Activate-Handler
390 0 : if ( bOLE )
391 : {
392 : pMnuCtrl->Bind( this, nSlotId,
393 0 : *new SfxVirtualMenu(nSlotId, this, *pPopup, bHelpInitialized, *pBindings, bOLE, bResCtor),
394 0 : sItemText, *pBindings );
395 : }
396 : }
397 :
398 0 : ++nVisibleItems;
399 : }
400 : else
401 : {
402 0 : switch ( pSVMenu->GetItemType(nSVPos) )
403 : {
404 : case MENUITEM_STRING:
405 : case MENUITEM_STRINGIMAGE:
406 : {
407 0 : SfxMenuControl *pMnuCtrl=0;
408 0 : OUString aCmd( pSVMenu->GetItemCommand( nSlotId ) );
409 0 : if ( !aCmd.isEmpty() && (( nSlotId < SID_SFX_START ) || ( nSlotId > SHRT_MAX )) )
410 : {
411 : // try to create control via command name
412 0 : pMnuCtrl = SfxMenuControl::CreateControl( aCmd, nSlotId, *pSVMenu, sItemText, *pBindings, this );
413 0 : if ( pMnuCtrl )
414 : {
415 0 : SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl();
416 0 : rCtrlArr.push_back(pMnuCtrl);
417 0 : (pItems+nPos)->Bind( 0, nSlotId, sItemText, *pBindings);
418 : }
419 : }
420 :
421 0 : if ( !pMnuCtrl )
422 : {
423 : // try to create control via Id
424 0 : pMnuCtrl = SfxMenuControl::CreateControl(nSlotId, *pSVMenu, *pBindings);
425 0 : if ( pMnuCtrl )
426 : {
427 0 : SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl();
428 0 : rCtrlArr.push_back(pMnuCtrl);
429 0 : (pItems+nPos)->Bind( 0, nSlotId, sItemText, *pBindings);
430 : }
431 : else
432 : // take default control
433 0 : pMnuCtrl = (pItems+nPos);
434 :
435 0 : pMnuCtrl->Bind( this, nSlotId, sItemText, *pBindings);
436 : }
437 :
438 0 : if ( Application::GetSettings().GetStyleSettings().GetUseImagesInMenus() )
439 : {
440 0 : Image aImage;
441 0 : if ( bIsAddonPopupMenu || framework::AddonMenuManager::IsAddonMenuId( nSlotId ))
442 : {
443 0 : OUString aImageId;
444 :
445 : ::framework::MenuConfiguration::Attributes* pMenuAttributes =
446 0 : (::framework::MenuConfiguration::Attributes*)pSVMenu->GetUserValue( nSlotId );
447 :
448 0 : if ( pMenuAttributes )
449 0 : aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes
450 :
451 0 : aImage = RetrieveAddOnImage( xFrame, aImageId, aCmd, false );
452 : }
453 : else
454 : {
455 0 : OUString aSlotURL( "slot:" );
456 0 : aSlotURL += OUString::number( nSlotId);
457 0 : aImage = GetImage( xFrame, aSlotURL, false );
458 : }
459 :
460 0 : if ( !!aImage )
461 0 : pSVMenu->SetItemImage( nSlotId, aImage );
462 : }
463 :
464 0 : if ( !IsItemHidden_Impl(nSlotId, bOleServer, bMac) )
465 0 : ++nVisibleItems;
466 : else
467 0 : pSVMenu->RemoveItem( nSVPos-- );
468 0 : break;
469 : }
470 :
471 : case MENUITEM_IMAGE:
472 : //! not implemented
473 0 : break;
474 :
475 : case MENUITEM_SEPARATOR:
476 : //! not implemented
477 0 : break;
478 : default:
479 0 : break; // DONTKNOW and STRINGIMAGE not handled.
480 : }
481 : }
482 0 : }
483 0 : pBindings->LEAVEREGISTRATIONS(); --nLocks;
484 0 : }
485 :
486 :
487 :
488 : // called on activation of the SV-Menu
489 :
490 0 : IMPL_LINK_NOARG( SfxVirtualMenu, Highlight )
491 : {
492 :
493 0 : return sal_True;
494 : }
495 :
496 0 : IMPL_LINK_NOARG(SfxVirtualMenu, SettingsChanged)
497 : {
498 0 : sal_uInt16 nItemCount = pSVMenu->GetItemCount();
499 0 : SfxViewFrame *pViewFrame = pBindings->GetDispatcher()->GetFrame();
500 0 : bool bIcons = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus();
501 0 : Reference<com::sun::star::frame::XFrame> xFrame( pViewFrame->GetFrame().GetFrameInterface() );
502 :
503 0 : if ( !bIsAddonPopupMenu )
504 : {
505 0 : for ( sal_uInt16 nSVPos=0; nSVPos<nItemCount; ++nSVPos )
506 : {
507 0 : sal_uInt16 nSlotId = pSVMenu->GetItemId( nSVPos );
508 0 : MenuItemType nType = pSVMenu->GetItemType( nSVPos );
509 0 : if ( nType == MENUITEM_STRING && bIcons )
510 : {
511 0 : if ( framework::AddonMenuManager::IsAddonMenuId( nSlotId ))
512 : {
513 : // Special code for Add-On menu items. They can appear inside the help menu.
514 0 : OUString aCmd( pSVMenu->GetItemCommand( nSlotId ) );
515 0 : OUString aImageId;
516 :
517 : ::framework::MenuConfiguration::Attributes* pMenuAttributes =
518 0 : (::framework::MenuConfiguration::Attributes*)pSVMenu->GetUserValue( nSlotId );
519 :
520 0 : if ( pMenuAttributes )
521 0 : aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes
522 :
523 0 : pSVMenu->SetItemImage( nSlotId, RetrieveAddOnImage( xFrame, aImageId, aCmd, false ));
524 : }
525 : else
526 : {
527 0 : OUString aSlotURL( "slot:" );
528 0 : aSlotURL += OUString::number( nSlotId);
529 0 : pSVMenu->SetItemImage( nSlotId, GetImage( xFrame, aSlotURL, false ));
530 0 : }
531 : }
532 0 : else if( nType == MENUITEM_STRINGIMAGE && !bIcons )
533 : {
534 0 : pSVMenu->SetItemImage( nSlotId, Image() );
535 : }
536 : }
537 : }
538 : else
539 : {
540 : // Remove/update images from Add-Ons top-level popup menus when settings have changed
541 0 : if ( !bIcons )
542 0 : RemoveMenuImages( pSVMenu );
543 : else
544 0 : UpdateImages( pSVMenu );
545 : }
546 :
547 : // Special code to remove menu images from runtime popup menus when settings have changed
548 0 : if ( pParent && pSVMenu == pParent->pAddonsMenu )
549 : {
550 0 : if ( !bIcons )
551 0 : RemoveMenuImages( pParent->pAddonsMenu->GetPopupMenu( SID_ADDONS ));
552 : else
553 0 : UpdateImages( pParent->pAddonsMenu->GetPopupMenu( SID_ADDONS ));
554 : }
555 :
556 0 : if ( pImageControl )
557 0 : pImageControl->Update();
558 :
559 0 : return 0;
560 : }
561 :
562 :
563 :
564 0 : void SfxVirtualMenu::UpdateImages( Menu* pMenu )
565 : {
566 0 : if ( !pMenu )
567 0 : return;
568 :
569 0 : framework::AddonsOptions aAddonOptions;
570 :
571 0 : bool bIcons = Application::GetSettings().GetStyleSettings().GetUseImagesInMenus();
572 0 : if ( bIcons )
573 : {
574 0 : sal_uInt16 nItemCount = pMenu->GetItemCount();
575 0 : Reference<com::sun::star::frame::XFrame> aXFrame( pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame().GetFrameInterface() );
576 :
577 0 : for ( sal_uInt16 nPos=0; nPos < nItemCount; ++nPos )
578 : {
579 0 : sal_uInt16 nSlotId = pMenu->GetItemId( nPos );
580 0 : PopupMenu* pPopup = pMenu->GetPopupMenu( nSlotId );
581 0 : if ( pMenu->GetItemType( nPos ) != MENUITEM_SEPARATOR )
582 : {
583 0 : OUString aImageId;
584 :
585 : ::framework::MenuConfiguration::Attributes* pMenuAttributes =
586 0 : (::framework::MenuConfiguration::Attributes*)pMenu->GetUserValue( nSlotId );
587 :
588 0 : if ( pMenuAttributes )
589 0 : aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes
590 :
591 0 : pMenu->SetItemImage( nSlotId, RetrieveAddOnImage( aXFrame, aImageId, pMenu->GetItemCommand( nSlotId ), false ));
592 : }
593 :
594 0 : if ( pPopup )
595 0 : UpdateImages( pPopup );
596 : }
597 :
598 0 : if ( pImageControl )
599 0 : pImageControl->Update();
600 0 : }
601 : }
602 :
603 :
604 :
605 0 : void SfxVirtualMenu::RemoveMenuImages( Menu* pMenu )
606 : {
607 0 : if ( !pMenu )
608 0 : return;
609 :
610 0 : sal_uInt16 nItemCount = pMenu->GetItemCount();
611 0 : for ( sal_uInt16 nPos=0; nPos < nItemCount; ++nPos )
612 : {
613 0 : sal_uInt16 nSlotId = pMenu->GetItemId( nPos );
614 0 : PopupMenu* pPopup = pMenu->GetPopupMenu( nSlotId );
615 0 : if ( pMenu->GetItemType( nPos ) == MENUITEM_STRINGIMAGE )
616 0 : pMenu->SetItemImage( nSlotId, Image() );
617 0 : if ( pPopup )
618 0 : RemoveMenuImages( pPopup );
619 : }
620 : }
621 :
622 :
623 :
624 0 : bool SfxVirtualMenu::Bind_Impl( Menu *pMenu )
625 : {
626 : // Search , as SV with 'sal_uInt16 nSID = pSVMenu->GetCurItemId();' always
627 : // returns 0. It is like this, since the Event-Forwarding has nothing to do
628 : // with the Parent-Menus CurItem.
629 0 : sal_uInt32 nAddonsPopupPrefixLen = ADDONSPOPUPMENU_URL_PREFIX.getLength();
630 :
631 0 : for ( sal_uInt16 nPos = 0; nPos < nCount; ++nPos )
632 : {
633 0 : sal_uInt16 nSID = pSVMenu->GetItemId(nPos);
634 0 : SfxMenuControl &rCtrl = pItems[nPos];
635 : // found the Sub-Menu in question?
636 0 : bool bFound = pSVMenu->GetPopupMenu(nSID) == pMenu;
637 0 : SfxVirtualMenu *pSubMenu = rCtrl.GetPopupMenu();
638 :
639 0 : if ( bFound )
640 : {
641 : // Only a binded Menu-Controller as already an Id!
642 0 : if ( !rCtrl.GetId() )
643 : {
644 0 : bIsAddonPopupMenu = false;
645 : DBG_ASSERT( !pSubMenu, "Popup already exists!");
646 :
647 : // Check if the popup is an Add-On popup menu
648 : // Either the popup menu has a special ID or a special command URL prefix!
649 0 : OUString aCommand = pSVMenu->GetItemCommand( nSID );
650 0 : if ( ( nSID == SID_ADDONS ) ||
651 0 : ( nSID == SID_ADDONHELP ) ||
652 0 : (( (sal_uInt32)aCommand.getLength() > nAddonsPopupPrefixLen ) &&
653 0 : ( aCommand.startsWith( ADDONSPOPUPMENU_URL_PREFIX ) ) ) )
654 0 : bIsAddonPopupMenu = true;
655 :
656 : // Create VirtualMenu for Sub-Menu
657 0 : bool bRes = bResCtor;
658 : pSubMenu = new SfxVirtualMenu( nSID, this,
659 0 : *pMenu, false, *pBindings, bOLE, bRes, bIsAddonPopupMenu );
660 :
661 : SAL_INFO("sfx", "New VirtualMenu " << pSubMenu << " created");
662 :
663 0 : rCtrl.Bind( this, nSID, *pSubMenu, pSVMenu->GetItemText(nSID), *pBindings );
664 :
665 : // Forward Activate
666 0 : pSubMenu->Bind_Impl( pMenu );
667 0 : pSubMenu->Activate( pMenu );
668 : }
669 : }
670 :
671 : // continue searching recursively (SV Activate only the menu itself
672 : // and Top-Menu)
673 0 : if ( !bFound && pSubMenu )
674 0 : bFound = pSubMenu->Bind_Impl( pMenu );
675 :
676 : // If found, break
677 0 : if ( bFound )
678 0 : return true;
679 : }
680 :
681 : // Not found in this submenu
682 0 : return false;
683 : }
684 :
685 0 : void SfxVirtualMenu::BindControllers()
686 : {
687 0 : pBindings->ENTERREGISTRATIONS();
688 :
689 : sal_uInt16 nPos;
690 0 : for ( nPos = 0; nPos < nCount; ++nPos )
691 : {
692 0 : SfxMenuControl& rCtrl = pItems[nPos];
693 0 : if ( rCtrl.IsBindable_Impl() && !rCtrl.GetPopupMenu() )
694 0 : rCtrl.ReBind();
695 : }
696 :
697 0 : SfxMenuCtrlArr_Impl& rCtrlArr = GetAppCtrl_Impl();
698 0 : for (SfxMenuCtrlArr_Impl::iterator i = rCtrlArr.begin();
699 0 : i != rCtrlArr.end(); ++i)
700 : {
701 0 : sal_uInt16 nSlotId = i->GetId();
702 0 : if (pSVMenu->GetItemCommand(nSlotId).isEmpty())
703 : {
704 0 : i->ReBind();
705 : }
706 : }
707 :
708 0 : pBindings->LEAVEREGISTRATIONS();
709 0 : bControllersUnBound = false;
710 0 : }
711 :
712 0 : void SfxVirtualMenu::UnbindControllers()
713 : {
714 0 : pBindings->ENTERREGISTRATIONS();
715 :
716 : sal_uInt16 nPos;
717 0 : for ( nPos = 0; nPos < nCount; ++nPos )
718 : {
719 0 : SfxMenuControl &rCtrl = pItems[nPos];
720 0 : if ( rCtrl.IsBound() )
721 0 : rCtrl.UnBind();
722 : }
723 :
724 0 : SfxMenuCtrlArr_Impl& rCtrlArr = GetAppCtrl_Impl();
725 0 : for (SfxMenuCtrlArr_Impl::iterator i = rCtrlArr.begin();
726 0 : i != rCtrlArr.end(); ++i)
727 : {
728 0 : if (i->IsBound())
729 : {
730 : // UnoController is not bound!
731 0 : i->UnBind();
732 : }
733 : }
734 :
735 0 : pBindings->LEAVEREGISTRATIONS();
736 0 : bControllersUnBound = true;
737 0 : }
738 :
739 :
740 :
741 0 : void SfxVirtualMenu::InsertAddOnsMenuItem( Menu* pMenu )
742 : {
743 : // Create special popup menu that is filled with the 3rd party components popup menu items
744 0 : ::framework::MenuConfiguration aConf( ::comphelper::getProcessComponentContext() );
745 0 : Reference<com::sun::star::frame::XFrame> xFrame( pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame().GetFrameInterface() );
746 :
747 0 : PopupMenu* pAddonMenu = NULL;
748 : try
749 : {
750 0 : pAddonMenu = framework::AddonMenuManager::CreateAddonMenu( xFrame );
751 : }
752 0 : catch ( const ::com::sun::star::lang::WrappedTargetException& )
753 : {
754 : }
755 :
756 : // Create menu item at the end of the tools popup menu for the addons popup menu
757 0 : if ( pAddonMenu && pAddonMenu->GetItemCount() > 0 )
758 : {
759 0 : sal_uInt16 nItemCount = pMenu->GetItemCount();
760 0 : OUString aAddonsTitle(SfxResId(STR_MENU_ADDONS).toString());
761 0 : if ( nItemCount > 0 && pMenu->GetItemType( nItemCount-1 ) != MENUITEM_SEPARATOR )
762 0 : pMenu->InsertSeparator();
763 0 : pMenu->InsertItem( SID_ADDONS, aAddonsTitle );
764 0 : pMenu->SetPopupMenu( SID_ADDONS, pAddonMenu );
765 :
766 0 : if ( Application::GetSettings().GetStyleSettings().GetUseImagesInMenus() )
767 : {
768 0 : OUString aSlotURL( "slot:" );
769 0 : aSlotURL += OUString::number( SID_ADDONS);
770 0 : pMenu->SetItemImage( SID_ADDONS, GetImage( xFrame, aSlotURL, false ));
771 0 : }
772 : }
773 : else
774 0 : delete pAddonMenu;
775 0 : }
776 :
777 :
778 :
779 : // called on activation of the SV-Menu
780 :
781 0 : IMPL_LINK( SfxVirtualMenu, Activate, Menu *, pMenu )
782 : {
783 : SAL_INFO(
784 : "sfx",
785 : "SfxVirtualMenu " << this << " activated " << pMenu << ", own "
786 : << pSVMenu);
787 :
788 : // MI: for what was it still good for?
789 : // MBA: seemes to be an old QAP-Hack( checked-in in rev.1.41 ! )
790 :
791 0 : if ( pMenu )
792 : {
793 0 : bool bDontHide = SvtMenuOptions().IsEntryHidingEnabled();
794 0 : sal_uInt16 nFlag = pMenu->GetMenuFlags();
795 0 : if ( bDontHide )
796 0 : nFlag &= ~MENU_FLAG_HIDEDISABLEDENTRIES;
797 : else
798 0 : nFlag |= MENU_FLAG_HIDEDISABLEDENTRIES;
799 0 : pMenu->SetMenuFlags( nFlag );
800 : }
801 :
802 : // Own StarView-Menu
803 0 : if ( pMenu == pSVMenu )
804 : {
805 : // Prevent Double Activate
806 0 : if ( bIsActive )
807 0 : return sal_True;
808 :
809 : // ggf. Pick-Menu erzeugen
810 0 : if ( pParent && pSVMenu == pParent->pPickMenu )
811 : {
812 0 : SfxPickList::Get().CreateMenuEntries( pParent->pPickMenu );
813 : }
814 : else
815 0 : pPickMenu = pSVMenu->GetPopupMenu(SID_PICKLIST);
816 :
817 0 : if ( pParent && pSVMenu == pParent->pWindowMenu )
818 : {
819 : // update window list
820 0 : ::std::vector< OUString > aNewWindowListVector;
821 0 : Reference< XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );;
822 :
823 0 : sal_uInt16 nActiveItemId = 0;
824 0 : sal_uInt16 nItemId = START_ITEMID_WINDOWLIST;
825 :
826 0 : Reference< XFrame > xCurrentFrame = xDesktop->getCurrentFrame();
827 0 : Reference< XIndexAccess > xList ( xDesktop->getFrames(), UNO_QUERY );
828 0 : sal_Int32 nFrameCount = xList->getCount();
829 0 : for( sal_Int32 i=0; i<nFrameCount; ++i )
830 : {
831 0 : Reference< XFrame > xFrame;
832 0 : Any aVal = xList->getByIndex(i);
833 0 : if (!(aVal>>=xFrame) || !xFrame.is() )
834 0 : continue;
835 :
836 0 : if ( xFrame == xCurrentFrame )
837 0 : nActiveItemId = nItemId;
838 :
839 0 : Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
840 0 : if ( pWin && pWin->IsVisible() )
841 : {
842 0 : aNewWindowListVector.push_back( pWin->GetText() );
843 0 : ++nItemId;
844 : }
845 0 : }
846 :
847 0 : int nItemCount = pMenu->GetItemCount();
848 :
849 0 : if ( nItemCount > 0 )
850 : {
851 : // remove all old window list entries from menu
852 0 : sal_uInt16 nPos = pMenu->GetItemPos( START_ITEMID_WINDOWLIST );
853 0 : for ( sal_uInt16 n = nPos; n < pMenu->GetItemCount(); )
854 0 : pMenu->RemoveItem( n );
855 :
856 0 : if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MENUITEM_SEPARATOR )
857 0 : pMenu->RemoveItem( pMenu->GetItemCount()-1 );
858 : }
859 :
860 0 : if ( aNewWindowListVector.size() > 0 )
861 : {
862 : // append new window list entries to menu
863 0 : pMenu->InsertSeparator();
864 0 : nItemId = START_ITEMID_WINDOWLIST;
865 0 : for ( sal_uInt32 i = 0; i < aNewWindowListVector.size(); i++ )
866 : {
867 0 : pMenu->InsertItem( nItemId, aNewWindowListVector.at( i ), MIB_RADIOCHECK );
868 0 : if ( nItemId == nActiveItemId )
869 0 : pMenu->CheckItem( nItemId );
870 0 : ++nItemId;
871 : }
872 0 : }
873 : }
874 : else
875 0 : pWindowMenu = pSVMenu->GetPopupMenu(SID_MDIWINDOWLIST);
876 :
877 0 : if ( !pParent && pSVMenu->IsMenuBar() && !pAddonsMenu )
878 : {
879 : // Store Add-Ons parents of our runtime menu items
880 0 : pAddonsMenu = pSVMenu->GetPopupMenu( SID_ADDONLIST );
881 : }
882 :
883 : // Provides consistency to the Status
884 0 : if ( bControllersUnBound )
885 0 : BindControllers();
886 :
887 0 : pBindings->GetDispatcher_Impl()->Flush();
888 0 : for ( sal_uInt16 nPos = 0; nPos < nCount; ++nPos )
889 : {
890 0 : sal_uInt16 nSlotId = (pItems+nPos)->GetId();
891 0 : if ( nSlotId && nSlotId > END_ITEMID_WINDOWLIST )
892 0 : pBindings->Update(nSlotId);
893 : }
894 :
895 0 : pBindings->Update( SID_IMAGE_ORIENTATION );
896 :
897 : // Supress the Status updates until Deactivate
898 0 : pBindings->ENTERREGISTRATIONS(); ++nLocks; bIsActive = true;
899 :
900 0 : return sal_True;
901 : }
902 : else
903 : {
904 : // Find the VirtualMenu for the SubMenu and if possible, bind a
905 : // VirtualMenu
906 0 : bool bRet = Bind_Impl( pMenu );
907 : #ifdef DBG_UTIL
908 : if ( !bRet)
909 : DBG_WARNING( "W1: Virtual menu could not be created!" );
910 : #endif
911 0 : return long(bRet);
912 : }
913 : }
914 :
915 :
916 :
917 0 : IMPL_LINK( SfxVirtualMenu, Deactivate, Menu *, pMenu )
918 : {
919 : SAL_INFO(
920 : "sfx",
921 : "SfxVirtualMenu " << this << " deactivated " << pMenu << ", own "
922 : << pSVMenu);
923 0 : if ( bIsActive && ( 0 == pMenu || pMenu == pSVMenu ) )
924 : {
925 : // All controllers can be unbinded all the way up to the Menubar,
926 : // when the menu is disabled (= closed)
927 0 : if ( pParent )
928 0 : UnbindControllers();
929 0 : pBindings->LEAVEREGISTRATIONS(); --nLocks; bIsActive = false;
930 : }
931 0 : return sal_True;
932 : }
933 :
934 :
935 : // called on activation of the SV-Menu
936 :
937 0 : IMPL_LINK( SfxVirtualMenu, Select, Menu *, pMenu )
938 : {
939 0 : sal_uInt16 nSlotId = (sal_uInt16) pMenu->GetCurItemId();
940 : SAL_INFO(
941 : "sfx",
942 : "SfxVirtualMenu " << this << " selected " << nSlotId << " from "
943 : << pMenu);
944 :
945 0 : if ( nSlotId >= START_ITEMID_WINDOWLIST && nSlotId <= END_ITEMID_WINDOWLIST )
946 : {
947 : // window list menu item selected
948 0 : Reference< XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
949 0 : sal_uInt16 nTaskId = START_ITEMID_WINDOWLIST;
950 0 : Reference< XIndexAccess > xList( xDesktop->getFrames(), UNO_QUERY );
951 0 : sal_Int32 nFrameCount = xList->getCount();
952 0 : for ( sal_Int32 i=0; i<nFrameCount; ++i )
953 : {
954 0 : Any aItem = xList->getByIndex(i);
955 0 : Reference< XFrame > xFrame;
956 0 : if (( aItem >>= xFrame ) && xFrame.is() && nTaskId == nSlotId )
957 : {
958 0 : Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
959 0 : pWin->GrabFocus();
960 0 : pWin->ToTop( TOTOP_RESTOREWHENMIN );
961 0 : break;
962 : }
963 :
964 0 : nTaskId++;
965 0 : }
966 :
967 0 : return sal_True;
968 : }
969 0 : else if ( nSlotId >= START_ITEMID_PICKLIST && nSlotId <= END_ITEMID_PICKLIST )
970 : {
971 0 : SfxPickList::Get().ExecuteMenuEntry( nSlotId );
972 0 : return sal_True;
973 : }
974 :
975 0 : OUString sCommand = pMenu->GetItemCommand(nSlotId);
976 0 : if (!sCommand.isEmpty())
977 0 : pBindings->ExecuteCommand_Impl(sCommand);
978 : else
979 0 : pBindings->Execute(nSlotId);
980 :
981 0 : return sal_True;
982 : }
983 :
984 :
985 :
986 : // returns the associated StarView-menu
987 :
988 0 : Menu* SfxVirtualMenu::GetSVMenu() const
989 : {
990 :
991 0 : return pSVMenu;
992 : }
993 :
994 :
995 :
996 : // set the checkmark of the specified item
997 :
998 0 : void SfxVirtualMenu::CheckItem( sal_uInt16 nItemId, bool bCheck )
999 : {
1000 : DBG_ASSERT( this != 0, "");
1001 : DBG_ASSERT( pSVMenu != 0, "" );
1002 0 : if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND )
1003 0 : pSVMenu->CheckItem( nItemId, bCheck );
1004 0 : }
1005 :
1006 :
1007 : // set the enabled-state of the specified item
1008 :
1009 0 : void SfxVirtualMenu::EnableItem( sal_uInt16 nItemId, bool bEnable )
1010 : {
1011 : DBG_ASSERT( this != 0, "");
1012 : DBG_ASSERT( pSVMenu != 0, "" );
1013 :
1014 0 : if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND )
1015 0 : pSVMenu->EnableItem( nItemId, bEnable );
1016 0 : }
1017 :
1018 :
1019 : // set the text of the specified item
1020 :
1021 0 : void SfxVirtualMenu::SetItemText( sal_uInt16 nItemId, const OUString& rText )
1022 : {
1023 : DBG_ASSERT( this != 0, "");
1024 : DBG_ASSERT( pSVMenu != 0, "" );
1025 0 : if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND )
1026 0 : pSVMenu->SetItemText( nItemId, rText );
1027 0 : }
1028 :
1029 :
1030 :
1031 :
1032 0 : void SfxVirtualMenu::SetPopupMenu( sal_uInt16 nItemId, PopupMenu *pMenu )
1033 : {
1034 :
1035 0 : if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND )
1036 0 : GetSVMenu()->SetPopupMenu( nItemId, pMenu );
1037 0 : for ( sal_uInt16 n = 0; n < nCount; ++n )
1038 : {
1039 0 : SfxVirtualMenu *pSubMenu = (pItems+n)->GetPopupMenu();
1040 0 : if ( pSubMenu )
1041 0 : pSubMenu->SetPopupMenu( nItemId, pMenu );
1042 : }
1043 0 : }
1044 :
1045 :
1046 :
1047 : // Forces the initialization, which is otherwise only happens in Activate
1048 :
1049 0 : void SfxVirtualMenu::InitPopup( sal_uInt16 nPos, bool /*bOLE*/ )
1050 : {
1051 :
1052 0 : sal_uInt16 nSID = pSVMenu->GetItemId(nPos);
1053 0 : PopupMenu *pMenu = pSVMenu->GetPopupMenu( nSID );
1054 :
1055 : DBG_ASSERT( pMenu, "No popup exist here!");
1056 :
1057 0 : SfxMenuControl &rCtrl = pItems[nPos];
1058 0 : if ( !rCtrl.GetId() )
1059 : {
1060 : // Generate VirtualMenu for Sub-Menu
1061 0 : bool bRes = bResCtor;
1062 : SfxVirtualMenu *pSubMenu =
1063 0 : new SfxVirtualMenu(nSID, this, *pMenu, false, *pBindings, bOLE, bRes);
1064 :
1065 : SAL_INFO("sfx", "New VirtualMenu " << pSubMenu << " created");
1066 :
1067 0 : rCtrl.Bind( this, nSID, *pSubMenu, pSVMenu->GetItemText(nSID), *pBindings );
1068 : }
1069 0 : }
1070 :
1071 0 : void SfxVirtualMenu::InitializeHelp()
1072 : {
1073 0 : for ( sal_uInt16 nPos = 0; nPos<pSVMenu->GetItemCount(); ++nPos )
1074 : {
1075 0 : sal_uInt16 nSlotId = pSVMenu->GetItemId(nPos);
1076 0 : SfxMenuControl &rCtrl = pItems[nPos];
1077 0 : if ( nSlotId && !rCtrl.GetId() )
1078 : {
1079 0 : InitPopup( nPos, true );
1080 : }
1081 :
1082 0 : SfxVirtualMenu *pSubMenu = rCtrl.GetPopupMenu();
1083 0 : if ( pSubMenu )
1084 0 : pSubMenu->InitializeHelp();
1085 : }
1086 :
1087 0 : bHelpInitialized = true;
1088 0 : }
1089 :
1090 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|