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