1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 #include <uielement/addonstoolbarmanager.hxx>
31 #include <uielement/toolbarmerger.hxx>
32 
33 //_________________________________________________________________________________________________________________
34 //	my own includes
35 //_________________________________________________________________________________________________________________
36 
37 
38 #ifndef __FRAMEWORK_UIELEMENT_TOOLBAR_HXX
39 #include <uielement/toolbar.hxx>
40 #endif
41 #ifndef __FRAMEWORK_UIELEMENT_GENERICTOOLBARCONTROLLER_HXX
42 #include <uielement/generictoolbarcontroller.hxx>
43 #endif
44 #include <threadhelp/resetableguard.hxx>
45 #include "services.h"
46 #include <framework/imageproducer.hxx>
47 #include <framework/sfxhelperfunctions.hxx>
48 #include <classes/fwkresid.hxx>
49 #ifndef __FRAMEWORK_CLASES_RESOURCE_HRC_
50 #include <classes/resource.hrc>
51 #endif
52 #include <framework/addonsoptions.hxx>
53 #ifndef __FRAMEWORK_UIELEMENT_COMBOBOXTOOLBARCONTROLLER_HXX
54 #include <uielement/comboboxtoolbarcontroller.hxx>
55 #endif
56 #ifndef __FRAMEWORK_UIELEMENT_IMAGEBUTTONTOOLBARCONTROLLER_HXX
57 #include <uielement/imagebuttontoolbarcontroller.hxx>
58 #endif
59 #ifndef __FRAMEWORK_UIELEMENT_TOGGLEBUTTONTOOLBARCONTROLLER_HXX
60 #include <uielement/togglebuttontoolbarcontroller.hxx>
61 #endif
62 #include <uielement/buttontoolbarcontroller.hxx>
63 #include <uielement/spinfieldtoolbarcontroller.hxx>
64 #include <uielement/edittoolbarcontroller.hxx>
65 #include <uielement/dropdownboxtoolbarcontroller.hxx>
66 #include <uielement/toolbarmerger.hxx>
67 
68 //_________________________________________________________________________________________________________________
69 //	interface includes
70 //_________________________________________________________________________________________________________________
71 #include <com/sun/star/ui/ItemType.hpp>
72 #include <com/sun/star/frame/XToolbarController.hpp>
73 #include <com/sun/star/frame/XDispatchProvider.hpp>
74 #ifndef _COM_SUN_STAR_BEANS_XLAYOUTMANAGER_HPP_
75 #include <com/sun/star/beans/XPropertySet.hpp>
76 #endif
77 #include <com/sun/star/lang/XServiceInfo.hpp>
78 #include <com/sun/star/frame/XLayoutManager.hpp>
79 #ifndef _COM_SUN_STAR_UI_XDOCKINGAREA_HPP_
80 #include <com/sun/star/ui/DockingArea.hpp>
81 #endif
82 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
83 
84 //_________________________________________________________________________________________________________________
85 //	other includes
86 //_________________________________________________________________________________________________________________
87 #include <svtools/imgdef.hxx>
88 #include <svtools/toolboxcontroller.hxx>
89 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
90 #include <toolkit/unohlp.hxx>
91 #endif
92 
93 #include <svtools/miscopt.hxx>
94 #include <vcl/svapp.hxx>
95 #include <vcl/menu.hxx>
96 #include <vcl/syswin.hxx>
97 #include <vcl/taskpanelist.hxx>
98 
99 //_________________________________________________________________________________________________________________
100 //	namespaces
101 //_________________________________________________________________________________________________________________
102 
103 using namespace ::com::sun::star;
104 using namespace ::com::sun::star::awt;
105 using namespace ::com::sun::star::beans;
106 using namespace ::com::sun::star::uno;
107 using namespace ::com::sun::star::lang;
108 using namespace ::com::sun::star::frame;
109 using namespace ::com::sun::star::util;
110 using namespace ::com::sun::star::container;
111 using namespace ::com::sun::star::frame;
112 using namespace ::com::sun::star::ui;
113 
114 namespace framework
115 {
116 
117 static const char   TOOLBOXITEM_SEPARATOR_STR[] = "private:separator";
118 static const sal_uInt16 TOOLBOXITEM_SEPARATOR_STR_LEN = sizeof( TOOLBOXITEM_SEPARATOR_STR )-1;
119 
120 AddonsToolBarManager::AddonsToolBarManager( const Reference< XMultiServiceFactory >& rServiceManager,
121                                 const Reference< XFrame >& rFrame,
122                                 const rtl::OUString& rResourceName,
123                                 ToolBar* pToolBar ) :
124     ToolBarManager( rServiceManager, rFrame, rResourceName, pToolBar )
125 {
126     // Configuration data is retrieved from non-writable configuration layer. Therefor we
127     // must disable some menu entries.
128     m_bCanBeCustomized = sal_False;
129 
130     m_pToolBar->SetMenuType( TOOLBOX_MENUTYPE_CLIPPEDITEMS );
131     m_pToolBar->SetSelectHdl( LINK( this, AddonsToolBarManager, Select) );
132 	m_pToolBar->SetActivateHdl( LINK( this, AddonsToolBarManager, Activate) );
133 	m_pToolBar->SetDeactivateHdl( LINK( this, AddonsToolBarManager, Deactivate) );
134     m_pToolBar->SetClickHdl( LINK( this, AddonsToolBarManager, Click ) );
135     m_pToolBar->SetDoubleClickHdl( LINK( this, AddonsToolBarManager, DoubleClick ) );
136     m_pToolBar->SetCommandHdl( LINK( this, AddonsToolBarManager, Command ) );
137     m_pToolBar->SetStateChangedHdl( LINK( this, AddonsToolBarManager, StateChanged ) );
138     m_pToolBar->SetDataChangedHdl( LINK( this, AddonsToolBarManager, DataChanged ) );
139 }
140 
141 AddonsToolBarManager::~AddonsToolBarManager()
142 {
143 }
144 
145 static sal_Bool IsCorrectContext( const ::rtl::OUString& rModuleIdentifier, const ::rtl::OUString& aContextList )
146 {
147     if ( aContextList.getLength() == 0 )
148         return sal_True;
149 
150     if ( rModuleIdentifier.getLength() > 0 )
151 	{
152         sal_Int32 nIndex = aContextList.indexOf( rModuleIdentifier );
153         return ( nIndex >= 0 );
154 	}
155 
156 	return sal_False;
157 }
158 
159 static Image RetrieveImage( Reference< com::sun::star::frame::XFrame >& rFrame,
160 						    const rtl::OUString& aImageId,
161 							const rtl::OUString& aURL,
162 							sal_Bool bBigImage,
163 							sal_Bool bHiContrast )
164 {
165 	Image aImage;
166 
167 	if ( aImageId.getLength() > 0 )
168 	{
169 		aImage = framework::AddonsOptions().GetImageFromURL( aImageId, bBigImage, bHiContrast );
170 		if ( !!aImage )
171 			return aImage;
172         else
173             aImage = GetImageFromURL( rFrame, aImageId, bBigImage, bHiContrast );
174 		if ( !!aImage )
175 			return aImage;
176 	}
177 
178     aImage = framework::AddonsOptions().GetImageFromURL( aURL, bBigImage, bHiContrast );
179 	if ( !aImage )
180 		aImage = GetImageFromURL( rFrame, aImageId, bBigImage, bHiContrast );
181 
182 	return aImage;
183 }
184 
185 // XComponent
186 void SAL_CALL AddonsToolBarManager::dispose() throw( RuntimeException )
187 {
188     Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY );
189 
190     {
191         // Remove addon specific data from toolbar items.
192         ResetableGuard aGuard( m_aLock );
193         for ( sal_uInt16 n = 0; n < m_pToolBar->GetItemCount(); n++ )
194         {
195             sal_uInt16 nId( m_pToolBar->GetItemId( n ) );
196 
197             if ( nId > 0 )
198             {
199 		        AddonsParams* pRuntimeItemData = (AddonsParams*)m_pToolBar->GetItemData( nId );
200                 if ( pRuntimeItemData )
201                     delete pRuntimeItemData;
202                 m_pToolBar->SetItemData( nId, NULL );
203             }
204         }
205     }
206 
207     // Base class will destroy our m_pToolBar member
208     ToolBarManager::dispose();
209 }
210 
211 bool AddonsToolBarManager::MenuItemAllowed( sal_uInt16 nId ) const
212 {
213     if (( nId == MENUITEM_TOOLBAR_VISIBLEBUTTON ) ||
214         ( nId == MENUITEM_TOOLBAR_CUSTOMIZETOOLBAR ))
215         return false;
216     else
217         return true;
218 }
219 
220 void AddonsToolBarManager::RefreshImages()
221 {
222     sal_Bool  bBigImages( SvtMiscOptions().AreCurrentSymbolsLarge() );
223     for ( sal_uInt16 nPos = 0; nPos < m_pToolBar->GetItemCount(); nPos++ )
224     {
225         sal_uInt16 nId( m_pToolBar->GetItemId( nPos ) );
226 
227         if ( nId > 0 )
228         {
229             ::rtl::OUString aCommandURL = m_pToolBar->GetItemCommand( nId );
230             ::rtl::OUString aImageId;
231             AddonsParams* pRuntimeItemData = (AddonsParams*)m_pToolBar->GetItemData( nId );
232             if ( pRuntimeItemData )
233                 aImageId  = pRuntimeItemData->aImageId;
234 
235             m_pToolBar->SetItemImage( nId, RetrieveImage( m_xFrame,
236                                                           aImageId,
237                                                           aCommandURL,
238                                                           bBigImages,
239                                                           m_bIsHiContrast ));
240         }
241     }
242 }
243 
244 void AddonsToolBarManager::FillToolbar( const Sequence< Sequence< PropertyValue > >& rAddonToolbar )
245 {
246     ResetableGuard aGuard( m_aLock );
247 
248     if ( m_bDisposed )
249         return;
250 
251     sal_uInt16    nId( 1 );
252 
253     RemoveControllers();
254 
255     m_pToolBar->Clear();
256     m_aControllerMap.clear();
257 
258     ::rtl::OUString aModuleIdentifier;
259     try
260     {
261         Reference< XModuleManager > xModuleManager(
262             m_xServiceManager->createInstance( SERVICENAME_MODULEMANAGER ), UNO_QUERY_THROW );
263         aModuleIdentifier = xModuleManager->identify( m_xFrame );
264     }
265     catch ( Exception& )
266     {
267     }
268 
269     Reference< XMultiComponentFactory > xToolbarControllerFactory( m_xToolbarControllerRegistration, UNO_QUERY );
270     Reference< XComponentContext > xComponentContext;
271     Reference< XPropertySet > xProps( m_xServiceManager, UNO_QUERY );
272 
273     if ( xProps.is() )
274         xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xComponentContext;
275 
276     sal_uInt32  nElements( 0 );
277     sal_Bool    bAppendSeparator( sal_False );
278     Reference< XWindow > xToolbarWindow = VCLUnoHelper::GetInterface( m_pToolBar );
279 	for ( sal_uInt32 n = 0; n < (sal_uInt32)rAddonToolbar.getLength(); n++ )
280 	{
281 		rtl::OUString	aValueName;
282 
283 		rtl::OUString	aURL;
284 		rtl::OUString	aTitle;
285 		rtl::OUString	aImageId;
286 		rtl::OUString	aContext;
287 		rtl::OUString	aTarget;
288         rtl::OUString   aControlType;
289         sal_uInt16      nWidth( 0 );
290 
291 		const Sequence< PropertyValue >& rSeq = rAddonToolbar[n];
292 
293         ToolBarMerger::ConvertSequenceToValues( rSeq, aURL, aTitle, aImageId, aTarget, aContext, aControlType, nWidth );
294 
295 		if ( IsCorrectContext( aModuleIdentifier, aContext ))
296 		{
297 			if ( aURL.equalsAsciiL( TOOLBOXITEM_SEPARATOR_STR, TOOLBOXITEM_SEPARATOR_STR_LEN ))
298 			{
299 				sal_uInt16 nCount = m_pToolBar->GetItemCount();
300 				if ( nCount > 0 && ( m_pToolBar->GetItemType( nCount-1 ) != TOOLBOXITEM_SEPARATOR ) && nElements > 0 )
301 				{
302                     nElements = 0;
303 					m_pToolBar->InsertSeparator();
304 				}
305 			}
306 			else
307 			{
308                 sal_uInt16 nCount = m_pToolBar->GetItemCount();
309 			    if ( bAppendSeparator && nCount > 0 && ( m_pToolBar->GetItemType( nCount-1 ) != TOOLBOXITEM_SEPARATOR ))
310 				{
311 				    // We have to append a separator first if the last item is not a separator
312 				    m_pToolBar->InsertSeparator();
313 			    }
314 				bAppendSeparator = sal_False;
315 
316 				m_pToolBar->InsertItem( nId, aTitle );
317 
318 				Image aImage = RetrieveImage( m_xFrame, aImageId, aURL, !m_bSmallSymbols, m_bIsHiContrast );
319 				if ( !!aImage )
320 					m_pToolBar->SetItemImage( nId, aImage );
321 
322 				// Create TbRuntimeItemData to hold additional information we will need in the future
323 				AddonsParams* pRuntimeItemData = new AddonsParams;
324 				pRuntimeItemData->aImageId	= aImageId;
325 				pRuntimeItemData->aTarget	= aTarget;
326 				m_pToolBar->SetItemData( nId, pRuntimeItemData );
327 				m_pToolBar->SetItemCommand( nId, aURL );
328 
329                 Reference< XStatusListener > xController;
330 
331                 sal_Bool bMustBeInit( sal_True );
332 
333                 // Support external toolbar controller for add-ons!
334                 if ( m_xToolbarControllerRegistration.is() &&
335                      m_xToolbarControllerRegistration->hasController( aURL, m_aModuleIdentifier ))
336                 {
337                     if ( xToolbarControllerFactory.is() )
338                     {
339                         Sequence< Any > aArgs(5);
340                         PropertyValue   aPropValue;
341 
342                         aPropValue.Name     = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleName" ));
343                         aPropValue.Value    <<= m_aModuleIdentifier;
344                         aArgs[0] <<= aPropValue;
345                         aPropValue.Name     = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
346                         aPropValue.Value    <<= m_xFrame;
347                         aArgs[1] <<= aPropValue;
348                         aPropValue.Name     = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" ));
349                         aPropValue.Value    <<= m_xServiceManager;
350                         aArgs[2] <<= aPropValue;
351                         aPropValue.Name     = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" ));
352                         aPropValue.Value    <<= xToolbarWindow;
353                         aArgs[3] <<= aPropValue;
354                         aPropValue.Name     = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ItemId" ));
355                         aPropValue.Value    = makeAny( sal_Int32( nId ));
356                         aArgs[4] <<= aPropValue;
357 
358                         try
359                         {
360                             xController = Reference< XStatusListener >( xToolbarControllerFactory->createInstanceWithArgumentsAndContext(
361                                                                             aURL, aArgs, xComponentContext ),
362                                                                         UNO_QUERY );
363                         }
364                         catch ( uno::Exception& )
365                         {
366                         }
367                         bMustBeInit = sal_False; // factory called init already!
368                     }
369                 }
370                 else
371                 {
372                     ::cppu::OWeakObject* pController = 0;
373 
374                     pController = ToolBarMerger::CreateController( m_xServiceManager, m_xFrame, m_pToolBar, aURL, nId, nWidth, aControlType );
375                     xController = Reference< XStatusListener >( pController, UNO_QUERY );
376                 }
377 
378                 // insert controller to the map
379                 m_aControllerMap[nId] = xController;
380 
381                 Reference< XInitialization > xInit( xController, UNO_QUERY );
382                 if ( xInit.is() && bMustBeInit )
383                 {
384                     PropertyValue aPropValue;
385                     Sequence< Any > aArgs( 3 );
386                     aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
387                     aPropValue.Value <<= m_xFrame;
388                     aArgs[0] <<= aPropValue;
389                     aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" ));
390                     aPropValue.Value <<= aURL;
391                     aArgs[1] <<= aPropValue;
392                     aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" ));
393                     aPropValue.Value <<= m_xServiceManager;
394                     aArgs[2] <<= aPropValue;
395                     try
396                     {
397                         xInit->initialize( aArgs );
398                     }
399                     catch ( uno::Exception& )
400                     {
401                     }
402                 }
403 
404                 // Request a item window from the toolbar controller and set it at the VCL toolbar
405                 Reference< XToolbarController > xTbxController( xController, UNO_QUERY );
406                 if ( xTbxController.is() && xToolbarWindow.is() )
407                 {
408                     Reference< XWindow > xWindow = xTbxController->createItemWindow( xToolbarWindow );
409                     if ( xWindow.is() )
410                     {
411                         Window* pItemWin = VCLUnoHelper::GetWindow( xWindow );
412                         if ( pItemWin )
413                         {
414                             WindowType nType = pItemWin->GetType();
415                             if ( nType == WINDOW_LISTBOX || nType == WINDOW_MULTILISTBOX || nType == WINDOW_COMBOBOX )
416                                 pItemWin->SetAccessibleName( m_pToolBar->GetItemText( nId ) );
417 				            m_pToolBar->SetItemWindow( nId, pItemWin );
418                         }
419                     }
420                 }
421 
422                 // Notify controller implementation to its listeners. Controller is now useable from outside.
423                 Reference< XUpdatable > xUpdatable( xController, UNO_QUERY );
424                 if ( xUpdatable.is() )
425                 {
426                     try
427                     {
428                         xUpdatable->update();
429                     }
430                     catch ( uno::Exception& )
431                     {
432                     }
433                 }
434 
435                 ++nId;
436 				++nElements;
437 			}
438 		}
439 	}
440 
441     AddFrameActionListener();
442 }
443 
444 IMPL_LINK( AddonsToolBarManager, Click, ToolBox*, EMPTYARG )
445 {
446     if ( m_bDisposed )
447         return 1;
448 
449     sal_uInt16 nId( m_pToolBar->GetCurItemId() );
450     ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId );
451     if ( pIter != m_aControllerMap.end() )
452     {
453         Reference< XToolbarController > xController( pIter->second, UNO_QUERY );
454 
455         if ( xController.is() )
456             xController->click();
457     }
458 
459     return 1;
460 }
461 
462 IMPL_LINK( AddonsToolBarManager, DoubleClick, ToolBox*, EMPTYARG )
463 {
464     if ( m_bDisposed )
465         return 1;
466 
467     sal_uInt16 nId( m_pToolBar->GetCurItemId() );
468     ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId );
469     if ( pIter != m_aControllerMap.end() )
470     {
471         Reference< XToolbarController > xController( pIter->second, UNO_QUERY );
472 
473         if ( xController.is() )
474             xController->doubleClick();
475     }
476 
477     return 1;
478 }
479 
480 IMPL_LINK( AddonsToolBarManager, Command, CommandEvent*, EMPTYARG )
481 {
482     ResetableGuard aGuard( m_aLock );
483 
484     if ( m_bDisposed )
485         return 1;
486 
487     return 0;
488 }
489 
490 IMPL_LINK( AddonsToolBarManager, Select, ToolBox*, EMPTYARG )
491 {
492     if ( m_bDisposed )
493         return 1;
494 
495     sal_Int16   nKeyModifier( (sal_Int16)m_pToolBar->GetModifier() );
496     sal_uInt16      nId( m_pToolBar->GetCurItemId() );
497     ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId );
498     if ( pIter != m_aControllerMap.end() )
499     {
500         Reference< XToolbarController > xController( pIter->second, UNO_QUERY );
501 
502         if ( xController.is() )
503             xController->execute( nKeyModifier );
504     }
505 
506     return 1;
507 }
508 
509 IMPL_LINK( AddonsToolBarManager, Highlight, ToolBox*, EMPTYARG )
510 {
511     return 1;
512 }
513 
514 IMPL_LINK( AddonsToolBarManager, Activate, ToolBox*, EMPTYARG )
515 {
516     return 1;
517 }
518 
519 IMPL_LINK( AddonsToolBarManager, Deactivate, ToolBox*, EMPTYARG )
520 {
521     return 1;
522 }
523 
524 IMPL_LINK( AddonsToolBarManager, StateChanged, StateChangedType*, pStateChangedType )
525 {
526 	if ( *pStateChangedType == STATE_CHANGE_CONTROLBACKGROUND )
527 	{
528 		// Check if we need to get new images for normal/high contrast mode
529 		CheckAndUpdateImages();
530 	}
531     return 1;
532 }
533 
534 IMPL_LINK( AddonsToolBarManager, DataChanged, DataChangedEvent*, pDataChangedEvent  )
535 {
536 	if ((( pDataChangedEvent->GetType() == DATACHANGED_SETTINGS	)	||
537 		(  pDataChangedEvent->GetType() == DATACHANGED_DISPLAY	))	&&
538         ( pDataChangedEvent->GetFlags() & SETTINGS_STYLE		))
539 	{
540 		// Check if we need to get new images for normal/high contrast mode
541 		CheckAndUpdateImages();
542 	}
543 
544     for ( sal_uInt16 nPos = 0; nPos < m_pToolBar->GetItemCount(); ++nPos )
545 	{
546         const sal_uInt16 nId = m_pToolBar->GetItemId(nPos);
547         Window* pWindow = m_pToolBar->GetItemWindow( nId );
548         if ( pWindow )
549         {
550             const DataChangedEvent& rDCEvt( *pDataChangedEvent );
551             pWindow->DataChanged( rDCEvt );
552         }
553     }
554 
555     return 1;
556 }
557 
558 }
559 
560