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 boost::unordered_map< OUString, OUString, OUStringHash, ::std::equal_to< OUString > > ToolbarHashMap;
86 :
87 678 : struct ToolBarEntry
88 : {
89 : OUString aUIName;
90 : OUString aCommand;
91 : bool bVisible;
92 : bool bContextSensitive;
93 : const CollatorWrapper* pCollatorWrapper;
94 : };
95 :
96 272 : bool CompareToolBarEntry( const ToolBarEntry& aOne, const ToolBarEntry& aTwo )
97 : {
98 272 : sal_Int32 nComp = aOne.pCollatorWrapper->compareString( aOne.aUIName, aTwo.aUIName );
99 :
100 272 : if ( nComp < 0 )
101 172 : return true;
102 : else
103 100 : return false;
104 : }
105 :
106 2 : Reference< XLayoutManager > getLayoutManagerFromFrame( const Reference< XFrame >& rFrame )
107 : {
108 2 : Reference< XPropertySet > xPropSet( rFrame, UNO_QUERY );
109 2 : Reference< XLayoutManager > xLayoutManager;
110 :
111 : try
112 : {
113 2 : xPropSet->getPropertyValue("LayoutManager") >>= xLayoutManager;
114 : }
115 0 : catch ( const UnknownPropertyException& )
116 : {
117 : }
118 :
119 2 : return xLayoutManager;
120 : }
121 :
122 36 : struct ToolBarInfo
123 : {
124 : OUString aToolBarResName;
125 : OUString aToolBarUIName;
126 : };
127 :
128 110 : DEFINE_XSERVICEINFO_MULTISERVICE_2 ( ToolbarsMenuController ,
129 : OWeakObject ,
130 : SERVICENAME_POPUPMENUCONTROLLER ,
131 : IMPLEMENTATIONNAME_TOOLBARSMENUCONTROLLER
132 : )
133 :
134 6 : DEFINE_INIT_SERVICE ( ToolbarsMenuController, {} )
135 :
136 6 : 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 6 : m_aIntlWrapper( xContext, Application::GetSettings().GetLanguageTag() )
144 : {
145 6 : }
146 :
147 12 : ToolbarsMenuController::~ToolbarsMenuController()
148 : {
149 12 : }
150 :
151 6 : void ToolbarsMenuController::addCommand(
152 : Reference< css::awt::XPopupMenu >& rPopupMenu, const OUString& rCommandURL, const OUString& rLabel )
153 : {
154 6 : sal_uInt16 nItemId = m_xPopupMenu->getItemCount()+1;
155 :
156 6 : OUString aLabel;
157 6 : if ( rLabel.isEmpty() )
158 4 : aLabel = getUINameFromCommand( rCommandURL );
159 : else
160 2 : aLabel = rLabel;
161 :
162 6 : rPopupMenu->insertItem( nItemId, aLabel, 0, nItemId );
163 6 : rPopupMenu->setCommand( nItemId, rCommandURL );
164 :
165 6 : bool bInternal = rCommandURL.startsWith( STATIC_INTERNAL_CMD_PART );
166 6 : if ( !bInternal )
167 : {
168 4 : if ( !getDispatchFromCommandURL( rCommandURL ).is() )
169 0 : m_xPopupMenu->enableItem( nItemId, sal_False );
170 : }
171 :
172 12 : SolarMutexGuard aSolarMutexGuard;
173 :
174 12 : Image aImage;
175 6 : const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
176 :
177 6 : if ( rSettings.GetUseImagesInMenus() )
178 6 : aImage = GetImageFromURL( m_xFrame, rCommandURL, false );
179 :
180 6 : VCLXPopupMenu* pPopupMenu = static_cast<VCLXPopupMenu *>(VCLXPopupMenu::GetImplementation( rPopupMenu ));
181 6 : if ( pPopupMenu )
182 : {
183 6 : PopupMenu* pVCLPopupMenu = static_cast<PopupMenu *>(pPopupMenu->GetMenu());
184 6 : if ( !!aImage )
185 2 : pVCLPopupMenu->SetItemImage( nItemId, aImage );
186 : }
187 :
188 12 : m_aCommandVector.push_back( rCommandURL );
189 6 : }
190 :
191 4 : Reference< XDispatch > ToolbarsMenuController::getDispatchFromCommandURL( const OUString& rCommandURL )
192 : {
193 4 : URL aTargetURL;
194 8 : Reference< XURLTransformer > xURLTransformer;
195 8 : Reference< XFrame > xFrame;
196 :
197 : {
198 4 : SolarMutexGuard aSolarMutexGuard;
199 4 : xURLTransformer = m_xURLTransformer;
200 4 : xFrame = m_xFrame;
201 : }
202 :
203 4 : aTargetURL.Complete = rCommandURL;
204 4 : xURLTransformer->parseStrict( aTargetURL );
205 8 : Reference< XDispatchProvider > xDispatchProvider( xFrame, UNO_QUERY );
206 4 : if ( xDispatchProvider.is() )
207 4 : return xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
208 : else
209 4 : return Reference< XDispatch >();
210 : }
211 :
212 : // private function
213 4 : OUString ToolbarsMenuController::getUINameFromCommand( const OUString& rCommandURL )
214 : {
215 4 : OUString aLabel;
216 :
217 4 : if ( !m_bModuleIdentified )
218 : {
219 : try
220 : {
221 4 : Reference< XModuleManager2 > xModuleManager = ModuleManager::create( m_xContext );
222 4 : m_aModuleIdentifier = xModuleManager->identify( m_xFrame );
223 8 : Reference< XNameAccess > xNameAccess = frame::theUICommandDescription::get( m_xContext );
224 8 : xNameAccess->getByName( m_aModuleIdentifier ) >>= m_xUICommandDescription;
225 : }
226 0 : catch ( const Exception& )
227 : {
228 : }
229 : }
230 :
231 4 : if ( m_xUICommandDescription.is() )
232 : {
233 : try
234 : {
235 4 : Sequence< PropertyValue > aPropSeq;
236 8 : OUString aStr;
237 4 : if ( m_xUICommandDescription->getByName( rCommandURL ) >>= aPropSeq )
238 : {
239 4 : for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ )
240 : {
241 4 : if ( aPropSeq[i].Name == "Label" )
242 : {
243 4 : aPropSeq[i].Value >>= aStr;
244 4 : break;
245 : }
246 : }
247 : }
248 8 : aLabel = aStr;
249 : }
250 0 : catch ( const Exception& )
251 : {
252 : }
253 : }
254 :
255 4 : return aLabel;
256 : }
257 :
258 6 : static void fillHashMap( const Sequence< Sequence< ::com::sun::star::beans::PropertyValue > >& rSeqToolBars,
259 : ToolbarHashMap& rHashMap )
260 : {
261 90 : for ( sal_Int32 i = 0; i < rSeqToolBars.getLength(); i++ )
262 : {
263 84 : OUString aResourceURL;
264 168 : OUString aUIName;
265 84 : const PropertyValue* pProperties = rSeqToolBars[i].getConstArray();
266 252 : for ( sal_Int32 j = 0; j < rSeqToolBars[i].getLength(); j++ )
267 : {
268 168 : if ( pProperties[j].Name == ITEM_DESCRIPTOR_RESOURCEURL )
269 84 : pProperties[j].Value >>= aResourceURL;
270 84 : else if ( pProperties[j].Name == ITEM_DESCRIPTOR_UINAME )
271 84 : pProperties[j].Value >>= aUIName;
272 : }
273 :
274 420 : if ( !aResourceURL.isEmpty() &&
275 420 : rHashMap.find( aResourceURL ) == rHashMap.end() )
276 80 : rHashMap.insert( ToolbarHashMap::value_type( aResourceURL, aUIName ));
277 84 : }
278 6 : }
279 :
280 : // private function
281 2 : Sequence< Sequence< com::sun::star::beans::PropertyValue > > ToolbarsMenuController::getLayoutManagerToolbars( const Reference< ::com::sun::star::frame::XLayoutManager >& rLayoutManager )
282 : {
283 2 : std::vector< ToolBarInfo > aToolBarArray;
284 4 : Sequence< Reference< XUIElement > > aUIElements = rLayoutManager->getElements();
285 12 : for ( sal_Int32 i = 0; i < aUIElements.getLength(); i++ )
286 : {
287 10 : Reference< XUIElement > xUIElement( aUIElements[i] );
288 20 : Reference< XPropertySet > xPropSet( aUIElements[i], UNO_QUERY );
289 10 : if ( xPropSet.is() && xUIElement.is() )
290 : {
291 : try
292 : {
293 10 : OUString aResName;
294 10 : sal_Int16 nType( -1 );
295 10 : xPropSet->getPropertyValue("Type") >>= nType;
296 10 : xPropSet->getPropertyValue("ResourceURL") >>= aResName;
297 :
298 16 : if (( nType == ::com::sun::star::ui::UIElementType::TOOLBAR ) &&
299 6 : !aResName.isEmpty() )
300 : {
301 6 : ToolBarInfo aToolBarInfo;
302 :
303 6 : aToolBarInfo.aToolBarResName = aResName;
304 :
305 12 : SolarMutexGuard aGuard;
306 12 : Reference< css::awt::XWindow > xWindow( xUIElement->getRealInterface(), UNO_QUERY );
307 6 : vcl::Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
308 6 : if ( pWindow )
309 6 : aToolBarInfo.aToolBarUIName = pWindow->GetText();
310 :
311 12 : aToolBarArray.push_back( aToolBarInfo );
312 10 : }
313 : }
314 0 : catch ( const Exception& )
315 : {
316 : }
317 : }
318 10 : }
319 :
320 4 : Sequence< com::sun::star::beans::PropertyValue > aTbSeq( 2 );
321 2 : aTbSeq[0].Name = m_aPropUIName;
322 2 : aTbSeq[1].Name = m_aPropResourceURL;
323 :
324 2 : Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeq( aToolBarArray.size() );
325 2 : const sal_uInt32 nCount = aToolBarArray.size();
326 8 : for ( sal_uInt32 i = 0; i < nCount; i++ )
327 : {
328 6 : aTbSeq[0].Value <<= aToolBarArray[i].aToolBarUIName;
329 6 : aTbSeq[1].Value <<= aToolBarArray[i].aToolBarResName;
330 6 : aSeq[i] = aTbSeq;
331 : }
332 :
333 4 : return aSeq;
334 : }
335 :
336 :
337 2 : void ToolbarsMenuController::fillPopupMenu( Reference< css::awt::XPopupMenu >& rPopupMenu )
338 : {
339 2 : if( SvtMiscOptions().DisableUICustomization() )
340 2 : return;
341 :
342 2 : SolarMutexGuard aSolarMutexGuard;
343 2 : resetPopupMenu( rPopupMenu );
344 :
345 2 : m_aCommandVector.clear();
346 :
347 : // Retrieve layout manager for additional information
348 4 : OUString aEmptyString;
349 4 : Reference< XLayoutManager > xLayoutManager( getLayoutManagerFromFrame( m_xFrame ));
350 :
351 2 : m_bResetActive = false;
352 2 : if ( xLayoutManager.is() )
353 : {
354 2 : ToolbarHashMap aToolbarHashMap;
355 :
356 2 : if ( m_xDocCfgMgr.is() )
357 : {
358 : Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqDocToolBars =
359 2 : m_xDocCfgMgr->getUIElementsInfo( UIElementType::TOOLBAR );
360 2 : fillHashMap( aSeqDocToolBars, aToolbarHashMap );
361 : }
362 :
363 2 : if ( m_xModuleCfgMgr.is() )
364 : {
365 : Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqToolBars =
366 2 : m_xModuleCfgMgr->getUIElementsInfo( UIElementType::TOOLBAR );
367 2 : fillHashMap( aSeqToolBars, aToolbarHashMap );
368 : }
369 :
370 4 : std::vector< ToolBarEntry > aSortedTbs;
371 4 : OUString aStaticCmdPart( STATIC_CMD_PART );
372 :
373 4 : Sequence< Sequence< com::sun::star::beans::PropertyValue > > aSeqFrameToolBars = getLayoutManagerToolbars( xLayoutManager );
374 2 : fillHashMap( aSeqFrameToolBars, aToolbarHashMap );
375 :
376 2 : ToolbarHashMap::const_iterator pIter = aToolbarHashMap.begin();
377 84 : while ( pIter != aToolbarHashMap.end() )
378 : {
379 80 : OUString aUIName = pIter->second;
380 80 : bool bHideFromMenu( false );
381 80 : bool bContextSensitive( false );
382 80 : bool bVisible( false );
383 158 : if ( aUIName.isEmpty() &&
384 78 : m_xPersistentWindowState.is() )
385 : {
386 : try
387 : {
388 78 : Sequence< PropertyValue > aWindowState;
389 156 : Any a( m_xPersistentWindowState->getByName( pIter->first ));
390 :
391 78 : if ( a >>= aWindowState )
392 : {
393 950 : for ( sal_Int32 i = 0; i < aWindowState.getLength(); i++ )
394 : {
395 872 : if ( aWindowState[i].Name == WINDOWSTATE_PROPERTY_UINAME )
396 78 : aWindowState[i].Value >>= aUIName;
397 794 : else if ( aWindowState[i].Name == WINDOWSTATE_PROPERTY_HIDEFROMENU )
398 78 : aWindowState[i].Value >>= bHideFromMenu;
399 716 : else if ( aWindowState[i].Name == WINDOWSTATE_PROPERTY_CONTEXT )
400 78 : aWindowState[i].Value >>= bContextSensitive;
401 638 : else if ( aWindowState[i].Name == WINDOWSTATE_PROPERTY_VISIBLE )
402 78 : aWindowState[i].Value >>= bVisible;
403 : }
404 78 : }
405 : }
406 0 : catch ( const Exception& )
407 : {
408 : }
409 :
410 : // Check if we have to enable/disable "Reset" menu item
411 78 : if ( bContextSensitive && !bVisible )
412 2 : m_bResetActive = true;
413 :
414 : }
415 :
416 80 : if ( !aUIName.isEmpty() && !bHideFromMenu )
417 : {
418 48 : ToolBarEntry aTbEntry;
419 48 : aTbEntry.aUIName = aUIName;
420 48 : aTbEntry.aCommand = pIter->first;
421 48 : aTbEntry.bVisible = xLayoutManager->isElementVisible( pIter->first );
422 48 : aTbEntry.bContextSensitive = bContextSensitive;
423 48 : aTbEntry.pCollatorWrapper = m_aIntlWrapper.getCaseCollator();
424 48 : aSortedTbs.push_back( aTbEntry );
425 : }
426 80 : ++pIter;
427 80 : }
428 :
429 : // sort toolbars
430 2 : std::sort( aSortedTbs.begin(), aSortedTbs.end(), CompareToolBarEntry );
431 :
432 2 : sal_Int16 nIndex( 1 );
433 2 : const sal_uInt32 nCount = aSortedTbs.size();
434 50 : for ( sal_uInt32 i = 0; i < nCount; i++ )
435 : {
436 48 : sal_uInt16 nItemCount = m_xPopupMenu->getItemCount();
437 48 : m_xPopupMenu->insertItem( nIndex, aSortedTbs[i].aUIName, css::awt::MenuItemStyle::CHECKABLE, nItemCount );
438 48 : if ( aSortedTbs[i].bVisible )
439 4 : m_xPopupMenu->checkItem( nIndex, sal_True );
440 :
441 : {
442 48 : SolarMutexGuard aGuard;
443 48 : VCLXPopupMenu* pXPopupMenu = static_cast<VCLXPopupMenu *>(VCLXMenu::GetImplementation( m_xPopupMenu ));
444 48 : PopupMenu* pVCLPopupMenu = pXPopupMenu ? static_cast<PopupMenu *>(pXPopupMenu->GetMenu()) : NULL;
445 : assert(pVCLPopupMenu);
446 48 : if (pVCLPopupMenu)
447 48 : pVCLPopupMenu->SetUserValue( nIndex, sal_uIntPtr( aSortedTbs[i].bContextSensitive ? 1L : 0L ));
448 : }
449 :
450 : // use VCL popup menu pointer to set vital information that are not part of the awt implementation
451 48 : OUStringBuffer aStrBuf( aStaticCmdPart );
452 :
453 48 : sal_Int32 n = aSortedTbs[i].aCommand.lastIndexOf( '/' );
454 48 : if (( n > 0 ) && (( n+1 ) < aSortedTbs[i].aCommand.getLength() ))
455 48 : aStrBuf.append( aSortedTbs[i].aCommand.copy( n+1 ));
456 :
457 96 : OUString aCmd( aStrBuf.makeStringAndClear() );
458 :
459 : // Store complete uno-command so it can also be dispatched. This is necessary to support
460 : // the test tool!
461 48 : rPopupMenu->setCommand( nIndex, aCmd );
462 48 : ++nIndex;
463 48 : }
464 :
465 : // Create commands for non-toolbars
466 4 : if ( m_aModuleIdentifier == "com.sun.star.text.TextDocument" ||
467 0 : m_aModuleIdentifier == "com.sun.star.text.WebDocument" ||
468 0 : m_aModuleIdentifier == "com.sun.star.text.GlobalDocument" ||
469 0 : m_aModuleIdentifier == "com.sun.star.drawing.DrawingDocument" ||
470 2 : m_aModuleIdentifier == "com.sun.star.presentation.PresentationDocument" ||
471 0 : m_aModuleIdentifier == "com.sun.star.sheet.SpreadsheetDocument" )
472 : {
473 4 : if ( m_aModuleIdentifier == "com.sun.star.drawing.DrawingDocument" ||
474 2 : m_aModuleIdentifier == "com.sun.star.presentation.PresentationDocument" )
475 0 : addCommand( m_xPopupMenu, OUString( CMD_COLORBAR ), aEmptyString );
476 2 : else if ( m_aModuleIdentifier == "com.sun.star.sheet.SpreadsheetDocument" )
477 0 : addCommand( m_xPopupMenu, OUString( CMD_INPUTLINEBAR ), aEmptyString );
478 : else
479 2 : addCommand( m_xPopupMenu, OUString( CMD_FORMULABAR ), aEmptyString );
480 : }
481 :
482 2 : bool bAddCommand( true );
483 4 : SvtCommandOptions aCmdOptions;
484 4 : OUString aConfigureToolbar( CONFIGURE_TOOLBARS );
485 :
486 2 : if ( aCmdOptions.HasEntries( SvtCommandOptions::CMDOPTION_DISABLED ))
487 : {
488 0 : if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED,
489 0 : OUString( CONFIGURE_TOOLBARS_CMD )))
490 0 : bAddCommand = false;
491 : }
492 :
493 2 : if ( bAddCommand )
494 : {
495 : // Create command for configure
496 2 : if ( m_xPopupMenu->getItemCount() > 0 )
497 : {
498 2 : sal_uInt16 nItemCount = m_xPopupMenu->getItemCount();
499 2 : m_xPopupMenu->insertSeparator( nItemCount+1 );
500 : }
501 :
502 2 : addCommand( m_xPopupMenu, aConfigureToolbar, aEmptyString );
503 : }
504 :
505 : // Add separator if no configure has been added
506 2 : if ( !bAddCommand )
507 : {
508 : // Create command for configure
509 0 : if ( m_xPopupMenu->getItemCount() > 0 )
510 : {
511 0 : sal_uInt16 nItemCount = m_xPopupMenu->getItemCount();
512 0 : m_xPopupMenu->insertSeparator( nItemCount+1 );
513 : }
514 : }
515 :
516 4 : OUString aLabelStr(FWK_RESSTR(STR_RESTORE_TOOLBARS));
517 4 : OUString aRestoreCmd( CMD_RESTOREVISIBILITY );
518 4 : addCommand( m_xPopupMenu, aRestoreCmd, aLabelStr );
519 2 : }
520 : }
521 :
522 : // XEventListener
523 2 : void SAL_CALL ToolbarsMenuController::disposing( const EventObject& ) throw ( RuntimeException, std::exception )
524 : {
525 2 : Reference< css::awt::XMenuListener > xHolder(( OWeakObject *)this, UNO_QUERY );
526 :
527 4 : osl::MutexGuard aLock( m_aMutex );
528 2 : m_xFrame.clear();
529 2 : m_xDispatch.clear();
530 2 : m_xDocCfgMgr.clear();
531 2 : m_xModuleCfgMgr.clear();
532 2 : m_xContext.clear();
533 :
534 2 : if ( m_xPopupMenu.is() )
535 2 : m_xPopupMenu->removeMenuListener( Reference< css::awt::XMenuListener >(( OWeakObject *)this, UNO_QUERY ));
536 4 : m_xPopupMenu.clear();
537 2 : }
538 :
539 : // XStatusListener
540 2 : void SAL_CALL ToolbarsMenuController::statusChanged( const FeatureStateEvent& Event ) throw ( RuntimeException, std::exception )
541 : {
542 2 : OUString aFeatureURL( Event.FeatureURL.Complete );
543 :
544 : // All other status events will be processed here
545 2 : bool bSetCheckmark = false;
546 2 : bool bCheckmark = false;
547 :
548 4 : osl::ClearableMutexGuard aLock( m_aMutex );
549 4 : Reference< css::awt::XPopupMenu > xPopupMenu( m_xPopupMenu );
550 2 : aLock.clear();
551 :
552 2 : if ( xPopupMenu.is() )
553 : {
554 0 : SolarMutexGuard aGuard;
555 0 : VCLXPopupMenu* pXPopupMenu = static_cast<VCLXPopupMenu *>(VCLXMenu::GetImplementation( xPopupMenu ));
556 0 : PopupMenu* pVCLPopupMenu = pXPopupMenu ? static_cast<PopupMenu *>(pXPopupMenu->GetMenu()) : NULL;
557 :
558 : assert(pVCLPopupMenu);
559 0 : if (!pVCLPopupMenu)
560 2 : return;
561 :
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 2 : }
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( STATIC_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 4 : void SAL_CALL ToolbarsMenuController::setPopupMenu( const Reference< css::awt::XPopupMenu >& xPopupMenu ) throw ( RuntimeException, std::exception )
794 : {
795 4 : osl::MutexGuard aLock( m_aMutex );
796 :
797 4 : throwIfDisposed();
798 :
799 4 : if ( m_xFrame.is() && !m_xPopupMenu.is() )
800 : {
801 : // Create popup menu on demand
802 2 : SolarMutexGuard aSolarMutexGuard;
803 :
804 2 : m_xPopupMenu = xPopupMenu;
805 2 : m_xPopupMenu->addMenuListener( Reference< css::awt::XMenuListener >( (OWeakObject*)this, UNO_QUERY ));
806 2 : fillPopupMenu( m_xPopupMenu );
807 4 : }
808 4 : }
809 :
810 : // XInitialization
811 4 : void SAL_CALL ToolbarsMenuController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException, std::exception )
812 : {
813 4 : osl::MutexGuard aLock( m_aMutex );
814 4 : bool bInitalized( m_bInitialized );
815 4 : if ( !bInitalized )
816 : {
817 4 : svt::PopupMenuControllerBase::initialize(aArguments);
818 :
819 4 : if ( m_bInitialized )
820 : {
821 2 : Reference< XModuleManager2 > xModuleManager = ModuleManager::create( m_xContext );
822 4 : Reference< XNameAccess > xPersistentWindowStateSupplier = ::com::sun::star::ui::theWindowStateConfiguration::get( m_xContext );
823 :
824 : // Retrieve persistent window state reference for our module
825 4 : OUString aModuleIdentifier;
826 : try
827 : {
828 2 : aModuleIdentifier = xModuleManager->identify( m_xFrame );
829 2 : xPersistentWindowStateSupplier->getByName( aModuleIdentifier ) >>= m_xPersistentWindowState;
830 :
831 : Reference< XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier =
832 2 : theModuleUIConfigurationManagerSupplier::get( m_xContext );
833 2 : m_xModuleCfgMgr = xModuleCfgSupplier->getUIConfigurationManager( aModuleIdentifier );
834 :
835 4 : Reference< XController > xController = m_xFrame->getController();
836 4 : Reference< XModel > xModel;
837 2 : if ( xController.is() )
838 2 : xModel = xController->getModel();
839 2 : if ( xModel.is() )
840 : {
841 2 : Reference< XUIConfigurationManagerSupplier > xUIConfigurationManagerSupplier( xModel, UNO_QUERY );
842 2 : if ( xUIConfigurationManagerSupplier.is() )
843 2 : m_xDocCfgMgr = xUIConfigurationManagerSupplier->getUIConfigurationManager();
844 : }
845 4 : m_aModuleIdentifier = aModuleIdentifier;
846 : }
847 0 : catch ( const Exception& )
848 : {
849 2 : }
850 : }
851 4 : }
852 4 : }
853 :
854 0 : IMPL_STATIC_LINK_NOINSTANCE( 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 198 : }
875 :
876 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|