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