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