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 2758 : AddonsToolBarManager::AddonsToolBarManager( const Reference< XComponentContext >& rxContext,
78 : const Reference< XFrame >& rFrame,
79 : const OUString& rResourceName,
80 : ToolBox* pToolBar ) :
81 2758 : ToolBarManager( rxContext, rFrame, rResourceName, pToolBar )
82 : {
83 2758 : m_pToolBar->SetMenuType( TOOLBOX_MENUTYPE_CLIPPEDITEMS );
84 2758 : m_pToolBar->SetSelectHdl( LINK( this, AddonsToolBarManager, Select) );
85 2758 : m_pToolBar->SetClickHdl( LINK( this, AddonsToolBarManager, Click ) );
86 2758 : m_pToolBar->SetDoubleClickHdl( LINK( this, AddonsToolBarManager, DoubleClick ) );
87 2758 : m_pToolBar->SetCommandHdl( LINK( this, AddonsToolBarManager, Command ) );
88 2758 : m_pToolBar->SetStateChangedHdl( LINK( this, AddonsToolBarManager, StateChanged ) );
89 2758 : m_pToolBar->SetDataChangedHdl( LINK( this, AddonsToolBarManager, DataChanged ) );
90 2758 : }
91 :
92 5510 : AddonsToolBarManager::~AddonsToolBarManager()
93 : {
94 5510 : }
95 :
96 27580 : static bool IsCorrectContext( const OUString& rModuleIdentifier, const OUString& aContextList )
97 : {
98 27580 : if ( aContextList.isEmpty() )
99 0 : return true;
100 :
101 27580 : if ( !rModuleIdentifier.isEmpty() )
102 : {
103 27580 : sal_Int32 nIndex = aContextList.indexOf( rModuleIdentifier );
104 27580 : return ( nIndex >= 0 );
105 : }
106 :
107 0 : return false;
108 : }
109 :
110 0 : static Image RetrieveImage( Reference< com::sun::star::frame::XFrame >& rFrame,
111 : const OUString& aImageId,
112 : const OUString& aURL,
113 : bool bBigImage
114 : )
115 : {
116 0 : Image aImage;
117 :
118 0 : if ( !aImageId.isEmpty() )
119 : {
120 0 : aImage = framework::AddonsOptions().GetImageFromURL( aImageId, bBigImage );
121 0 : if ( !!aImage )
122 0 : return aImage;
123 : else
124 0 : aImage = GetImageFromURL( rFrame, aImageId, bBigImage );
125 0 : if ( !!aImage )
126 0 : return aImage;
127 : }
128 :
129 0 : aImage = framework::AddonsOptions().GetImageFromURL( aURL, bBigImage );
130 0 : if ( !aImage )
131 0 : aImage = GetImageFromURL( rFrame, aImageId, bBigImage );
132 :
133 0 : return aImage;
134 : }
135 :
136 : // XComponent
137 2755 : void SAL_CALL AddonsToolBarManager::dispose() throw( RuntimeException, std::exception )
138 : {
139 2755 : Reference< XComponent > xThis( static_cast< OWeakObject* >(this), UNO_QUERY );
140 :
141 : {
142 : // Remove addon specific data from toolbar items.
143 2755 : SolarMutexGuard g;
144 30305 : for ( sal_uInt16 n = 0; n < m_pToolBar->GetItemCount(); n++ )
145 : {
146 27550 : sal_uInt16 nId( m_pToolBar->GetItemId( n ) );
147 :
148 27550 : if ( nId > 0 )
149 : {
150 27550 : AddonsParams* pRuntimeItemData = static_cast<AddonsParams*>(m_pToolBar->GetItemData( nId ));
151 27550 : if ( pRuntimeItemData )
152 27550 : delete pRuntimeItemData;
153 27550 : m_pToolBar->SetItemData( nId, NULL );
154 : }
155 2755 : }
156 : }
157 :
158 : // Base class will destroy our m_pToolBar member
159 2755 : ToolBarManager::dispose();
160 2755 : }
161 :
162 0 : bool AddonsToolBarManager::MenuItemAllowed( sal_uInt16 nId ) const
163 : {
164 0 : if (( nId == MENUITEM_TOOLBAR_VISIBLEBUTTON ) ||
165 : ( nId == MENUITEM_TOOLBAR_CUSTOMIZETOOLBAR ))
166 0 : return false;
167 : else
168 0 : return true;
169 : }
170 :
171 0 : void AddonsToolBarManager::RefreshImages()
172 : {
173 0 : bool bBigImages( SvtMiscOptions().AreCurrentSymbolsLarge() );
174 0 : for ( sal_uInt16 nPos = 0; nPos < m_pToolBar->GetItemCount(); nPos++ )
175 : {
176 0 : sal_uInt16 nId( m_pToolBar->GetItemId( nPos ) );
177 :
178 0 : if ( nId > 0 )
179 : {
180 0 : OUString aCommandURL = m_pToolBar->GetItemCommand( nId );
181 0 : OUString aImageId;
182 0 : AddonsParams* pRuntimeItemData = static_cast<AddonsParams*>(m_pToolBar->GetItemData( nId ));
183 0 : if ( pRuntimeItemData )
184 0 : aImageId = pRuntimeItemData->aImageId;
185 :
186 : m_pToolBar->SetItemImage(
187 : nId,
188 : RetrieveImage( m_xFrame, aImageId, aCommandURL, bBigImages )
189 0 : );
190 : }
191 : }
192 0 : m_pToolBar->SetToolboxButtonSize( bBigImages ? TOOLBOX_BUTTONSIZE_LARGE : TOOLBOX_BUTTONSIZE_SMALL );
193 0 : ::Size aSize = m_pToolBar->CalcWindowSizePixel();
194 0 : m_pToolBar->SetOutputSizePixel( aSize );
195 0 : }
196 :
197 2758 : void AddonsToolBarManager::FillToolbar( const Sequence< Sequence< PropertyValue > >& rAddonToolbar )
198 : {
199 2758 : SolarMutexGuard g;
200 :
201 2758 : if ( m_bDisposed )
202 2758 : return;
203 :
204 2758 : sal_uInt16 nId( 1 );
205 :
206 2758 : RemoveControllers();
207 :
208 2758 : m_pToolBar->Clear();
209 2758 : m_aControllerMap.clear();
210 :
211 5516 : OUString aModuleIdentifier;
212 : try
213 : {
214 2758 : Reference< XModuleManager2 > xModuleManager = ModuleManager::create( m_xContext );
215 2758 : aModuleIdentifier = xModuleManager->identify( m_xFrame );
216 : }
217 0 : catch ( const Exception& )
218 : {
219 : }
220 :
221 2758 : sal_uInt32 nElements( 0 );
222 2758 : bool bAppendSeparator( false );
223 5516 : Reference< XWindow > xToolbarWindow = VCLUnoHelper::GetInterface( m_pToolBar );
224 30338 : for ( sal_uInt32 n = 0; n < (sal_uInt32)rAddonToolbar.getLength(); n++ )
225 : {
226 27580 : OUString aURL;
227 55160 : OUString aTitle;
228 55160 : OUString aImageId;
229 55160 : OUString aContext;
230 55160 : OUString aTarget;
231 55160 : OUString aControlType;
232 27580 : sal_uInt16 nWidth( 0 );
233 :
234 27580 : const Sequence< PropertyValue >& rSeq = rAddonToolbar[n];
235 :
236 27580 : ToolBarMerger::ConvertSequenceToValues( rSeq, aURL, aTitle, aImageId, aTarget, aContext, aControlType, nWidth );
237 :
238 27580 : if ( IsCorrectContext( aModuleIdentifier, aContext ))
239 : {
240 27580 : if ( aURL == TOOLBOXITEM_SEPARATOR_STR )
241 : {
242 0 : sal_uInt16 nCount = m_pToolBar->GetItemCount();
243 0 : if ( nCount > 0 && ( m_pToolBar->GetItemType( nCount-1 ) != ToolBoxItemType::SEPARATOR ) && nElements > 0 )
244 : {
245 0 : nElements = 0;
246 0 : m_pToolBar->InsertSeparator();
247 : }
248 : }
249 : else
250 : {
251 27580 : sal_uInt16 nCount = m_pToolBar->GetItemCount();
252 27580 : if ( bAppendSeparator && nCount > 0 && ( m_pToolBar->GetItemType( nCount-1 ) != ToolBoxItemType::SEPARATOR ))
253 : {
254 : // We have to append a separator first if the last item is not a separator
255 0 : m_pToolBar->InsertSeparator();
256 : }
257 27580 : bAppendSeparator = false;
258 :
259 27580 : m_pToolBar->InsertItem( nId, aTitle );
260 :
261 : // don't setup images yet, AddonsToolbarWrapper::populateImages does that.
262 :
263 : // Create TbRuntimeItemData to hold additional information we will need in the future
264 27580 : AddonsParams* pRuntimeItemData = new AddonsParams;
265 27580 : pRuntimeItemData->aImageId = aImageId;
266 27580 : pRuntimeItemData->aTarget = aTarget;
267 27580 : m_pToolBar->SetItemData( nId, pRuntimeItemData );
268 27580 : m_pToolBar->SetItemCommand( nId, aURL );
269 :
270 27580 : Reference< XStatusListener > xController;
271 :
272 27580 : bool bMustBeInit( true );
273 :
274 : // Support external toolbar controller for add-ons!
275 55160 : if ( m_xToolbarControllerFactory.is() &&
276 27580 : m_xToolbarControllerFactory->hasController( aURL, m_aModuleIdentifier ))
277 : {
278 0 : Sequence< Any > aArgs(5);
279 0 : PropertyValue aPropValue;
280 :
281 0 : aPropValue.Name = "ModuleIdentifier";
282 0 : aPropValue.Value <<= m_aModuleIdentifier;
283 0 : aArgs[0] <<= aPropValue;
284 0 : aPropValue.Name = "Frame";
285 0 : aPropValue.Value <<= m_xFrame;
286 0 : aArgs[1] <<= aPropValue;
287 0 : aPropValue.Name = "ServiceManager";
288 0 : aPropValue.Value <<= Reference<XMultiServiceFactory>(m_xContext->getServiceManager(), UNO_QUERY_THROW);
289 0 : aArgs[2] <<= aPropValue;
290 0 : aPropValue.Name = "ParentWindow";
291 0 : aPropValue.Value <<= xToolbarWindow;
292 0 : aArgs[3] <<= aPropValue;
293 0 : aPropValue.Name = "ItemId";
294 0 : aPropValue.Value = makeAny( sal_Int32( nId ));
295 0 : aArgs[4] <<= aPropValue;
296 :
297 : try
298 : {
299 0 : xController = Reference< XStatusListener >( m_xToolbarControllerFactory->createInstanceWithArgumentsAndContext(
300 0 : aURL, aArgs, m_xContext ),
301 0 : UNO_QUERY );
302 : }
303 0 : catch ( uno::Exception& )
304 : {
305 : }
306 0 : bMustBeInit = false; // factory called init already!
307 : }
308 : else
309 : {
310 27580 : ::cppu::OWeakObject* pController = 0;
311 :
312 27580 : pController = ToolBarMerger::CreateController( m_xContext, m_xFrame, m_pToolBar, aURL, nId, nWidth, aControlType );
313 27580 : xController = Reference< XStatusListener >( pController, UNO_QUERY );
314 : }
315 :
316 : // insert controller to the map
317 27580 : m_aControllerMap[nId] = xController;
318 :
319 55160 : Reference< XInitialization > xInit( xController, UNO_QUERY );
320 27580 : if ( xInit.is() && bMustBeInit )
321 : {
322 27580 : PropertyValue aPropValue;
323 55160 : Sequence< Any > aArgs( 3 );
324 27580 : aPropValue.Name = "Frame";
325 27580 : aPropValue.Value <<= m_xFrame;
326 27580 : aArgs[0] <<= aPropValue;
327 27580 : aPropValue.Name = "CommandURL";
328 27580 : aPropValue.Value <<= aURL;
329 27580 : aArgs[1] <<= aPropValue;
330 27580 : aPropValue.Name = "ServiceManager";
331 27580 : aPropValue.Value <<= Reference<XMultiServiceFactory>(m_xContext->getServiceManager(), UNO_QUERY_THROW);
332 27580 : aArgs[2] <<= aPropValue;
333 : try
334 : {
335 27580 : xInit->initialize( aArgs );
336 : }
337 0 : catch ( const uno::Exception& )
338 : {
339 27580 : }
340 : }
341 :
342 : // Request a item window from the toolbar controller and set it at the VCL toolbar
343 55160 : Reference< XToolbarController > xTbxController( xController, UNO_QUERY );
344 27580 : if ( xTbxController.is() && xToolbarWindow.is() )
345 : {
346 27580 : Reference< XWindow > xWindow = xTbxController->createItemWindow( xToolbarWindow );
347 27580 : if ( xWindow.is() )
348 : {
349 0 : vcl::Window* pItemWin = VCLUnoHelper::GetWindow( xWindow );
350 0 : if ( pItemWin )
351 : {
352 0 : WindowType nType = pItemWin->GetType();
353 0 : if ( nType == WINDOW_LISTBOX || nType == WINDOW_MULTILISTBOX || nType == WINDOW_COMBOBOX )
354 0 : pItemWin->SetAccessibleName( m_pToolBar->GetItemText( nId ) );
355 0 : m_pToolBar->SetItemWindow( nId, pItemWin );
356 : }
357 27580 : }
358 : }
359 :
360 : // Notify controller implementation to its listeners. Controller is now useable from outside.
361 55160 : Reference< XUpdatable > xUpdatable( xController, UNO_QUERY );
362 27580 : if ( xUpdatable.is() )
363 : {
364 : try
365 : {
366 27580 : xUpdatable->update();
367 : }
368 0 : catch ( const uno::Exception& )
369 : {
370 : }
371 : }
372 :
373 27580 : ++nId;
374 55160 : ++nElements;
375 : }
376 : }
377 27580 : }
378 :
379 5516 : AddFrameActionListener();
380 : }
381 :
382 0 : IMPL_LINK_NOARG_TYPED(AddonsToolBarManager, Click, ToolBox *, void)
383 : {
384 0 : if ( m_bDisposed )
385 0 : return;
386 :
387 0 : sal_uInt16 nId( m_pToolBar->GetCurItemId() );
388 0 : ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId );
389 0 : if ( pIter != m_aControllerMap.end() )
390 : {
391 0 : Reference< XToolbarController > xController( pIter->second, UNO_QUERY );
392 :
393 0 : if ( xController.is() )
394 0 : xController->click();
395 : }
396 : }
397 :
398 0 : IMPL_LINK_NOARG_TYPED(AddonsToolBarManager, DoubleClick, ToolBox *, void)
399 : {
400 0 : if ( m_bDisposed )
401 0 : return;
402 :
403 0 : sal_uInt16 nId( m_pToolBar->GetCurItemId() );
404 0 : ToolBarControllerMap::const_iterator pIter = m_aControllerMap.find( nId );
405 0 : if ( pIter != m_aControllerMap.end() )
406 : {
407 0 : Reference< XToolbarController > xController( pIter->second, UNO_QUERY );
408 :
409 0 : if ( xController.is() )
410 0 : xController->doubleClick();
411 : }
412 : }
413 :
414 0 : IMPL_LINK_NOARG_TYPED(AddonsToolBarManager, Select, ToolBox *, void)
415 : {
416 0 : if ( m_bDisposed )
417 0 : return;
418 :
419 0 : sal_Int16 nKeyModifier( (sal_Int16)m_pToolBar->GetModifier() );
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->execute( nKeyModifier );
428 : }
429 : }
430 :
431 8084 : IMPL_LINK_TYPED( AddonsToolBarManager, StateChanged, StateChangedType const *, pStateChangedType, void )
432 : {
433 4042 : if ( *pStateChangedType == StateChangedType::ControlBackground )
434 : {
435 0 : CheckAndUpdateImages();
436 : }
437 4042 : }
438 :
439 6 : IMPL_LINK_TYPED( AddonsToolBarManager, DataChanged, DataChangedEvent const *, pDataChangedEvent, void )
440 : {
441 9 : if ((( pDataChangedEvent->GetType() == DataChangedEventType::SETTINGS ) ||
442 12 : ( pDataChangedEvent->GetType() == DataChangedEventType::DISPLAY )) &&
443 12 : ( pDataChangedEvent->GetFlags() & AllSettingsFlags::STYLE ))
444 : {
445 0 : CheckAndUpdateImages();
446 : }
447 :
448 33 : for ( sal_uInt16 nPos = 0; nPos < m_pToolBar->GetItemCount(); ++nPos )
449 : {
450 30 : const sal_uInt16 nId = m_pToolBar->GetItemId(nPos);
451 30 : vcl::Window* pWindow = m_pToolBar->GetItemWindow( nId );
452 30 : if ( pWindow )
453 : {
454 3 : const DataChangedEvent& rDCEvt( *pDataChangedEvent );
455 3 : pWindow->DataChanged( rDCEvt );
456 : }
457 : }
458 3 : }
459 :
460 648 : }
461 :
462 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|