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 : Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
294 0 : sal_uInt16 nPos = pSVMenu->GetItemPos( SID_MDIWINDOWLIST );
295 0 : if ( nPos != MENU_ITEM_NOTFOUND && xFrame.is() )
296 : {
297 : // Retrieve addon popup menus and add them to our menu bar
298 0 : framework::AddonMenuManager::MergeAddonPopupMenus( xFrame, nPos, static_cast<MenuBar *>(pSVMenu), xContext );
299 : }
300 :
301 : // Merge the Add-Ons help menu items into the Office help menu
302 0 : if ( xFrame.is() )
303 0 : framework::AddonMenuManager::MergeAddonHelpMenu( xFrame, static_cast<MenuBar *>(pSVMenu), xContext );
304 :
305 : // Set addon menu pointer here to avoid problems. When accessibility is enabled, the whole menu
306 : // is created immediately!
307 0 : pAddonsMenu = pSVMenu->GetPopupMenu( SID_ADDONLIST );
308 : }
309 0 : else if ( pParent )
310 : {
311 0 : if ( pSVMenu == pParent->pAddonsMenu &&
312 0 : framework::AddonsOptions().HasAddonsMenu() &&
313 0 : !pSVMenu->GetPopupMenu( SID_ADDONS ) )
314 : {
315 : // Create menu item at the end of the tools popup menu for the addons popup menu
316 0 : InsertAddOnsMenuItem( pSVMenu );
317 : }
318 : }
319 :
320 : // get and store the number of items
321 0 : nCount = pSVMenu->GetItemCount();
322 :
323 : // Note: only this time it is guaranteed that nCount and the ItemCount
324 : // the SV-menus match; later on the SvMenu can have more entries
325 : // (Pick list!)
326 0 : if (nCount)
327 0 : pItems = new SfxMenuControl[nCount];
328 :
329 : // remember some values
330 0 : SfxGetpApp();
331 0 : const int bOleServer = sal_False;
332 0 : const int bMac = sal_False;
333 0 : SvtMenuOptions aOptions;
334 0 : aOptions.AddListenerLink( LINK( this, SfxVirtualMenu, SettingsChanged ) );
335 :
336 : // iterate through the items
337 0 : pBindings->ENTERREGISTRATIONS(); ++nLocks;
338 0 : pImageControl = new SfxMenuImageControl_Impl( SID_IMAGE_ORIENTATION, *pBindings, this );
339 :
340 0 : sal_uInt16 nSVPos = 0;
341 0 : for ( sal_uInt16 nPos=0; nPos<nCount; ++nPos, ++nSVPos )
342 : {
343 0 : sal_uInt16 nSlotId = pSVMenu->GetItemId(nSVPos);
344 0 : PopupMenu* pPopup = pSVMenu->GetPopupMenu(nSlotId);
345 0 : if( pPopup && nSlotId >= SID_OBJECTMENU0 && nSlotId <= SID_OBJECTMENU_LAST )
346 : {
347 : // artefact in XML menuconfig: every entry in root menu must have a popup!
348 0 : pSVMenu->SetPopupMenu( nSlotId, NULL );
349 0 : DELETEZ( pPopup );
350 : }
351 :
352 0 : const OUString sItemText = pSVMenu->GetItemText(nSlotId);
353 :
354 0 : if ( pPopup )
355 : {
356 :
357 : SfxMenuControl *pMnuCtrl =
358 0 : SfxMenuControl::CreateControl(nSlotId, *pPopup, *pBindings);
359 :
360 0 : if ( pMnuCtrl )
361 : {
362 : // The pop was obviously not "real" and such are never loaded
363 : // from the resource and need thus to be explicitly deleted.
364 0 : if ( pSVMenu->GetPopupMenu( nSlotId ) == pPopup )
365 0 : pSVMenu->SetPopupMenu( nSlotId, NULL );
366 0 : delete pPopup;
367 0 : pPopup = 0;
368 :
369 0 : SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl();
370 0 : rCtrlArr.push_back(pMnuCtrl);
371 0 : (pItems+nPos)->Bind( 0, nSlotId, sItemText, *pBindings);
372 0 : pMnuCtrl->Bind( this, nSlotId, sItemText, *pBindings);
373 :
374 0 : if ( Application::GetSettings().GetStyleSettings().GetUseImagesInMenus() )
375 : {
376 0 : OUString aSlotURL( "slot:" );
377 0 : aSlotURL += OUString::number( nSlotId);
378 0 : Image aImage = GetImage( xFrame, aSlotURL, false );
379 0 : pSVMenu->SetItemImage( nSlotId, aImage );
380 : }
381 : }
382 : else
383 : {
384 0 : pMnuCtrl = pItems+nPos;
385 :
386 : // Normally only now in Activate-Handler
387 0 : if ( bOLE )
388 : {
389 : pMnuCtrl->Bind( this, nSlotId,
390 0 : *new SfxVirtualMenu(nSlotId, this, *pPopup, bHelpInitialized, *pBindings, bOLE, bResCtor),
391 0 : sItemText, *pBindings );
392 : }
393 : }
394 :
395 0 : ++nVisibleItems;
396 : }
397 : else
398 : {
399 0 : switch ( pSVMenu->GetItemType(nSVPos) )
400 : {
401 : case MenuItemType::STRING:
402 : case MenuItemType::STRINGIMAGE:
403 : {
404 0 : SfxMenuControl *pMnuCtrl=0;
405 0 : OUString aCmd( pSVMenu->GetItemCommand( nSlotId ) );
406 0 : if ( !aCmd.isEmpty() && (( nSlotId < SID_SFX_START ) || ( nSlotId > SHRT_MAX )) )
407 : {
408 : // try to create control via command name
409 0 : pMnuCtrl = SfxMenuControl::CreateControl( aCmd, nSlotId, *pSVMenu, sItemText, *pBindings, this );
410 0 : if ( pMnuCtrl )
411 : {
412 0 : SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl();
413 0 : rCtrlArr.push_back(pMnuCtrl);
414 0 : (pItems+nPos)->Bind( 0, nSlotId, sItemText, *pBindings);
415 : }
416 : }
417 :
418 0 : if ( !pMnuCtrl )
419 : {
420 : // try to create control via Id
421 0 : pMnuCtrl = SfxMenuControl::CreateControl(nSlotId, *pSVMenu, *pBindings);
422 0 : if ( pMnuCtrl )
423 : {
424 0 : SfxMenuCtrlArr_Impl &rCtrlArr = GetAppCtrl_Impl();
425 0 : rCtrlArr.push_back(pMnuCtrl);
426 0 : (pItems+nPos)->Bind( 0, nSlotId, sItemText, *pBindings);
427 : }
428 : else
429 : // take default control
430 0 : pMnuCtrl = (pItems+nPos);
431 :
432 0 : pMnuCtrl->Bind( this, nSlotId, sItemText, *pBindings);
433 : }
434 :
435 0 : if ( Application::GetSettings().GetStyleSettings().GetUseImagesInMenus() )
436 : {
437 0 : Image aImage;
438 0 : if ( bIsAddonPopupMenu || framework::AddonMenuManager::IsAddonMenuId( nSlotId ))
439 : {
440 0 : OUString aImageId;
441 :
442 : ::framework::MenuConfiguration::Attributes* pMenuAttributes =
443 0 : reinterpret_cast< ::framework::MenuConfiguration::Attributes*>(pSVMenu->GetUserValue( nSlotId ));
444 :
445 0 : if ( pMenuAttributes )
446 0 : aImageId = pMenuAttributes->aImageId; // Retrieve image id from menu attributes
447 :
448 0 : aImage = RetrieveAddOnImage( xFrame, aImageId, aCmd, false );
449 : }
450 : else
451 : {
452 0 : OUString aSlotURL( "slot:" );
453 0 : aSlotURL += OUString::number( nSlotId);
454 0 : aImage = GetImage( xFrame, aSlotURL, false );
455 : }
456 :
457 0 : if ( !!aImage )
458 0 : pSVMenu->SetItemImage( nSlotId, aImage );
459 : }
460 :
461 0 : if ( !IsItemHidden_Impl(nSlotId, bOleServer, bMac) )
462 0 : ++nVisibleItems;
463 : else
464 0 : pSVMenu->RemoveItem( nSVPos-- );
465 0 : break;
466 : }
467 :
468 : case MenuItemType::IMAGE:
469 : //! not implemented
470 0 : break;
471 :
472 : case MenuItemType::SEPARATOR:
473 : //! not implemented
474 0 : break;
475 : default:
476 0 : break; // DONTKNOW and STRINGIMAGE not handled.
477 : }
478 : }
479 0 : }
480 0 : pBindings->LEAVEREGISTRATIONS(); --nLocks;
481 0 : }
482 :
483 :
484 :
485 : // called on activation of the SV-Menu
486 :
487 0 : IMPL_LINK_NOARG( SfxVirtualMenu, Highlight )
488 : {
489 :
490 0 : return sal_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::MenuConfiguration::Attributes* pMenuAttributes =
515 0 : reinterpret_cast< ::framework::MenuConfiguration::Attributes*>(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::MenuConfiguration::Attributes* pMenuAttributes =
583 0 : reinterpret_cast< ::framework::MenuConfiguration::Attributes*>(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 0 : sal_uInt32 nAddonsPopupPrefixLen = ADDONSPOPUPMENU_URL_PREFIX.getLength();
627 :
628 0 : for ( sal_uInt16 nPos = 0; nPos < nCount; ++nPos )
629 : {
630 0 : sal_uInt16 nSID = pSVMenu->GetItemId(nPos);
631 0 : SfxMenuControl &rCtrl = pItems[nPos];
632 : // found the Sub-Menu in question?
633 0 : bool bFound = pSVMenu->GetPopupMenu(nSID) == pMenu;
634 0 : SfxVirtualMenu *pSubMenu = rCtrl.GetPopupMenu();
635 :
636 0 : if ( bFound )
637 : {
638 : // Only a binded Menu-Controller as already an Id!
639 0 : if ( !rCtrl.GetId() )
640 : {
641 0 : bIsAddonPopupMenu = false;
642 : DBG_ASSERT( !pSubMenu, "Popup already exists!");
643 :
644 : // Check if the popup is an Add-On popup menu
645 : // Either the popup menu has a special ID or a special command URL prefix!
646 0 : OUString aCommand = pSVMenu->GetItemCommand( nSID );
647 0 : if ( ( nSID == SID_ADDONS ) ||
648 0 : ( nSID == SID_ADDONHELP ) ||
649 0 : (( (sal_uInt32)aCommand.getLength() > nAddonsPopupPrefixLen ) &&
650 0 : ( aCommand.startsWith( ADDONSPOPUPMENU_URL_PREFIX ) ) ) )
651 0 : bIsAddonPopupMenu = true;
652 :
653 : // Create VirtualMenu for Sub-Menu
654 0 : bool bRes = bResCtor;
655 : pSubMenu = new SfxVirtualMenu( nSID, this,
656 0 : *pMenu, false, *pBindings, bOLE, bRes, bIsAddonPopupMenu );
657 :
658 : SAL_INFO("sfx", "New VirtualMenu " << pSubMenu << " created");
659 :
660 0 : rCtrl.Bind( this, nSID, *pSubMenu, pSVMenu->GetItemText(nSID), *pBindings );
661 :
662 : // Forward Activate
663 0 : pSubMenu->Bind_Impl( pMenu );
664 0 : pSubMenu->Activate( pMenu );
665 : }
666 : }
667 :
668 : // continue searching recursively (SV Activate only the menu itself
669 : // and Top-Menu)
670 0 : if ( !bFound && pSubMenu )
671 0 : bFound = pSubMenu->Bind_Impl( pMenu );
672 :
673 : // If found, break
674 0 : if ( bFound )
675 0 : return true;
676 : }
677 :
678 : // Not found in this submenu
679 0 : return false;
680 : }
681 :
682 0 : void SfxVirtualMenu::BindControllers()
683 : {
684 0 : pBindings->ENTERREGISTRATIONS();
685 :
686 : sal_uInt16 nPos;
687 0 : for ( nPos = 0; nPos < nCount; ++nPos )
688 : {
689 0 : SfxMenuControl& rCtrl = pItems[nPos];
690 0 : if ( rCtrl.IsBindable_Impl() && !rCtrl.GetPopupMenu() )
691 0 : rCtrl.ReBind();
692 : }
693 :
694 0 : SfxMenuCtrlArr_Impl& rCtrlArr = GetAppCtrl_Impl();
695 0 : for (SfxMenuCtrlArr_Impl::iterator i = rCtrlArr.begin();
696 0 : i != rCtrlArr.end(); ++i)
697 : {
698 0 : sal_uInt16 nSlotId = i->GetId();
699 0 : if (pSVMenu->GetItemCommand(nSlotId).isEmpty())
700 : {
701 0 : i->ReBind();
702 : }
703 : }
704 :
705 0 : pBindings->LEAVEREGISTRATIONS();
706 0 : bControllersUnBound = false;
707 0 : }
708 :
709 0 : void SfxVirtualMenu::UnbindControllers()
710 : {
711 0 : pBindings->ENTERREGISTRATIONS();
712 :
713 : sal_uInt16 nPos;
714 0 : for ( nPos = 0; nPos < nCount; ++nPos )
715 : {
716 0 : SfxMenuControl &rCtrl = pItems[nPos];
717 0 : if ( rCtrl.IsBound() )
718 0 : rCtrl.UnBind();
719 : }
720 :
721 0 : SfxMenuCtrlArr_Impl& rCtrlArr = GetAppCtrl_Impl();
722 0 : for (SfxMenuCtrlArr_Impl::iterator i = rCtrlArr.begin();
723 0 : i != rCtrlArr.end(); ++i)
724 : {
725 0 : if (i->IsBound())
726 : {
727 : // UnoController is not bound!
728 0 : i->UnBind();
729 : }
730 : }
731 :
732 0 : pBindings->LEAVEREGISTRATIONS();
733 0 : bControllersUnBound = true;
734 0 : }
735 :
736 :
737 :
738 0 : void SfxVirtualMenu::InsertAddOnsMenuItem( Menu* pMenu )
739 : {
740 : // Create special popup menu that is filled with the 3rd party components popup menu items
741 0 : ::framework::MenuConfiguration aConf( ::comphelper::getProcessComponentContext() );
742 0 : Reference<com::sun::star::frame::XFrame> xFrame( pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame().GetFrameInterface() );
743 :
744 0 : PopupMenu* pAddonMenu = NULL;
745 : try
746 : {
747 0 : Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
748 0 : pAddonMenu = framework::AddonMenuManager::CreateAddonMenu(xFrame, xContext);
749 : }
750 0 : catch ( const ::com::sun::star::lang::WrappedTargetException& )
751 : {
752 : }
753 :
754 : // Create menu item at the end of the tools popup menu for the addons popup menu
755 0 : if ( pAddonMenu && pAddonMenu->GetItemCount() > 0 )
756 : {
757 0 : sal_uInt16 nItemCount = pMenu->GetItemCount();
758 0 : OUString aAddonsTitle(SfxResId(STR_MENU_ADDONS).toString());
759 0 : if ( nItemCount > 0 && pMenu->GetItemType( nItemCount-1 ) != MenuItemType::SEPARATOR )
760 0 : pMenu->InsertSeparator();
761 0 : pMenu->InsertItem( SID_ADDONS, aAddonsTitle );
762 0 : pMenu->SetPopupMenu( SID_ADDONS, pAddonMenu );
763 :
764 0 : if ( Application::GetSettings().GetStyleSettings().GetUseImagesInMenus() )
765 : {
766 0 : OUString aSlotURL( "slot:" );
767 0 : aSlotURL += OUString::number( SID_ADDONS);
768 0 : pMenu->SetItemImage( SID_ADDONS, GetImage( xFrame, aSlotURL, false ));
769 0 : }
770 : }
771 : else
772 0 : delete pAddonMenu;
773 0 : }
774 :
775 :
776 :
777 : // called on activation of the SV-Menu
778 :
779 0 : IMPL_LINK( SfxVirtualMenu, Activate, Menu *, pMenu )
780 : {
781 : SAL_INFO(
782 : "sfx",
783 : "SfxVirtualMenu " << this << " activated " << pMenu << ", own "
784 : << pSVMenu);
785 :
786 : // MI: for what was it still good for?
787 : // MBA: seemes to be an old QAP-Hack( checked-in in rev.1.41 ! )
788 :
789 0 : if ( pMenu )
790 : {
791 0 : bool bDontHide = SvtMenuOptions().IsEntryHidingEnabled();
792 0 : sal_uInt16 nFlag = pMenu->GetMenuFlags();
793 0 : if ( bDontHide )
794 0 : nFlag &= ~MENU_FLAG_HIDEDISABLEDENTRIES;
795 : else
796 0 : nFlag |= MENU_FLAG_HIDEDISABLEDENTRIES;
797 0 : pMenu->SetMenuFlags( nFlag );
798 : }
799 :
800 : // Own StarView-Menu
801 0 : if ( pMenu == pSVMenu )
802 : {
803 : // Prevent Double Activate
804 0 : if ( bIsActive )
805 0 : return sal_True;
806 :
807 : // ggf. Pick-Menu erzeugen
808 0 : if ( pParent && pSVMenu == pParent->pPickMenu )
809 : {
810 0 : SfxPickList::Get().CreateMenuEntries( pParent->pPickMenu );
811 : }
812 : else
813 0 : pPickMenu = pSVMenu->GetPopupMenu(SID_PICKLIST);
814 :
815 0 : if ( pParent && pSVMenu == pParent->pWindowMenu )
816 : {
817 : // update window list
818 0 : ::std::vector< OUString > aNewWindowListVector;
819 0 : Reference< XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );;
820 :
821 0 : sal_uInt16 nActiveItemId = 0;
822 0 : sal_uInt16 nItemId = START_ITEMID_WINDOWLIST;
823 :
824 0 : Reference< XFrame > xCurrentFrame = xDesktop->getCurrentFrame();
825 0 : Reference< XIndexAccess > xList ( xDesktop->getFrames(), UNO_QUERY );
826 0 : sal_Int32 nFrameCount = xList->getCount();
827 0 : for( sal_Int32 i=0; i<nFrameCount; ++i )
828 : {
829 0 : Reference< XFrame > xFrame;
830 0 : Any aVal = xList->getByIndex(i);
831 0 : if (!(aVal>>=xFrame) || !xFrame.is() )
832 0 : continue;
833 :
834 0 : if ( xFrame == xCurrentFrame )
835 0 : nActiveItemId = nItemId;
836 :
837 0 : vcl::Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
838 0 : if ( pWin && pWin->IsVisible() )
839 : {
840 0 : aNewWindowListVector.push_back( pWin->GetText() );
841 0 : ++nItemId;
842 : }
843 0 : }
844 :
845 0 : int nItemCount = pMenu->GetItemCount();
846 :
847 0 : if ( nItemCount > 0 )
848 : {
849 : // remove all old window list entries from menu
850 0 : sal_uInt16 nPos = pMenu->GetItemPos( START_ITEMID_WINDOWLIST );
851 0 : for ( sal_uInt16 n = nPos; n < pMenu->GetItemCount(); )
852 0 : pMenu->RemoveItem( n );
853 :
854 0 : if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MenuItemType::SEPARATOR )
855 0 : pMenu->RemoveItem( pMenu->GetItemCount()-1 );
856 : }
857 :
858 0 : if ( aNewWindowListVector.size() > 0 )
859 : {
860 : // append new window list entries to menu
861 0 : pMenu->InsertSeparator();
862 0 : nItemId = START_ITEMID_WINDOWLIST;
863 0 : for ( sal_uInt32 i = 0; i < aNewWindowListVector.size(); i++ )
864 : {
865 0 : pMenu->InsertItem( nItemId, aNewWindowListVector.at( i ), MenuItemBits::RADIOCHECK );
866 0 : if ( nItemId == nActiveItemId )
867 0 : pMenu->CheckItem( nItemId );
868 0 : ++nItemId;
869 : }
870 0 : }
871 : }
872 : else
873 0 : pWindowMenu = pSVMenu->GetPopupMenu(SID_MDIWINDOWLIST);
874 :
875 0 : if ( !pParent && pSVMenu->IsMenuBar() && !pAddonsMenu )
876 : {
877 : // Store Add-Ons parents of our runtime menu items
878 0 : pAddonsMenu = pSVMenu->GetPopupMenu( SID_ADDONLIST );
879 : }
880 :
881 : // Provides consistency to the Status
882 0 : if ( bControllersUnBound )
883 0 : BindControllers();
884 :
885 0 : pBindings->GetDispatcher_Impl()->Flush();
886 0 : for ( sal_uInt16 nPos = 0; nPos < nCount; ++nPos )
887 : {
888 0 : sal_uInt16 nSlotId = (pItems+nPos)->GetId();
889 0 : if ( nSlotId && nSlotId > END_ITEMID_WINDOWLIST )
890 0 : pBindings->Update(nSlotId);
891 : }
892 :
893 0 : pBindings->Update( SID_IMAGE_ORIENTATION );
894 :
895 : // Supress the Status updates until Deactivate
896 0 : pBindings->ENTERREGISTRATIONS(); ++nLocks; bIsActive = true;
897 :
898 0 : return sal_True;
899 : }
900 : else
901 : {
902 : // Find the VirtualMenu for the SubMenu and if possible, bind a
903 : // VirtualMenu
904 0 : bool bRet = pMenu ? Bind_Impl(pMenu) : false;
905 : #ifdef DBG_UTIL
906 : if ( !bRet)
907 : DBG_WARNING( "W1: Virtual menu could not be created!" );
908 : #endif
909 0 : return long(bRet);
910 : }
911 : }
912 :
913 :
914 :
915 0 : IMPL_LINK( SfxVirtualMenu, Deactivate, Menu *, pMenu )
916 : {
917 : SAL_INFO(
918 : "sfx",
919 : "SfxVirtualMenu " << this << " deactivated " << pMenu << ", own "
920 : << pSVMenu);
921 0 : if ( bIsActive && ( 0 == pMenu || pMenu == pSVMenu ) )
922 : {
923 : // All controllers can be unbinded all the way up to the Menubar,
924 : // when the menu is disabled (= closed)
925 0 : if ( pParent )
926 0 : UnbindControllers();
927 0 : pBindings->LEAVEREGISTRATIONS(); --nLocks; bIsActive = false;
928 : }
929 0 : return sal_True;
930 : }
931 :
932 :
933 : // called on activation of the SV-Menu
934 :
935 0 : IMPL_LINK( SfxVirtualMenu, Select, Menu *, pMenu )
936 : {
937 0 : sal_uInt16 nSlotId = (sal_uInt16) pMenu->GetCurItemId();
938 : SAL_INFO(
939 : "sfx",
940 : "SfxVirtualMenu " << this << " selected " << nSlotId << " from "
941 : << pMenu);
942 :
943 0 : if ( nSlotId >= START_ITEMID_WINDOWLIST && nSlotId <= END_ITEMID_WINDOWLIST )
944 : {
945 : // window list menu item selected
946 0 : Reference< XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
947 0 : sal_uInt16 nTaskId = START_ITEMID_WINDOWLIST;
948 0 : Reference< XIndexAccess > xList( xDesktop->getFrames(), UNO_QUERY );
949 0 : sal_Int32 nFrameCount = xList->getCount();
950 0 : for ( sal_Int32 i=0; i<nFrameCount; ++i )
951 : {
952 0 : Any aItem = xList->getByIndex(i);
953 0 : Reference< XFrame > xFrame;
954 0 : if (( aItem >>= xFrame ) && xFrame.is() && nTaskId == nSlotId )
955 : {
956 0 : vcl::Window* pWin = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() );
957 0 : pWin->GrabFocus();
958 0 : pWin->ToTop( TOTOP_RESTOREWHENMIN );
959 0 : break;
960 : }
961 :
962 0 : nTaskId++;
963 0 : }
964 :
965 0 : return sal_True;
966 : }
967 0 : else if ( nSlotId >= START_ITEMID_PICKLIST && nSlotId <= END_ITEMID_PICKLIST )
968 : {
969 0 : SfxPickList::Get().ExecuteMenuEntry( nSlotId );
970 0 : return sal_True;
971 : }
972 :
973 0 : OUString sCommand = pMenu->GetItemCommand(nSlotId);
974 0 : if (!sCommand.isEmpty())
975 0 : pBindings->ExecuteCommand_Impl(sCommand);
976 : else
977 0 : pBindings->Execute(nSlotId);
978 :
979 0 : return sal_True;
980 : }
981 :
982 :
983 :
984 : // returns the associated StarView-menu
985 :
986 :
987 :
988 :
989 : // set the checkmark of the specified item
990 :
991 0 : void SfxVirtualMenu::CheckItem( sal_uInt16 nItemId, bool bCheck )
992 : {
993 : DBG_ASSERT( pSVMenu != 0, "" );
994 0 : if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND )
995 0 : pSVMenu->CheckItem( nItemId, bCheck );
996 0 : }
997 :
998 :
999 : // set the enabled-state of the specified item
1000 :
1001 0 : void SfxVirtualMenu::EnableItem( sal_uInt16 nItemId, bool bEnable )
1002 : {
1003 : DBG_ASSERT( pSVMenu != 0, "" );
1004 :
1005 0 : if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND )
1006 0 : pSVMenu->EnableItem( nItemId, bEnable );
1007 0 : }
1008 :
1009 :
1010 : // set the text of the specified item
1011 :
1012 0 : void SfxVirtualMenu::SetItemText( sal_uInt16 nItemId, const OUString& rText )
1013 : {
1014 : DBG_ASSERT( pSVMenu != 0, "" );
1015 0 : if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND )
1016 0 : pSVMenu->SetItemText( nItemId, rText );
1017 0 : }
1018 :
1019 :
1020 :
1021 :
1022 0 : void SfxVirtualMenu::SetPopupMenu( sal_uInt16 nItemId, PopupMenu *pMenu )
1023 : {
1024 :
1025 0 : if (pSVMenu->GetItemPos( nItemId ) != MENU_ITEM_NOTFOUND )
1026 0 : GetSVMenu()->SetPopupMenu( nItemId, pMenu );
1027 0 : for ( sal_uInt16 n = 0; n < nCount; ++n )
1028 : {
1029 0 : SfxVirtualMenu *pSubMenu = (pItems+n)->GetPopupMenu();
1030 0 : if ( pSubMenu )
1031 0 : pSubMenu->SetPopupMenu( nItemId, pMenu );
1032 : }
1033 0 : }
1034 :
1035 :
1036 :
1037 : // Forces the initialization, which is otherwise only happens in Activate
1038 :
1039 0 : void SfxVirtualMenu::InitPopup( sal_uInt16 nPos, bool /*bOLE*/ )
1040 : {
1041 :
1042 0 : sal_uInt16 nSID = pSVMenu->GetItemId(nPos);
1043 0 : PopupMenu *pMenu = pSVMenu->GetPopupMenu( nSID );
1044 :
1045 : DBG_ASSERT( pMenu, "No popup exist here!");
1046 :
1047 0 : SfxMenuControl &rCtrl = pItems[nPos];
1048 0 : if ( !rCtrl.GetId() )
1049 : {
1050 : // Generate VirtualMenu for Sub-Menu
1051 0 : bool bRes = bResCtor;
1052 : SfxVirtualMenu *pSubMenu =
1053 0 : new SfxVirtualMenu(nSID, this, *pMenu, false, *pBindings, bOLE, bRes);
1054 :
1055 : SAL_INFO("sfx", "New VirtualMenu " << pSubMenu << " created");
1056 :
1057 0 : rCtrl.Bind( this, nSID, *pSubMenu, pSVMenu->GetItemText(nSID), *pBindings );
1058 : }
1059 0 : }
1060 :
1061 0 : void SfxVirtualMenu::InitializeHelp()
1062 : {
1063 0 : for ( sal_uInt16 nPos = 0; nPos<pSVMenu->GetItemCount(); ++nPos )
1064 : {
1065 0 : sal_uInt16 nSlotId = pSVMenu->GetItemId(nPos);
1066 0 : SfxMenuControl &rCtrl = pItems[nPos];
1067 0 : if ( nSlotId && !rCtrl.GetId() )
1068 : {
1069 0 : InitPopup( nPos, true );
1070 : }
1071 :
1072 0 : SfxVirtualMenu *pSubMenu = rCtrl.GetPopupMenu();
1073 0 : if ( pSubMenu )
1074 0 : pSubMenu->InitializeHelp();
1075 : }
1076 :
1077 0 : bHelpInitialized = true;
1078 951 : }
1079 :
1080 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|