Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <uielement/toolbarsmenucontroller.hxx>
21 :
22 : #include <algorithm>
23 :
24 : #include "services.h"
25 : #include <classes/resource.hrc>
26 : #include <classes/fwkresid.hxx>
27 : #include <framework/imageproducer.hxx>
28 : #include <framework/sfxhelperfunctions.hxx>
29 : #include <uiconfiguration/windowstateproperties.hxx>
30 :
31 : #include <com/sun/star/awt/XDevice.hpp>
32 : #include <com/sun/star/beans/PropertyValue.hpp>
33 : #include <com/sun/star/awt/MenuItemStyle.hpp>
34 : #include <com/sun/star/frame/ModuleManager.hpp>
35 : #include <com/sun/star/frame/XDispatchProvider.hpp>
36 : #include <com/sun/star/frame/theUICommandDescription.hpp>
37 : #include <com/sun/star/container/XNameContainer.hpp>
38 : #include <com/sun/star/beans/XPropertySet.hpp>
39 : #include <com/sun/star/frame/XLayoutManager.hpp>
40 : #include <com/sun/star/ui/XUIElementSettings.hpp>
41 : #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
42 : #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
43 : #include <com/sun/star/ui/UIElementType.hpp>
44 : #include <com/sun/star/ui/theWindowStateConfiguration.hpp>
45 :
46 : #include <vcl/menu.hxx>
47 : #include <vcl/svapp.hxx>
48 : #include <vcl/i18nhelp.hxx>
49 : #include <vcl/image.hxx>
50 : #include <vcl/settings.hxx>
51 : #include <rtl/ustrbuf.hxx>
52 : #include <toolkit/helper/vclunohelper.hxx>
53 : #include <vcl/window.hxx>
54 : #include <svtools/menuoptions.hxx>
55 : #include <unotools/cmdoptions.hxx>
56 : #include <svtools/miscopt.hxx>
57 :
58 : // Defines
59 :
60 : using namespace ::com::sun::star;
61 : using namespace ::com::sun::star::uno;
62 : using namespace ::com::sun::star::lang;
63 : using namespace ::com::sun::star::frame;
64 : using namespace ::com::sun::star::beans;
65 : using namespace ::com::sun::star::util;
66 : using namespace ::com::sun::star::container;
67 : using namespace ::com::sun::star::ui;
68 :
69 : static const char CONFIGURE_TOOLBARS_CMD[] = "ConfigureDialog";
70 : static const char CONFIGURE_TOOLBARS[] = ".uno:ConfigureDialog";
71 : static const char CMD_COLORBAR[] = ".uno:ColorControl";
72 : static const char CMD_FORMULABAR[] = ".uno:InsertFormula";
73 : static const char CMD_INPUTLINEBAR[] = ".uno:InputLineVisible";
74 : static const char CMD_RESTOREVISIBILITY[] = ".cmd:RestoreVisibility";
75 : static const char ITEM_DESCRIPTOR_RESOURCEURL[] = "ResourceURL";
76 : static const char ITEM_DESCRIPTOR_UINAME[] = "UIName";
77 : static const char STATIC_PRIVATE_TB_RESOURCE[] = "private:resource/toolbar/";
78 :
79 : static const char STATIC_CMD_PART[] = ".uno:AvailableToolbars?Toolbar:string=";
80 : static const char STATIC_INTERNAL_CMD_PART[] = ".cmd:";
81 :
82 : namespace framework
83 : {
84 :
85 : typedef std::unordered_map< OUString, OUString, OUStringHash, std::equal_to< OUString > > ToolbarHashMap;
86 :
87 325 : struct ToolBarEntry
88 : {
89 : OUString aUIName;
90 : OUString aCommand;
91 : bool bVisible;
92 : bool bContextSensitive;
93 : const CollatorWrapper* pCollatorWrapper;
94 : };
95 :
96 119 : bool CompareToolBarEntry( const ToolBarEntry& aOne, const ToolBarEntry& aTwo )
97 : {
98 119 : sal_Int32 nComp = aOne.pCollatorWrapper->compareString( aOne.aUIName, aTwo.aUIName );
99 :
100 119 : if ( nComp < 0 )
101 77 : return true;
102 : else
103 42 : return false;
104 : }
105 :
106 1 : Reference< XLayoutManager > getLayoutManagerFromFrame( const Reference< XFrame >& rFrame )
107 : {
108 1 : Reference< XPropertySet > xPropSet( rFrame, UNO_QUERY );
109 1 : Reference< XLayoutManager > xLayoutManager;
110 :
111 : try
112 : {
113 1 : xPropSet->getPropertyValue("LayoutManager") >>= xLayoutManager;
114 : }
115 0 : catch ( const UnknownPropertyException& )
116 : {
117 : }
118 :
119 1 : return xLayoutManager;
120 : }
121 :
122 18 : struct ToolBarInfo
123 : {
124 : OUString aToolBarResName;
125 : OUString aToolBarUIName;
126 : };
127 :
128 83 : DEFINE_XSERVICEINFO_MULTISERVICE_2 ( ToolbarsMenuController ,
129 : OWeakObject ,
130 : SERVICENAME_POPUPMENUCONTROLLER ,
131 : IMPLEMENTATIONNAME_TOOLBARSMENUCONTROLLER
132 : )
133 :
134 4 : DEFINE_INIT_SERVICE ( ToolbarsMenuController, {} )
135 :
136 4 : ToolbarsMenuController::ToolbarsMenuController( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& xContext ) :
137 : svt::PopupMenuControllerBase( xContext ),
138 : m_xContext( xContext ),
139 : m_aPropUIName( "UIName" ),
140 : m_aPropResourceURL( "ResourceURL" ),
141 : m_bModuleIdentified( false ),
142 : m_bResetActive( false ),
143 4 : m_aIntlWrapper( xContext, Application::GetSettings().GetLanguageTag() )
144 : {
145 4 : }
146 :
147 8 : ToolbarsMenuController::~ToolbarsMenuController()
148 : {
149 8 : }
150 :
151 3 : void ToolbarsMenuController::addCommand(
152 : Reference< css::awt::XPopupMenu >& rPopupMenu, const OUString& rCommandURL, const OUString& rLabel )
153 : {
154 3 : sal_uInt16 nItemId = m_xPopupMenu->getItemCount()+1;
155 :
156 3 : OUString aLabel;
157 3 : if ( rLabel.isEmpty() )
158 2 : aLabel = getUINameFromCommand( rCommandURL );
159 : else
160 1 : aLabel = rLabel;
161 :
162 3 : rPopupMenu->insertItem( nItemId, aLabel, 0, nItemId );
163 3 : rPopupMenu->setCommand( nItemId, rCommandURL );
164 :
165 3 : bool bInternal = rCommandURL.startsWith( STATIC_INTERNAL_CMD_PART );
166 3 : if ( !bInternal )
167 : {
168 2 : if ( !getDispatchFromCommandURL( rCommandURL ).is() )
169 0 : m_xPopupMenu->enableItem( nItemId, sal_False );
170 : }
171 :
172 6 : SolarMutexGuard aSolarMutexGuard;
173 :
174 6 : Image aImage;
175 3 : const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
176 :
177 3 : if ( rSettings.GetUseImagesInMenus() )
178 3 : aImage = GetImageFromURL( m_xFrame, rCommandURL, false );
179 :
180 3 : VCLXPopupMenu* pPopupMenu = static_cast<VCLXPopupMenu *>(VCLXPopupMenu::GetImplementation( rPopupMenu ));
181 3 : if ( pPopupMenu )
182 : {
183 3 : PopupMenu* pVCLPopupMenu = static_cast<PopupMenu *>(pPopupMenu->GetMenu());
184 3 : if ( !!aImage )
185 1 : pVCLPopupMenu->SetItemImage( nItemId, aImage );
186 : }
187 :
188 6 : m_aCommandVector.push_back( rCommandURL );
189 3 : }
190 :
191 2 : Reference< XDispatch > ToolbarsMenuController::getDispatchFromCommandURL( const OUString& rCommandURL )
192 : {
193 2 : URL aTargetURL;
194 4 : Reference< XURLTransformer > xURLTransformer;
195 4 : Reference< XFrame > xFrame;
196 :
197 : {
198 2 : SolarMutexGuard aSolarMutexGuard;
199 2 : xURLTransformer = m_xURLTransformer;
200 2 : xFrame = m_xFrame;
201 : }
202 :
203 2 : aTargetURL.Complete = rCommandURL;
204 2 : xURLTransformer->parseStrict( aTargetURL );
205 4 : Reference< XDispatchProvider > xDispatchProvider( xFrame, UNO_QUERY );
206 2 : if ( xDispatchProvider.is() )
207 2 : return xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
208 : else
209 2 : return Reference< XDispatch >();
210 : }
211 :
212 : // private function
213 2 : OUString ToolbarsMenuController::getUINameFromCommand( const OUString& rCommandURL )
214 : {
215 2 : OUString aLabel;
216 :
217 2 : if ( !m_bModuleIdentified )
218 : {
219 : try
220 : {
221 2 : Reference< XModuleManager2 > xModuleManager = ModuleManager::create( m_xContext );
222 2 : m_aModuleIdentifier = xModuleManager->identify( m_xFrame );
223 4 : Reference< XNameAccess > xNameAccess = frame::theUICommandDescription::get( m_xContext );
224 4 : xNameAccess->getByName( m_aModuleIdentifier ) >>= m_xUICommandDescription;
225 : }
226 0 : catch ( const Exception& )
227 : {
228 : }
229 : }
230 :
231 2 : if ( m_xUICommandDescription.is() )
232 : {
233 : try
234 : {
235 2 : Sequence< PropertyValue > aPropSeq;
236 4 : OUString aStr;
237 2 : if ( m_xUICommandDescription->getByName( rCommandURL ) >>= aPropSeq )
238 : {
239 2 : for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ )
240 : {
241 2 : if ( aPropSeq[i].Name == "Label" )
242 : {
243 2 : aPropSeq[i].Value >>= aStr;
244 2 : break;
245 : }
246 : }
247 : }
248 4 : aLabel = aStr;
249 : }
250 0 : catch ( const Exception& )
251 : {
252 : }
253 : }
254 :
255 2 : return aLabel;
256 : }
257 :
258 3 : static void fillHashMap( const Sequence< Sequence< ::com::sun::star::beans::PropertyValue > >& rSeqToolBars,
259 : ToolbarHashMap& rHashMap )
260 : {
261 45 : for ( sal_Int32 i = 0; i < rSeqToolBars.getLength(); i++ )
262 : {
263 42 : OUString aResourceURL;
264 84 : OUString aUIName;
265 42 : const PropertyValue* pProperties = rSeqToolBars[i].getConstArray();
266 126 : for ( sal_Int32 j = 0; j < rSeqToolBars[i].getLength(); j++ )
267 : {
268 84 : if ( pProperties[j].Name == ITEM_DESCRIPTOR_RESOURCEURL )
269 42 : pProperties[j].Value >>= aResourceURL;
270 42 : else if ( pProperties[j].Name == ITEM_DESCRIPTOR_UINAME )
271 42 : pProperties[j].Value >>= aUIName;
272 : }
273 :
274 210 : if ( !aResourceURL.isEmpty() &&
275 210 : rHashMap.find( aResourceURL ) == rHashMap.end() )
276 40 : rHashMap.insert( ToolbarHashMap::value_type( aResourceURL, aUIName ));
277 42 : }
278 3 : }
279 :
280 : // private function
281 1 : Sequence< Sequence< com::sun::star::beans::PropertyValue > > ToolbarsMenuController::getLayoutManagerToolbars( const Reference< ::com::sun::star::frame::XLayoutManager >& rLayoutManager )
282 : {
283 1 : std::vector< ToolBarInfo > aToolBarArray;
284 2 : Sequence< Reference< XUIElement > > aUIElements = rLayoutManager->getElements();
285 6 : for ( sal_Int32 i = 0; i < aUIElements.getLength(); i++ )
286 : {
287 5 : Reference< XUIElement > xUIElement( aUIElements[i] );
288 10 : Reference< XPropertySet > xPropSet( aUIElements[i], UNO_QUERY );
289 5 : if ( xPropSet.is() && xUIElement.is() )
290 : {
291 : try
292 : {
293 5 : OUString aResName;
294 5 : sal_Int16 nType( -1 );
295 5 : xPropSet->getPropertyValue("Type") >>= nType;
296 5 : xPropSet->getPropertyValue("ResourceURL") >>= aResName;
297 :
298 8 : if (( nType == ::com::sun::star::ui::UIElementType::TOOLBAR ) &&
299 3 : !aResName.isEmpty() )
300 : {
301 3 : ToolBarInfo aToolBarInfo;
302 :
303 3 : aToolBarInfo.aToolBarResName = aResName;
304 :
305 6 : SolarMutexGuard aGuard;
306 6 : Reference< css::awt::XWindow > xWindow( xUIElement->getRealInterface(), UNO_QUERY );
307 3 : vcl::Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
308 3 : if ( pWindow )
309 3 : aToolBarInfo.aToolBarUIName = pWindow->GetText();
310 :
311 6 : aToolBarArray.push_back( aToolBarInfo );
312 5 : }
313 : }
314 0 : catch ( const Exception& )
315 : {
316 : }
317 : }
318 5 : }
319 :
320 2 : Sequence< com::sun::star::beans::PropertyValue > aTbSeq( 2 );
321 1 : aTbSeq[0].Name = m_aPropUIName;
322 1 : aTbSeq[1].Name = m_aPropResourceURL;
323 :
324 1 : Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeq( aToolBarArray.size() );
325 1 : const sal_uInt32 nCount = aToolBarArray.size();
326 4 : for ( sal_uInt32 i = 0; i < nCount; i++ )
327 : {
328 3 : aTbSeq[0].Value <<= aToolBarArray[i].aToolBarUIName;
329 3 : aTbSeq[1].Value <<= aToolBarArray[i].aToolBarResName;
330 3 : aSeq[i] = aTbSeq;
331 : }
332 :
333 2 : return aSeq;
334 : }
335 :
336 :
337 1 : void ToolbarsMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu )
338 : {
339 1 : if( SvtMiscOptions().DisableUICustomization() )
340 1 : return;
341 :
342 1 : SolarMutexGuard aSolarMutexGuard;
343 1 : resetPopupMenu( rPopupMenu );
344 :
345 1 : m_aCommandVector.clear();
346 :
347 : // Retrieve layout manager for additional information
348 2 : OUString aEmptyString;
349 2 : Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( m_xFrame ));
350 :
351 1 : m_bResetActive = false;
352 1 : if ( xLayoutManager.is() )
353 : {
354 1 : ToolbarHashMap aToolbarHashMap;
355 :
356 1 : if ( m_xDocCfgMgr.is() )
357 : {
358 : Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqDocToolBars =
359 1 : m_xDocCfgMgr->getUIElementsInfo( UIElementType::TOOLBAR );
360 1 : fillHashMap( aSeqDocToolBars, aToolbarHashMap );
361 : }
362 :
363 1 : if ( m_xModuleCfgMgr.is() )
364 : {
365 : Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqToolBars =
366 1 : m_xModuleCfgMgr->getUIElementsInfo( UIElementType::TOOLBAR );
367 1 : fillHashMap( aSeqToolBars, aToolbarHashMap );
368 : }
369 :
370 2 : std::vector< ToolBarEntry > aSortedTbs;
371 2 : OUString aStaticCmdPart( STATIC_CMD_PART );
372 :
373 2 : Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqFrameToolBars = getLayoutManagerToolbars( xLayoutManager );
374 1 : fillHashMap( aSeqFrameToolBars, aToolbarHashMap );
375 :
376 1 : ToolbarHashMap::const_iterator pIter = aToolbarHashMap.begin();
377 42 : while ( pIter != aToolbarHashMap.end() )
378 : {
379 40 : OUString aUIName = pIter->second;
380 40 : bool bHideFromMenu( false );
381 40 : bool bContextSensitive( false );
382 79 : if ( aUIName.isEmpty() &&
383 39 : m_xPersistentWindowState.is() )
384 : {
385 39 : bool bVisible( false );
386 :
387 : try
388 : {
389 39 : Sequence< PropertyValue > aWindowState;
390 78 : Any a( m_xPersistentWindowState->getByName( pIter->first ));
391 :
392 39 : if ( a >>= aWindowState )
393 : {
394 475 : for ( sal_Int32 i = 0; i < aWindowState.getLength(); i++ )
395 : {
396 436 : if ( aWindowState[i].Name == WINDOWSTATE_PROPERTY_UINAME )
397 39 : aWindowState[i].Value >>= aUIName;
398 397 : else if ( aWindowState[i].Name == WINDOWSTATE_PROPERTY_HIDEFROMENU )
399 39 : aWindowState[i].Value >>= bHideFromMenu;
400 358 : else if ( aWindowState[i].Name == WINDOWSTATE_PROPERTY_CONTEXT )
401 39 : aWindowState[i].Value >>= bContextSensitive;
402 319 : else if ( aWindowState[i].Name == WINDOWSTATE_PROPERTY_VISIBLE )
403 39 : aWindowState[i].Value >>= bVisible;
404 : }
405 39 : }
406 : }
407 0 : catch ( const Exception& )
408 : {
409 : }
410 :
411 : // Check if we have to enable/disable "Reset" menu item
412 39 : if ( bContextSensitive && !bVisible )
413 1 : m_bResetActive = true;
414 :
415 : }
416 :
417 40 : if ( !aUIName.isEmpty() && !bHideFromMenu )
418 : {
419 24 : ToolBarEntry aTbEntry;
420 24 : aTbEntry.aUIName = aUIName;
421 24 : aTbEntry.aCommand = pIter->first;
422 24 : aTbEntry.bVisible = xLayoutManager->isElementVisible( pIter->first );
423 24 : aTbEntry.bContextSensitive = bContextSensitive;
424 24 : aTbEntry.pCollatorWrapper = m_aIntlWrapper.getCaseCollator();
425 24 : aSortedTbs.push_back( aTbEntry );
426 : }
427 40 : ++pIter;
428 40 : }
429 :
430 : // sort toolbars
431 1 : std::sort( aSortedTbs.begin(), aSortedTbs.end(), CompareToolBarEntry );
432 :
433 1 : sal_Int16 nIndex( 1 );
434 1 : const sal_uInt32 nCount = aSortedTbs.size();
435 25 : for ( sal_uInt32 i = 0; i < nCount; i++ )
436 : {
437 24 : sal_uInt16 nItemCount = m_xPopupMenu->getItemCount();
438 24 : m_xPopupMenu->insertItem( nIndex, aSortedTbs[i].aUIName, css::awt::MenuItemStyle::CHECKABLE, nItemCount );
439 24 : if ( aSortedTbs[i].bVisible )
440 2 : m_xPopupMenu->checkItem( nIndex, sal_True );
441 :
442 : {
443 24 : SolarMutexGuard aGuard;
444 24 : VCLXPopupMenu* pXPopupMenu = static_cast<VCLXPopupMenu *>(VCLXMenu::GetImplementation( m_xPopupMenu ));
445 24 : PopupMenu* pVCLPopupMenu = pXPopupMenu ? static_cast<PopupMenu *>(pXPopupMenu->GetMenu()) : NULL;
446 : assert(pVCLPopupMenu);
447 24 : if (pVCLPopupMenu)
448 24 : pVCLPopupMenu->SetUserValue( nIndex, sal_uIntPtr( aSortedTbs[i].bContextSensitive ? 1L : 0L ));
449 : }
450 :
451 : // use VCL popup menu pointer to set vital information that are not part of the awt implementation
452 24 : OUStringBuffer aStrBuf( aStaticCmdPart );
453 :
454 24 : sal_Int32 n = aSortedTbs[i].aCommand.lastIndexOf( '/' );
455 24 : if (( n > 0 ) && (( n+1 ) < aSortedTbs[i].aCommand.getLength() ))
456 24 : aStrBuf.append( aSortedTbs[i].aCommand.copy( n+1 ));
457 :
458 48 : OUString aCmd( aStrBuf.makeStringAndClear() );
459 :
460 : // Store complete uno-command so it can also be dispatched. This is necessary to support
461 : // the test tool!
462 24 : rPopupMenu->setCommand( nIndex, aCmd );
463 24 : ++nIndex;
464 24 : }
465 :
466 : // Create commands for non-toolbars
467 2 : if ( m_aModuleIdentifier == "com.sun.star.text.TextDocument" ||
468 0 : m_aModuleIdentifier == "com.sun.star.text.WebDocument" ||
469 0 : m_aModuleIdentifier == "com.sun.star.text.GlobalDocument" ||
470 0 : m_aModuleIdentifier == "com.sun.star.drawing.DrawingDocument" ||
471 1 : m_aModuleIdentifier == "com.sun.star.presentation.PresentationDocument" ||
472 0 : m_aModuleIdentifier == "com.sun.star.sheet.SpreadsheetDocument" )
473 : {
474 2 : if ( m_aModuleIdentifier == "com.sun.star.drawing.DrawingDocument" ||
475 1 : m_aModuleIdentifier == "com.sun.star.presentation.PresentationDocument" )
476 0 : addCommand( m_xPopupMenu, OUString( CMD_COLORBAR ), aEmptyString );
477 1 : else if ( m_aModuleIdentifier == "com.sun.star.sheet.SpreadsheetDocument" )
478 0 : addCommand( m_xPopupMenu, OUString( CMD_INPUTLINEBAR ), aEmptyString );
479 : else
480 1 : addCommand( m_xPopupMenu, OUString( CMD_FORMULABAR ), aEmptyString );
481 : }
482 :
483 1 : bool bAddCommand( true );
484 2 : SvtCommandOptions aCmdOptions;
485 2 : OUString aConfigureToolbar( CONFIGURE_TOOLBARS );
486 :
487 1 : if ( aCmdOptions.HasEntries( SvtCommandOptions::CMDOPTION_DISABLED ))
488 : {
489 0 : if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED,
490 0 : OUString( CONFIGURE_TOOLBARS_CMD )))
491 0 : bAddCommand = false;
492 : }
493 :
494 1 : if ( bAddCommand )
495 : {
496 : // Create command for configure
497 1 : if ( m_xPopupMenu->getItemCount() > 0 )
498 : {
499 1 : sal_uInt16 nItemCount = m_xPopupMenu->getItemCount();
500 1 : m_xPopupMenu->insertSeparator( nItemCount+1 );
501 : }
502 :
503 1 : addCommand( m_xPopupMenu, aConfigureToolbar, aEmptyString );
504 : }
505 :
506 : // Add separator if no configure has been added
507 1 : if ( !bAddCommand )
508 : {
509 : // Create command for configure
510 0 : if ( m_xPopupMenu->getItemCount() > 0 )
511 : {
512 0 : sal_uInt16 nItemCount = m_xPopupMenu->getItemCount();
513 0 : m_xPopupMenu->insertSeparator( nItemCount+1 );
514 : }
515 : }
516 :
517 2 : OUString aLabelStr(FWK_RESSTR(STR_RESTORE_TOOLBARS));
518 2 : OUString aRestoreCmd( CMD_RESTOREVISIBILITY );
519 2 : addCommand( m_xPopupMenu, aRestoreCmd, aLabelStr );
520 1 : }
521 : }
522 :
523 : // XEventListener
524 1 : void SAL_CALL ToolbarsMenuController::disposing( const EventObject& ) throw ( RuntimeException, std::exception )
525 : {
526 1 : Reference< css::awt::XMenuListener > xHolder(static_cast<OWeakObject *>(this), UNO_QUERY );
527 :
528 2 : osl::MutexGuard aLock( m_aMutex );
529 1 : m_xFrame.clear();
530 1 : m_xDispatch.clear();
531 1 : m_xDocCfgMgr.clear();
532 1 : m_xModuleCfgMgr.clear();
533 1 : m_xContext.clear();
534 :
535 1 : if ( m_xPopupMenu.is() )
536 1 : m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(static_cast<OWeakObject *>(this), UNO_QUERY ));
537 2 : m_xPopupMenu.clear();
538 1 : }
539 :
540 : // XStatusListener
541 1 : void SAL_CALL ToolbarsMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException, std::exception )
542 : {
543 1 : OUString aFeatureURL( Event.FeatureURL.Complete );
544 :
545 : // All other status events will be processed here
546 2 : osl::ClearableMutexGuard aLock( m_aMutex );
547 2 : Reference< css::awt::XPopupMenu > xPopupMenu( m_xPopupMenu );
548 1 : aLock.clear();
549 :
550 1 : if ( xPopupMenu.is() )
551 : {
552 0 : SolarMutexGuard aGuard;
553 0 : VCLXPopupMenu* pXPopupMenu = static_cast<VCLXPopupMenu *>(VCLXMenu::GetImplementation( xPopupMenu ));
554 0 : PopupMenu* pVCLPopupMenu = pXPopupMenu ? static_cast<PopupMenu *>(pXPopupMenu->GetMenu()) : NULL;
555 :
556 : SAL_WARN_IF(!pVCLPopupMenu, "framework", "worrying lack of popup menu");
557 0 : if (!pVCLPopupMenu)
558 1 : return;
559 :
560 0 : bool bSetCheckmark = false;
561 0 : bool bCheckmark = false;
562 0 : for ( sal_uInt16 i = 0; i < pVCLPopupMenu->GetItemCount(); i++ )
563 : {
564 0 : sal_uInt16 nId = pVCLPopupMenu->GetItemId( i );
565 0 : if ( nId == 0 )
566 0 : continue;
567 :
568 0 : OUString aCmd = pVCLPopupMenu->GetItemCommand( nId );
569 0 : if ( aCmd == aFeatureURL )
570 : {
571 : // Enable/disable item
572 0 : pVCLPopupMenu->EnableItem( nId, Event.IsEnabled );
573 :
574 : // Checkmark
575 0 : if ( Event.State >>= bCheckmark )
576 0 : bSetCheckmark = true;
577 :
578 0 : if ( bSetCheckmark )
579 0 : pVCLPopupMenu->CheckItem( nId, bCheckmark );
580 : else
581 : {
582 0 : OUString aItemText;
583 :
584 0 : if ( Event.State >>= aItemText )
585 0 : pVCLPopupMenu->SetItemText( nId, aItemText );
586 : }
587 : }
588 0 : }
589 1 : }
590 : }
591 :
592 : // XMenuListener
593 0 : void SAL_CALL ToolbarsMenuController::itemSelected( const css::awt::MenuEvent& rEvent ) throw (RuntimeException, std::exception)
594 : {
595 0 : Reference< css::awt::XPopupMenu > xPopupMenu;
596 0 : Reference< XComponentContext > xContext;
597 0 : Reference< XURLTransformer > xURLTransformer;
598 0 : Reference< XFrame > xFrame;
599 0 : Reference< XNameAccess > xPersistentWindowState;
600 :
601 0 : osl::ClearableMutexGuard aLock( m_aMutex );
602 0 : xPopupMenu = m_xPopupMenu;
603 0 : xContext = m_xContext;
604 0 : xURLTransformer = m_xURLTransformer;
605 0 : xFrame = m_xFrame;
606 0 : xPersistentWindowState = m_xPersistentWindowState;
607 0 : aLock.clear();
608 :
609 0 : if ( xPopupMenu.is() )
610 : {
611 0 : VCLXPopupMenu* pPopupMenu = static_cast<VCLXPopupMenu *>(VCLXPopupMenu::GetImplementation( xPopupMenu ));
612 0 : if ( pPopupMenu )
613 : {
614 0 : SolarMutexGuard aSolarMutexGuard;
615 0 : PopupMenu* pVCLPopupMenu = static_cast<PopupMenu *>(pPopupMenu->GetMenu());
616 :
617 0 : OUString aCmd( pVCLPopupMenu->GetItemCommand( rEvent.MenuId ));
618 0 : if ( aCmd.startsWith( STATIC_INTERNAL_CMD_PART ) )
619 : {
620 : // Command to restore the visibility of all context sensitive toolbars
621 0 : Reference< XNameReplace > xNameReplace( xPersistentWindowState, UNO_QUERY );
622 0 : if ( xPersistentWindowState.is() && xNameReplace.is() )
623 : {
624 : try
625 : {
626 0 : Sequence< OUString > aElementNames = xPersistentWindowState->getElementNames();
627 0 : sal_Int32 nCount = aElementNames.getLength();
628 0 : bool bRefreshToolbars( false );
629 :
630 0 : for ( sal_Int32 i = 0; i < nCount; i++ )
631 : {
632 : try
633 : {
634 0 : OUString aElementName = aElementNames[i];
635 0 : Sequence< PropertyValue > aWindowState;
636 :
637 0 : if ( xPersistentWindowState->getByName( aElementName ) >>= aWindowState )
638 : {
639 0 : bool bVisible( false );
640 0 : bool bContextSensitive( false );
641 0 : sal_Int32 nVisibleIndex( -1 );
642 0 : for ( sal_Int32 j = 0; j < aWindowState.getLength(); j++ )
643 : {
644 0 : if ( aWindowState[j].Name == WINDOWSTATE_PROPERTY_VISIBLE )
645 : {
646 0 : aWindowState[j].Value >>= bVisible;
647 0 : nVisibleIndex = j;
648 : }
649 0 : else if ( aWindowState[j].Name == WINDOWSTATE_PROPERTY_CONTEXT )
650 0 : aWindowState[j].Value >>= bContextSensitive;
651 : }
652 :
653 0 : if ( !bVisible && bContextSensitive && nVisibleIndex >= 0 )
654 : {
655 : // Default is: Every context sensitive toolbar is visible
656 0 : aWindowState[nVisibleIndex].Value <<= sal_True;
657 0 : xNameReplace->replaceByName( aElementName, makeAny( aWindowState ));
658 0 : bRefreshToolbars = true;
659 : }
660 0 : }
661 : }
662 0 : catch ( const NoSuchElementException& )
663 : {
664 : }
665 : }
666 :
667 0 : if ( bRefreshToolbars )
668 : {
669 0 : Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( xFrame ));
670 0 : if ( xLayoutManager.is() )
671 : {
672 0 : Reference< XPropertySet > xPropSet( xLayoutManager, UNO_QUERY );
673 0 : if ( xPropSet.is() )
674 : {
675 : try
676 : {
677 0 : xPropSet->setPropertyValue("RefreshContextToolbarVisibility", makeAny( sal_True ));
678 : }
679 0 : catch ( const RuntimeException& )
680 : {
681 : }
682 0 : catch ( const Exception& )
683 : {
684 : }
685 0 : }
686 : }
687 0 : RefreshToolbars( xFrame );
688 0 : }
689 : }
690 0 : catch ( const RuntimeException& )
691 : {
692 0 : throw;
693 : }
694 0 : catch ( const Exception& )
695 : {
696 : }
697 0 : }
698 : }
699 0 : else if ( aCmd.indexOf( STATIC_CMD_PART ) < 0 )
700 : {
701 0 : URL aTargetURL;
702 0 : Sequence<PropertyValue> aArgs;
703 :
704 0 : aTargetURL.Complete = aCmd;
705 0 : xURLTransformer->parseStrict( aTargetURL );
706 0 : Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
707 0 : if ( xDispatchProvider.is() )
708 : {
709 0 : Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch(
710 0 : aTargetURL, OUString(), 0 );
711 :
712 0 : ExecuteInfo* pExecuteInfo = new ExecuteInfo;
713 0 : pExecuteInfo->xDispatch = xDispatch;
714 0 : pExecuteInfo->aTargetURL = aTargetURL;
715 0 : pExecuteInfo->aArgs = aArgs;
716 0 : Application::PostUserEvent( LINK(0, ToolbarsMenuController, ExecuteHdl_Impl), pExecuteInfo );
717 0 : }
718 : }
719 : else
720 : {
721 0 : Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( xFrame ));
722 0 : if ( xLayoutManager.is() )
723 : {
724 : // Extract toolbar name from the combined uno-command.
725 0 : sal_Int32 nIndex = aCmd.indexOf( '=' );
726 0 : if (( nIndex > 0 ) && (( nIndex+1 ) < aCmd.getLength() ))
727 : {
728 0 : OUStringBuffer aBuf( STATIC_PRIVATE_TB_RESOURCE );
729 0 : aBuf.append( aCmd.copy( nIndex+1 ));
730 :
731 0 : bool bShow( !pVCLPopupMenu->IsItemChecked( rEvent.MenuId ));
732 0 : OUString aToolBarResName( aBuf.makeStringAndClear() );
733 0 : if ( bShow )
734 : {
735 0 : xLayoutManager->createElement( aToolBarResName );
736 0 : xLayoutManager->showElement( aToolBarResName );
737 : }
738 : else
739 : {
740 : // closing means:
741 : // hide and destroy element
742 0 : xLayoutManager->hideElement( aToolBarResName );
743 0 : xLayoutManager->destroyElement( aToolBarResName );
744 0 : }
745 : }
746 0 : }
747 0 : }
748 : }
749 0 : }
750 0 : }
751 :
752 0 : void SAL_CALL ToolbarsMenuController::itemActivated( const css::awt::MenuEvent& ) throw (RuntimeException, std::exception)
753 : {
754 0 : std::vector< OUString > aCmdVector;
755 0 : Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
756 0 : Reference< XURLTransformer > xURLTransformer( m_xURLTransformer );
757 : {
758 0 : osl::MutexGuard aLock( m_aMutex );
759 0 : fillPopupMenu( m_xPopupMenu );
760 0 : aCmdVector = m_aCommandVector;
761 : }
762 :
763 : // Update status for all commands inside our toolbars popup menu
764 0 : const sal_uInt32 nCount = aCmdVector.size();
765 0 : for ( sal_uInt32 i = 0; i < nCount; i++ )
766 : {
767 0 : bool bInternal = aCmdVector[i].startsWith( STATIC_INTERNAL_CMD_PART );
768 :
769 0 : if ( !bInternal )
770 : {
771 0 : URL aTargetURL;
772 0 : aTargetURL.Complete = aCmdVector[i];
773 0 : xURLTransformer->parseStrict( aTargetURL );
774 0 : Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
775 0 : if ( xDispatch.is() )
776 : {
777 0 : xDispatch->addStatusListener( (static_cast< XStatusListener* >(this)), aTargetURL );
778 0 : xDispatch->removeStatusListener( (static_cast< XStatusListener* >(this)), aTargetURL );
779 0 : }
780 : }
781 0 : else if ( aCmdVector[i] == CMD_RESTOREVISIBILITY )
782 : {
783 : // Special code to determine the enable/disable state of this command
784 0 : FeatureStateEvent aFeatureStateEvent;
785 0 : aFeatureStateEvent.FeatureURL.Complete = aCmdVector[i];
786 0 : aFeatureStateEvent.IsEnabled = isContextSensitiveToolbarNonVisible();
787 0 : statusChanged( aFeatureStateEvent );
788 : }
789 0 : }
790 0 : }
791 :
792 : // XPopupMenuController
793 2 : void SAL_CALL ToolbarsMenuController::setPopupMenu( const Reference< css::awt::XPopupMenu >& xPopupMenu ) throw ( RuntimeException, std::exception )
794 : {
795 2 : osl::MutexGuard aLock( m_aMutex );
796 :
797 2 : throwIfDisposed();
798 :
799 2 : if ( m_xFrame.is() && !m_xPopupMenu.is() )
800 : {
801 : // Create popup menu on demand
802 1 : SolarMutexGuard aSolarMutexGuard;
803 :
804 1 : m_xPopupMenu = xPopupMenu;
805 1 : m_xPopupMenu->addMenuListener( Reference< css::awt::XMenuListener >( static_cast<OWeakObject*>(this), UNO_QUERY ));
806 1 : fillPopupMenu( m_xPopupMenu );
807 2 : }
808 2 : }
809 :
810 : // XInitialization
811 2 : void SAL_CALL ToolbarsMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException, std::exception )
812 : {
813 2 : osl::MutexGuard aLock( m_aMutex );
814 2 : bool bInitalized( m_bInitialized );
815 2 : if ( !bInitalized )
816 : {
817 2 : svt::PopupMenuControllerBase::initialize(aArguments);
818 :
819 2 : if ( m_bInitialized )
820 : {
821 1 : Reference< XModuleManager2 > xModuleManager = ModuleManager::create( m_xContext );
822 2 : Reference< XNameAccess > xPersistentWindowStateSupplier = ::com::sun::star::ui::theWindowStateConfiguration::get( m_xContext );
823 :
824 : // Retrieve persistent window state reference for our module
825 2 : OUString aModuleIdentifier;
826 : try
827 : {
828 1 : aModuleIdentifier = xModuleManager->identify( m_xFrame );
829 1 : xPersistentWindowStateSupplier->getByName( aModuleIdentifier ) >>= m_xPersistentWindowState;
830 :
831 : Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier =
832 1 : theModuleUIConfigurationManagerSupplier::get( m_xContext );
833 1 : m_xModuleCfgMgr = xModuleCfgSupplier->getUIConfigurationManager( aModuleIdentifier );
834 :
835 2 : Reference< XController > xController = m_xFrame->getController();
836 2 : Reference< XModel > xModel;
837 1 : if ( xController.is() )
838 1 : xModel = xController->getModel();
839 1 : if ( xModel.is() )
840 : {
841 1 : Reference< XUIConfigurationManagerSupplier > xUIConfigurationManagerSupplier( xModel, UNO_QUERY );
842 1 : if ( xUIConfigurationManagerSupplier.is() )
843 1 : m_xDocCfgMgr = xUIConfigurationManagerSupplier->getUIConfigurationManager();
844 : }
845 2 : m_aModuleIdentifier = aModuleIdentifier;
846 : }
847 0 : catch ( const Exception& )
848 : {
849 1 : }
850 : }
851 2 : }
852 2 : }
853 :
854 0 : IMPL_STATIC_LINK( ToolbarsMenuController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
855 : {
856 : try
857 : {
858 : // Asynchronous execution as this can lead to our own destruction!
859 : // Framework can recycle our current frame and the layout manager disposes all user interface
860 : // elements if a component gets detached from its frame!
861 0 : if ( pExecuteInfo->xDispatch.is() )
862 : {
863 0 : pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
864 : }
865 : }
866 0 : catch ( const Exception& )
867 : {
868 : }
869 :
870 0 : delete pExecuteInfo;
871 0 : return 0;
872 : }
873 :
874 : }
875 :
876 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|