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