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/addonstoolbarmanager.hxx>
21 : #include <uielement/toolbarmerger.hxx>
22 :
23 : #include <uielement/toolbar.hxx>
24 : #include <uielement/generictoolbarcontroller.hxx>
25 : #include <threadhelp/resetableguard.hxx>
26 : #include "services.h"
27 : #include <framework/imageproducer.hxx>
28 : #include <framework/sfxhelperfunctions.hxx>
29 : #include <classes/fwkresid.hxx>
30 : #include <classes/resource.hrc>
31 : #include <framework/addonsoptions.hxx>
32 : #include <uielement/comboboxtoolbarcontroller.hxx>
33 : #include <uielement/imagebuttontoolbarcontroller.hxx>
34 : #include <uielement/togglebuttontoolbarcontroller.hxx>
35 : #include <uielement/buttontoolbarcontroller.hxx>
36 : #include <uielement/spinfieldtoolbarcontroller.hxx>
37 : #include <uielement/edittoolbarcontroller.hxx>
38 : #include <uielement/dropdownboxtoolbarcontroller.hxx>
39 : #include <uielement/toolbarmerger.hxx>
40 :
41 : #include <com/sun/star/ui/ItemType.hpp>
42 : #include <com/sun/star/frame/ModuleManager.hpp>
43 : #include <com/sun/star/frame/XToolbarController.hpp>
44 : #include <com/sun/star/frame/XDispatchProvider.hpp>
45 : #include <com/sun/star/lang/XServiceInfo.hpp>
46 : #include <com/sun/star/frame/XLayoutManager.hpp>
47 : #include <com/sun/star/ui/DockingArea.hpp>
48 : #include <com/sun/star/lang/XMultiComponentFactory.hpp>
49 : #include <comphelper/processfactory.hxx>
50 : #include <svtools/imgdef.hxx>
51 : #include <svtools/toolboxcontroller.hxx>
52 : #include <toolkit/unohlp.hxx>
53 :
54 : #include <svtools/miscopt.hxx>
55 : #include <vcl/svapp.hxx>
56 : #include <vcl/menu.hxx>
57 : #include <vcl/syswin.hxx>
58 : #include <vcl/taskpanelist.hxx>
59 :
60 : //_________________________________________________________________________________________________________________
61 : // namespaces
62 : //_________________________________________________________________________________________________________________
63 :
64 : using namespace ::com::sun::star;
65 : using namespace ::com::sun::star::awt;
66 : using namespace ::com::sun::star::beans;
67 : using namespace ::com::sun::star::uno;
68 : using namespace ::com::sun::star::lang;
69 : using namespace ::com::sun::star::frame;
70 : using namespace ::com::sun::star::util;
71 : using namespace ::com::sun::star::container;
72 : using namespace ::com::sun::star::frame;
73 : using namespace ::com::sun::star::ui;
74 :
75 : namespace framework
76 : {
77 :
78 : static const char TOOLBOXITEM_SEPARATOR_STR[] = "private:separator";
79 : static const sal_uInt16 TOOLBOXITEM_SEPARATOR_STR_LEN = sizeof( TOOLBOXITEM_SEPARATOR_STR )-1;
80 :
81 236 : AddonsToolBarManager::AddonsToolBarManager( const Reference< XMultiServiceFactory >& rServiceManager,
82 : const Reference< XFrame >& rFrame,
83 : const rtl::OUString& rResourceName,
84 : ToolBar* pToolBar ) :
85 236 : ToolBarManager( rServiceManager, rFrame, rResourceName, pToolBar )
86 : {
87 236 : m_pToolBar->SetMenuType( TOOLBOX_MENUTYPE_CLIPPEDITEMS );
88 236 : m_pToolBar->SetSelectHdl( LINK( this, AddonsToolBarManager, Select) );
89 236 : m_pToolBar->SetActivateHdl( LINK( this, AddonsToolBarManager, Activate) );
90 236 : m_pToolBar->SetDeactivateHdl( LINK( this, AddonsToolBarManager, Deactivate) );
91 236 : m_pToolBar->SetClickHdl( LINK( this, AddonsToolBarManager, Click ) );
92 236 : m_pToolBar->SetDoubleClickHdl( LINK( this, AddonsToolBarManager, DoubleClick ) );
93 236 : m_pToolBar->SetCommandHdl( LINK( this, AddonsToolBarManager, Command ) );
94 236 : m_pToolBar->SetStateChangedHdl( LINK( this, AddonsToolBarManager, StateChanged ) );
95 236 : m_pToolBar->SetDataChangedHdl( LINK( this, AddonsToolBarManager, DataChanged ) );
96 236 : }
97 :
98 126 : AddonsToolBarManager::~AddonsToolBarManager()
99 : {
100 126 : }
101 :
102 2360 : static sal_Bool IsCorrectContext( const ::rtl::OUString& rModuleIdentifier, const ::rtl::OUString& aContextList )
103 : {
104 2360 : if ( aContextList.isEmpty() )
105 0 : return sal_True;
106 :
107 2360 : if ( !rModuleIdentifier.isEmpty() )
108 : {
109 2360 : sal_Int32 nIndex = aContextList.indexOf( rModuleIdentifier );
110 2360 : return ( nIndex >= 0 );
111 : }
112 :
113 0 : return sal_False;
114 : }
115 :
116 2360 : static Image RetrieveImage( Reference< com::sun::star::frame::XFrame >& rFrame,
117 : const rtl::OUString& aImageId,
118 : const rtl::OUString& aURL,
119 : sal_Bool bBigImage
120 : )
121 : {
122 2360 : Image aImage;
123 :
124 2360 : if ( !aImageId.isEmpty() )
125 : {
126 0 : aImage = framework::AddonsOptions().GetImageFromURL( aImageId, bBigImage );
127 0 : if ( !!aImage )
128 0 : return aImage;
129 : else
130 0 : aImage = GetImageFromURL( rFrame, aImageId, bBigImage );
131 0 : if ( !!aImage )
132 0 : return aImage;
133 : }
134 :
135 2360 : aImage = framework::AddonsOptions().GetImageFromURL( aURL, bBigImage );
136 2360 : if ( !aImage )
137 2360 : aImage = GetImageFromURL( rFrame, aImageId, bBigImage );
138 :
139 2360 : return aImage;
140 : }
141 :
142 : // XComponent
143 63 : void SAL_CALL AddonsToolBarManager::dispose() throw( RuntimeException )
144 : {
145 63 : Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY );
146 :
147 : {
148 : // Remove addon specific data from toolbar items.
149 63 : ResetableGuard aGuard( m_aLock );
150 693 : for ( sal_uInt16 n = 0; n < m_pToolBar->GetItemCount(); n++ )
151 : {
152 630 : sal_uInt16 nId( m_pToolBar->GetItemId( n ) );
153 :
154 630 : if ( nId > 0 )
155 : {
156 630 : AddonsParams* pRuntimeItemData = (AddonsParams*)m_pToolBar->GetItemData( nId );
157 630 : if ( pRuntimeItemData )
158 630 : delete pRuntimeItemData;
159 630 : m_pToolBar->SetItemData( nId, NULL );
160 : }
161 63 : }
162 : }
163 :
164 : // Base class will destroy our m_pToolBar member
165 63 : ToolBarManager::dispose();
166 63 : }
167 :
168 0 : bool AddonsToolBarManager::MenuItemAllowed( sal_uInt16 nId ) const
169 : {
170 0 : if (( nId == MENUITEM_TOOLBAR_VISIBLEBUTTON ) ||
171 : ( nId == MENUITEM_TOOLBAR_CUSTOMIZETOOLBAR ))
172 0 : return false;
173 : else
174 0 : return true;
175 : }
176 :
177 0 : void AddonsToolBarManager::RefreshImages()
178 : {
179 0 : sal_Bool bBigImages( SvtMiscOptions().AreCurrentSymbolsLarge() );
180 0 : for ( sal_uInt16 nPos = 0; nPos < m_pToolBar->GetItemCount(); nPos++ )
181 : {
182 0 : sal_uInt16 nId( m_pToolBar->GetItemId( nPos ) );
183 :
184 0 : if ( nId > 0 )
185 : {
186 0 : ::rtl::OUString aCommandURL = m_pToolBar->GetItemCommand( nId );
187 0 : ::rtl::OUString aImageId;
188 0 : AddonsParams* pRuntimeItemData = (AddonsParams*)m_pToolBar->GetItemData( nId );
189 0 : if ( pRuntimeItemData )
190 0 : aImageId = pRuntimeItemData->aImageId;
191 :
192 : m_pToolBar->SetItemImage(
193 : nId,
194 : RetrieveImage( m_xFrame, aImageId, aCommandURL, bBigImages )
195 0 : );
196 : }
197 : }
198 0 : m_pToolBar->SetToolboxButtonSize( bBigImages ? TOOLBOX_BUTTONSIZE_LARGE : TOOLBOX_BUTTONSIZE_SMALL );
199 0 : ::Size aSize = m_pToolBar->CalcWindowSizePixel();
200 0 : m_pToolBar->SetOutputSizePixel( aSize );
201 0 : }
202 :
203 236 : void AddonsToolBarManager::FillToolbar( const Sequence< Sequence< PropertyValue > >& rAddonToolbar )
204 : {
205 236 : ResetableGuard aGuard( m_aLock );
206 :
207 236 : if ( m_bDisposed )
208 236 : return;
209 :
210 236 : sal_uInt16 nId( 1 );
211 :
212 236 : RemoveControllers();
213 :
214 236 : m_pToolBar->Clear();
215 236 : m_aControllerMap.clear();
216 :
217 236 : ::rtl::OUString aModuleIdentifier;
218 : try
219 : {
220 236 : Reference< XModuleManager2 > xModuleManager = ModuleManager::create( comphelper::getComponentContext(m_xServiceManager) );
221 236 : aModuleIdentifier = xModuleManager->identify( m_xFrame );
222 : }
223 0 : catch ( const Exception& )
224 : {
225 : }
226 :
227 236 : Reference< XMultiComponentFactory > xToolbarControllerFactory( m_xToolbarControllerRegistration, UNO_QUERY );
228 : Reference< XComponentContext > xComponentContext(
229 236 : comphelper::getComponentContext( m_xServiceManager ) );
230 :
231 236 : sal_uInt32 nElements( 0 );
232 236 : sal_Bool bAppendSeparator( sal_False );
233 236 : Reference< XWindow > xToolbarWindow = VCLUnoHelper::GetInterface( m_pToolBar );
234 2596 : for ( sal_uInt32 n = 0; n < (sal_uInt32)rAddonToolbar.getLength(); n++ )
235 : {
236 2360 : rtl::OUString aURL;
237 2360 : rtl::OUString aTitle;
238 2360 : rtl::OUString aImageId;
239 2360 : rtl::OUString aContext;
240 2360 : rtl::OUString aTarget;
241 2360 : rtl::OUString aControlType;
242 2360 : sal_uInt16 nWidth( 0 );
243 :
244 2360 : const Sequence< PropertyValue >& rSeq = rAddonToolbar[n];
245 :
246 2360 : ToolBarMerger::ConvertSequenceToValues( rSeq, aURL, aTitle, aImageId, aTarget, aContext, aControlType, nWidth );
247 :
248 2360 : if ( IsCorrectContext( aModuleIdentifier, aContext ))
249 : {
250 2360 : if ( aURL.equalsAsciiL( TOOLBOXITEM_SEPARATOR_STR, TOOLBOXITEM_SEPARATOR_STR_LEN ))
251 : {
252 0 : sal_uInt16 nCount = m_pToolBar->GetItemCount();
253 0 : if ( nCount > 0 && ( m_pToolBar->GetItemType( nCount-1 ) != TOOLBOXITEM_SEPARATOR ) && nElements > 0 )
254 : {
255 0 : nElements = 0;
256 0 : m_pToolBar->InsertSeparator();
257 : }
258 : }
259 : else
260 : {
261 2360 : sal_uInt16 nCount = m_pToolBar->GetItemCount();
262 2360 : if ( bAppendSeparator && nCount > 0 && ( m_pToolBar->GetItemType( nCount-1 ) != TOOLBOXITEM_SEPARATOR ))
263 : {
264 : // We have to append a separator first if the last item is not a separator
265 0 : m_pToolBar->InsertSeparator();
266 : }
267 2360 : bAppendSeparator = sal_False;
268 :
269 2360 : m_pToolBar->InsertItem( nId, aTitle );
270 :
271 2360 : Image aImage = RetrieveImage( m_xFrame, aImageId, aURL, !m_bSmallSymbols );
272 2360 : if ( !!aImage )
273 0 : m_pToolBar->SetItemImage( nId, aImage );
274 :
275 : // Create TbRuntimeItemData to hold additional information we will need in the future
276 2360 : AddonsParams* pRuntimeItemData = new AddonsParams;
277 2360 : pRuntimeItemData->aImageId = aImageId;
278 2360 : pRuntimeItemData->aTarget = aTarget;
279 2360 : m_pToolBar->SetItemData( nId, pRuntimeItemData );
280 2360 : m_pToolBar->SetItemCommand( nId, aURL );
281 :
282 2360 : Reference< XStatusListener > xController;
283 :
284 2360 : sal_Bool bMustBeInit( sal_True );
285 :
286 : // Support external toolbar controller for add-ons!
287 4720 : if ( m_xToolbarControllerRegistration.is() &&
288 2360 : m_xToolbarControllerRegistration->hasController( aURL, m_aModuleIdentifier ))
289 : {
290 0 : if ( xToolbarControllerFactory.is() )
291 : {
292 0 : Sequence< Any > aArgs(5);
293 0 : PropertyValue aPropValue;
294 :
295 0 : aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ModuleName" ));
296 0 : aPropValue.Value <<= m_aModuleIdentifier;
297 0 : aArgs[0] <<= aPropValue;
298 0 : aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
299 0 : aPropValue.Value <<= m_xFrame;
300 0 : aArgs[1] <<= aPropValue;
301 0 : aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" ));
302 0 : aPropValue.Value <<= m_xServiceManager;
303 0 : aArgs[2] <<= aPropValue;
304 0 : aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" ));
305 0 : aPropValue.Value <<= xToolbarWindow;
306 0 : aArgs[3] <<= aPropValue;
307 0 : aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ItemId" ));
308 0 : aPropValue.Value = makeAny( sal_Int32( nId ));
309 0 : aArgs[4] <<= aPropValue;
310 :
311 : try
312 : {
313 0 : xController = Reference< XStatusListener >( xToolbarControllerFactory->createInstanceWithArgumentsAndContext(
314 0 : aURL, aArgs, xComponentContext ),
315 0 : UNO_QUERY );
316 : }
317 0 : catch ( const uno::Exception& )
318 : {
319 : }
320 0 : bMustBeInit = sal_False; // factory called init already!
321 : }
322 : }
323 : else
324 : {
325 2360 : ::cppu::OWeakObject* pController = 0;
326 :
327 2360 : pController = ToolBarMerger::CreateController( m_xServiceManager, m_xFrame, m_pToolBar, aURL, nId, nWidth, aControlType );
328 2360 : xController = Reference< XStatusListener >( pController, UNO_QUERY );
329 : }
330 :
331 : // insert controller to the map
332 2360 : m_aControllerMap[nId] = xController;
333 :
334 2360 : Reference< XInitialization > xInit( xController, UNO_QUERY );
335 2360 : if ( xInit.is() && bMustBeInit )
336 : {
337 2360 : PropertyValue aPropValue;
338 2360 : Sequence< Any > aArgs( 3 );
339 2360 : aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
340 2360 : aPropValue.Value <<= m_xFrame;
341 2360 : aArgs[0] <<= aPropValue;
342 2360 : aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" ));
343 2360 : aPropValue.Value <<= aURL;
344 2360 : aArgs[1] <<= aPropValue;
345 2360 : aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" ));
346 2360 : aPropValue.Value <<= m_xServiceManager;
347 2360 : aArgs[2] <<= aPropValue;
348 : try
349 : {
350 2360 : xInit->initialize( aArgs );
351 : }
352 0 : catch ( const uno::Exception& )
353 : {
354 2360 : }
355 : }
356 :
357 : // Request a item window from the toolbar controller and set it at the VCL toolbar
358 2360 : Reference< XToolbarController > xTbxController( xController, UNO_QUERY );
359 2360 : if ( xTbxController.is() && xToolbarWindow.is() )
360 : {
361 2360 : Reference< XWindow > xWindow = xTbxController->createItemWindow( xToolbarWindow );
362 2360 : if ( xWindow.is() )
363 : {
364 0 : Window* pItemWin = VCLUnoHelper::GetWindow( xWindow );
365 0 : if ( pItemWin )
366 : {
367 0 : WindowType nType = pItemWin->GetType();
368 0 : if ( nType == WINDOW_LISTBOX || nType == WINDOW_MULTILISTBOX || nType == WINDOW_COMBOBOX )
369 0 : pItemWin->SetAccessibleName( m_pToolBar->GetItemText( nId ) );
370 0 : m_pToolBar->SetItemWindow( nId, pItemWin );
371 : }
372 2360 : }
373 : }
374 :
375 : // Notify controller implementation to its listeners. Controller is now useable from outside.
376 2360 : Reference< XUpdatable > xUpdatable( xController, UNO_QUERY );
377 2360 : if ( xUpdatable.is() )
378 : {
379 : try
380 : {
381 2360 : xUpdatable->update();
382 : }
383 0 : catch ( const uno::Exception& )
384 : {
385 : }
386 : }
387 :
388 2360 : ++nId;
389 2360 : ++nElements;
390 : }
391 : }
392 2360 : }
393 :
394 236 : AddFrameActionListener();
395 : }
396 :
397 0 : IMPL_LINK_NOARG(AddonsToolBarManager, Click)
398 : {
399 0 : if ( m_bDisposed )
400 0 : return 1;
401 :
402 0 : sal_uInt16 nId( m_pToolBar->GetCurItemId() );
403 0 : ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId );
404 0 : if ( pIter != m_aControllerMap.end() )
405 : {
406 0 : Reference< XToolbarController > xController( pIter->second, UNO_QUERY );
407 :
408 0 : if ( xController.is() )
409 0 : xController->click();
410 : }
411 :
412 0 : return 1;
413 : }
414 :
415 0 : IMPL_LINK_NOARG(AddonsToolBarManager, DoubleClick)
416 : {
417 0 : if ( m_bDisposed )
418 0 : return 1;
419 :
420 0 : sal_uInt16 nId( m_pToolBar->GetCurItemId() );
421 0 : ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId );
422 0 : if ( pIter != m_aControllerMap.end() )
423 : {
424 0 : Reference< XToolbarController > xController( pIter->second, UNO_QUERY );
425 :
426 0 : if ( xController.is() )
427 0 : xController->doubleClick();
428 : }
429 :
430 0 : return 1;
431 : }
432 :
433 0 : IMPL_LINK_NOARG(AddonsToolBarManager, Command)
434 : {
435 0 : ResetableGuard aGuard( m_aLock );
436 :
437 0 : if ( m_bDisposed )
438 0 : return 1;
439 :
440 0 : return 0;
441 : }
442 :
443 0 : IMPL_LINK_NOARG(AddonsToolBarManager, Select)
444 : {
445 0 : if ( m_bDisposed )
446 0 : return 1;
447 :
448 0 : sal_Int16 nKeyModifier( (sal_Int16)m_pToolBar->GetModifier() );
449 0 : sal_uInt16 nId( m_pToolBar->GetCurItemId() );
450 0 : ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId );
451 0 : if ( pIter != m_aControllerMap.end() )
452 : {
453 0 : Reference< XToolbarController > xController( pIter->second, UNO_QUERY );
454 :
455 0 : if ( xController.is() )
456 0 : xController->execute( nKeyModifier );
457 : }
458 :
459 0 : return 1;
460 : }
461 :
462 0 : IMPL_LINK_NOARG(AddonsToolBarManager, Activate)
463 : {
464 0 : return 1;
465 : }
466 :
467 0 : IMPL_LINK_NOARG(AddonsToolBarManager, Deactivate)
468 : {
469 0 : return 1;
470 : }
471 :
472 692 : IMPL_LINK( AddonsToolBarManager, StateChanged, StateChangedType*, pStateChangedType )
473 : {
474 346 : if ( *pStateChangedType == STATE_CHANGE_CONTROLBACKGROUND )
475 : {
476 0 : CheckAndUpdateImages();
477 : }
478 346 : return 1;
479 : }
480 :
481 184 : IMPL_LINK( AddonsToolBarManager, DataChanged, DataChangedEvent*, pDataChangedEvent )
482 : {
483 184 : if ((( pDataChangedEvent->GetType() == DATACHANGED_SETTINGS ) ||
484 0 : ( pDataChangedEvent->GetType() == DATACHANGED_DISPLAY )) &&
485 92 : ( pDataChangedEvent->GetFlags() & SETTINGS_STYLE ))
486 : {
487 0 : CheckAndUpdateImages();
488 : }
489 :
490 1012 : for ( sal_uInt16 nPos = 0; nPos < m_pToolBar->GetItemCount(); ++nPos )
491 : {
492 920 : const sal_uInt16 nId = m_pToolBar->GetItemId(nPos);
493 920 : Window* pWindow = m_pToolBar->GetItemWindow( nId );
494 920 : if ( pWindow )
495 : {
496 92 : const DataChangedEvent& rDCEvt( *pDataChangedEvent );
497 92 : pWindow->DataChanged( rDCEvt );
498 : }
499 : }
500 :
501 92 : return 1;
502 : }
503 :
504 : }
505 :
506 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|