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