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