Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <framework/actiontriggerhelper.hxx>
30 : : #include <classes/actiontriggerseparatorpropertyset.hxx>
31 : : #include <classes/rootactiontriggercontainer.hxx>
32 : : #include <classes/imagewrapper.hxx>
33 : : #include <framework/addonsoptions.hxx>
34 : : #include <com/sun/star/lang/XServiceInfo.hpp>
35 : : #include <com/sun/star/beans/XPropertySet.hpp>
36 : : #include <com/sun/star/awt/XBitmap.hpp>
37 : : #include <vcl/svapp.hxx>
38 : : #include <osl/mutex.hxx>
39 : : #include <tools/stream.hxx>
40 : : #include <cppuhelper/weak.hxx>
41 : : #include <comphelper/processfactory.hxx>
42 : :
43 : :
44 : : const sal_uInt16 START_ITEMID = 1000;
45 : :
46 : : using namespace com::sun::star::awt;
47 : : using namespace com::sun::star::uno;
48 : : using namespace com::sun::star::lang;
49 : : using namespace com::sun::star::beans;
50 : : using namespace com::sun::star::container;
51 : :
52 : : using ::rtl::OUString;
53 : :
54 : : namespace framework
55 : : {
56 : :
57 : : // ----------------------------------------------------------------------------
58 : : // implementation helper ( menu => ActionTrigger )
59 : : // ----------------------------------------------------------------------------
60 : :
61 : 0 : sal_Bool IsSeparator( Reference< XPropertySet > xPropertySet )
62 : : {
63 [ # # ]: 0 : Reference< XServiceInfo > xServiceInfo( xPropertySet, UNO_QUERY );
64 : : try
65 : : {
66 [ # # ][ # # ]: 0 : return xServiceInfo->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERSEPARATOR )) );
[ # # ][ # # ]
67 : : }
68 [ # # ]: 0 : catch (const Exception&)
69 : : {
70 : : }
71 : :
72 : 0 : return sal_False;
73 : : }
74 : :
75 : 0 : void GetMenuItemAttributes( Reference< XPropertySet > xActionTriggerPropertySet,
76 : : OUString& aMenuLabel,
77 : : OUString& aCommandURL,
78 : : OUString& aHelpURL,
79 : : Reference< XBitmap >& xBitmap,
80 : : Reference< XIndexContainer >& xSubContainer )
81 : : {
82 : 0 : Any a;
83 : :
84 : : try
85 : : {
86 : : // mandatory properties
87 [ # # ][ # # ]: 0 : a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )) );
[ # # ]
88 : 0 : a >>= aMenuLabel;
89 [ # # ][ # # ]: 0 : a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )) );
[ # # ]
90 : 0 : a >>= aCommandURL;
91 [ # # ][ # # ]: 0 : a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Image" )) );
[ # # ]
92 [ # # ]: 0 : a >>= xBitmap;
93 [ # # ][ # # ]: 0 : a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "SubContainer" )) );
[ # # ][ # # ]
94 [ # # ]: 0 : a >>= xSubContainer;
95 : : }
96 [ # # ]: 0 : catch (const Exception&)
97 : : {
98 : : }
99 : :
100 : : // optional properties
101 : : try
102 : : {
103 [ # # ][ # # ]: 0 : a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "HelpURL" )) );
[ # # ][ # # ]
104 : 0 : a >>= aHelpURL;
105 : : }
106 [ # # ]: 0 : catch (const Exception&)
107 : : {
108 : 0 : }
109 : 0 : }
110 : :
111 : 0 : void InsertSubMenuItems( Menu* pSubMenu, sal_uInt16& nItemId, Reference< XIndexContainer > xActionTriggerContainer )
112 : : {
113 [ # # ]: 0 : Reference< XIndexAccess > xIndexAccess( xActionTriggerContainer, UNO_QUERY );
114 [ # # ]: 0 : if ( xIndexAccess.is() )
115 : : {
116 [ # # ]: 0 : AddonsOptions aAddonOptions;
117 [ # # ]: 0 : OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
118 : :
119 [ # # ][ # # ]: 0 : for ( sal_Int32 i = 0; i < xIndexAccess->getCount(); i++ )
[ # # ]
120 : : {
121 : : try
122 : : {
123 : 0 : Reference< XPropertySet > xPropSet;
124 [ # # ][ # # ]: 0 : if (( xIndexAccess->getByIndex( i ) >>= xPropSet ) && ( xPropSet.is() ))
[ # # ][ # # ]
[ # # ]
[ # # # # ]
[ # # ]
125 : : {
126 [ # # ][ # # ]: 0 : if ( IsSeparator( xPropSet ))
127 : : {
128 : : // Separator
129 [ # # ]: 0 : SolarMutexGuard aGuard;
130 [ # # ][ # # ]: 0 : pSubMenu->InsertSeparator();
131 : : }
132 : : else
133 : : {
134 : : // Menu item
135 : 0 : OUString aLabel;
136 : 0 : OUString aCommandURL;
137 : 0 : OUString aHelpURL;
138 : 0 : Reference< XBitmap > xBitmap;
139 : 0 : Reference< XIndexContainer > xSubContainer;
140 : :
141 : 0 : sal_uInt16 nNewItemId = nItemId++;
142 [ # # ]: 0 : GetMenuItemAttributes( xPropSet, aLabel, aCommandURL, aHelpURL, xBitmap, xSubContainer );
143 : :
144 [ # # ]: 0 : SolarMutexGuard aGuard;
145 : : {
146 : : // insert new menu item
147 : 0 : sal_Int32 nIndex = aCommandURL.indexOf( aSlotURL );
148 [ # # ]: 0 : if ( nIndex >= 0 )
149 : : {
150 : : // Special code for our menu implementation: some menu items don't have a
151 : : // command url but uses the item id as a unqiue identifier. These entries
152 : : // got a special url during conversion from menu=>actiontriggercontainer.
153 : : // Now we have to extract this special url and set the correct item id!!!
154 : 0 : nNewItemId = (sal_uInt16)aCommandURL.copy( nIndex+aSlotURL.getLength() ).toInt32();
155 [ # # ][ # # ]: 0 : pSubMenu->InsertItem( nNewItemId, aLabel );
[ # # ]
156 : : }
157 : : else
158 : : {
159 [ # # ][ # # ]: 0 : pSubMenu->InsertItem( nNewItemId, aLabel );
[ # # ]
160 [ # # ][ # # ]: 0 : pSubMenu->SetItemCommand( nNewItemId, aCommandURL );
[ # # ]
161 : : }
162 : :
163 : : // handle bitmap
164 [ # # ]: 0 : if ( xBitmap.is() )
165 : : {
166 : 0 : sal_Bool bImageSet = sal_False;
167 : :
168 [ # # ]: 0 : Reference< XUnoTunnel > xUnoTunnel( xBitmap, UNO_QUERY );
169 [ # # ]: 0 : if ( xUnoTunnel.is() )
170 : : {
171 : : // Try to get implementation pointer through XUnoTunnel
172 [ # # ][ # # ]: 0 : sal_Int64 nPointer = xUnoTunnel->getSomething( ImageWrapper::GetUnoTunnelId() );
[ # # ][ # # ]
173 [ # # ]: 0 : if ( nPointer )
174 : : {
175 : : // This is our own optimized implementation of menu images!
176 : 0 : ImageWrapper* pImageWrapper = reinterpret_cast< ImageWrapper * >( nPointer );
177 [ # # ]: 0 : Image aMenuImage = pImageWrapper->GetImage();
178 : :
179 [ # # ]: 0 : if ( !!aMenuImage )
180 [ # # ]: 0 : pSubMenu->SetItemImage( nNewItemId, aMenuImage );
181 : :
182 [ # # ]: 0 : bImageSet = sal_True;
183 : : }
184 : : }
185 : :
186 [ # # ]: 0 : if ( !bImageSet )
187 : : {
188 : : // This is an unknown implementation of a XBitmap interface. We have to
189 : : // use a more time consuming way to build an Image!
190 [ # # ]: 0 : Image aImage;
191 [ # # ]: 0 : Bitmap aBitmap;
192 : :
193 [ # # ]: 0 : Sequence< sal_Int8 > aDIBSeq;
194 : : {
195 [ # # ][ # # ]: 0 : aDIBSeq = xBitmap->getDIB();
[ # # ][ # # ]
196 [ # # ]: 0 : SvMemoryStream aMem( (void *)aDIBSeq.getConstArray(), aDIBSeq.getLength(), STREAM_READ );
197 [ # # ][ # # ]: 0 : aMem >> aBitmap;
198 : : }
199 : :
200 [ # # ][ # # ]: 0 : aDIBSeq = xBitmap->getMaskDIB();
[ # # ][ # # ]
201 [ # # ]: 0 : if ( aDIBSeq.getLength() > 0 )
202 : : {
203 [ # # ]: 0 : Bitmap aMaskBitmap;
204 [ # # ]: 0 : SvMemoryStream aMem( (void *)aDIBSeq.getConstArray(), aDIBSeq.getLength(), STREAM_READ );
205 [ # # ]: 0 : aMem >> aMaskBitmap;
206 [ # # ][ # # ]: 0 : aImage = Image( aBitmap, aMaskBitmap );
[ # # ][ # # ]
[ # # ]
207 : : }
208 : : else
209 [ # # ][ # # ]: 0 : aImage = Image( aBitmap );
[ # # ]
210 : :
211 [ # # ]: 0 : if ( !!aImage )
212 [ # # ][ # # ]: 0 : pSubMenu->SetItemImage( nNewItemId, aImage );
[ # # ][ # # ]
213 : 0 : }
214 : : }
215 : : else
216 : : {
217 : : // Support add-on images for context menu interceptors
218 [ # # ]: 0 : Image aImage = aAddonOptions.GetImageFromURL( aCommandURL, sal_False, sal_True );
219 [ # # ]: 0 : if ( !!aImage )
220 [ # # ][ # # ]: 0 : pSubMenu->SetItemImage( nNewItemId, aImage );
221 : : }
222 : :
223 [ # # ]: 0 : if ( xSubContainer.is() )
224 : : {
225 [ # # ][ # # ]: 0 : PopupMenu* pNewSubMenu = new PopupMenu;
226 : :
227 : : // Sub menu (recursive call CreateSubMenu )
228 [ # # ]: 0 : InsertSubMenuItems( pNewSubMenu, nItemId, xSubContainer );
229 [ # # ]: 0 : pSubMenu->SetPopupMenu( nNewItemId, pNewSubMenu );
230 : : }
231 [ # # ]: 0 : }
232 : : }
233 [ # # # # ]: 0 : }
234 : : }
235 [ # # ]: 0 : catch (const IndexOutOfBoundsException&)
236 : : {
237 : : return;
238 : : }
239 [ # # ]: 0 : catch (const WrappedTargetException&)
240 : : {
241 : : return;
242 : : }
243 [ # # ]: 0 : catch (const RuntimeException&)
244 : : {
245 : : return;
246 : : }
247 [ # # ][ # # ]: 0 : }
[ # # ]
248 [ # # ]: 0 : }
249 : : }
250 : :
251 : :
252 : : // ----------------------------------------------------------------------------
253 : : // implementation helper ( ActionTrigger => menu )
254 : : // ----------------------------------------------------------------------------
255 : :
256 : 0 : Reference< XPropertySet > CreateActionTrigger( sal_uInt16 nItemId, const Menu* pMenu, const Reference< XIndexContainer >& rActionTriggerContainer ) throw ( RuntimeException )
257 : : {
258 : 0 : Reference< XPropertySet > xPropSet;
259 : :
260 [ # # ]: 0 : Reference< XMultiServiceFactory > xMultiServiceFactory( rActionTriggerContainer, UNO_QUERY );
261 [ # # ]: 0 : if ( xMultiServiceFactory.is() )
262 : : {
263 [ # # ]: 0 : xPropSet = Reference< XPropertySet >( xMultiServiceFactory->createInstance(
264 : 0 : OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.ActionTrigger" )) ),
265 [ # # ][ # # ]: 0 : UNO_QUERY );
[ # # ][ # # ]
266 : :
267 : 0 : Any a;
268 : :
269 : : try
270 : : {
271 : : // Retrieve the menu attributes and set them in our PropertySet
272 [ # # ][ # # ]: 0 : OUString aLabel = pMenu->GetItemText( nItemId );
[ # # ]
273 [ # # ]: 0 : a <<= aLabel;
274 [ # # ][ # # ]: 0 : xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )), a );
[ # # ]
275 : :
276 [ # # ][ # # ]: 0 : OUString aCommandURL = pMenu->GetItemCommand( nItemId );
277 : :
278 [ # # ]: 0 : if ( aCommandURL.isEmpty() )
279 : : {
280 [ # # ]: 0 : aCommandURL = OUString( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
281 : 0 : aCommandURL += OUString::valueOf( (sal_Int32)nItemId );
282 : : }
283 : :
284 [ # # ]: 0 : a <<= aCommandURL;
285 [ # # ][ # # ]: 0 : xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )), a );
[ # # ]
286 : :
287 [ # # ]: 0 : Image aImage = pMenu->GetItemImage( nItemId );
288 [ # # ]: 0 : if ( !!aImage )
289 : : {
290 : : // We use our own optimized XBitmap implementation
291 [ # # ][ # # ]: 0 : Reference< XBitmap > xBitmap( static_cast< cppu::OWeakObject* >( new ImageWrapper( aImage )), UNO_QUERY );
292 [ # # ]: 0 : a <<= xBitmap;
293 [ # # ][ # # ]: 0 : xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Image" )), a );
[ # # ]
294 [ # # ][ # # ]: 0 : }
295 : : }
296 [ # # ]: 0 : catch (const Exception&)
297 : : {
298 : 0 : }
299 : : }
300 : :
301 : 0 : return xPropSet;
302 : : }
303 : :
304 : 0 : Reference< XPropertySet > CreateActionTriggerSeparator( const Reference< XIndexContainer >& rActionTriggerContainer ) throw ( RuntimeException )
305 : : {
306 [ # # ]: 0 : Reference< XMultiServiceFactory > xMultiServiceFactory( rActionTriggerContainer, UNO_QUERY );
307 [ # # ]: 0 : if ( xMultiServiceFactory.is() )
308 : : {
309 [ # # ]: 0 : return Reference< XPropertySet >( xMultiServiceFactory->createInstance(
310 : 0 : OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.ActionTriggerSeparator" )) ),
311 [ # # ][ # # ]: 0 : UNO_QUERY );
[ # # ]
312 : : }
313 : :
314 : 0 : return Reference< XPropertySet >();
315 : : }
316 : :
317 : 0 : Reference< XIndexContainer > CreateActionTriggerContainer( const Reference< XIndexContainer >& rActionTriggerContainer ) throw ( RuntimeException )
318 : : {
319 [ # # ]: 0 : Reference< XMultiServiceFactory > xMultiServiceFactory( rActionTriggerContainer, UNO_QUERY );
320 [ # # ]: 0 : if ( xMultiServiceFactory.is() )
321 : : {
322 [ # # ]: 0 : return Reference< XIndexContainer >( xMultiServiceFactory->createInstance(
323 : 0 : OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.ActionTriggerContainer" )) ),
324 [ # # ][ # # ]: 0 : UNO_QUERY );
[ # # ]
325 : : }
326 : :
327 : 0 : return Reference< XIndexContainer >();
328 : : }
329 : :
330 : 0 : void FillActionTriggerContainerWithMenu( const Menu* pMenu, Reference< XIndexContainer >& rActionTriggerContainer )
331 : : {
332 [ # # ]: 0 : SolarMutexGuard aGuard;
333 : :
334 [ # # ][ # # ]: 0 : for ( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); nPos++ )
335 : : {
336 [ # # ]: 0 : sal_uInt16 nItemId = pMenu->GetItemId( nPos );
337 [ # # ]: 0 : MenuItemType nType = pMenu->GetItemType( nPos );
338 : :
339 : : try
340 : : {
341 : 0 : Any a;
342 : 0 : Reference< XPropertySet > xPropSet;
343 : :
344 [ # # ]: 0 : if ( nType == MENUITEM_SEPARATOR )
345 : : {
346 [ # # ][ # # ]: 0 : xPropSet = CreateActionTriggerSeparator( rActionTriggerContainer );
347 : :
348 [ # # ]: 0 : a <<= xPropSet;
349 [ # # ][ # # ]: 0 : rActionTriggerContainer->insertByIndex( nPos, a );
350 : : }
351 : : else
352 : : {
353 [ # # ][ # # ]: 0 : xPropSet = CreateActionTrigger( nItemId, pMenu, rActionTriggerContainer );
354 : :
355 [ # # ]: 0 : a <<= xPropSet;
356 [ # # ][ # # ]: 0 : rActionTriggerContainer->insertByIndex( nPos, a );
357 : :
358 [ # # ]: 0 : PopupMenu* pPopupMenu = pMenu->GetPopupMenu( nItemId );
359 [ # # ]: 0 : if ( pPopupMenu )
360 : : {
361 : : // recursive call to build next sub menu
362 [ # # ]: 0 : Reference< XIndexContainer > xSubContainer = CreateActionTriggerContainer( rActionTriggerContainer );
363 : :
364 [ # # ]: 0 : a <<= xSubContainer;
365 [ # # ][ # # ]: 0 : xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "SubContainer" )), a );
[ # # ]
366 [ # # ]: 0 : FillActionTriggerContainerWithMenu( pPopupMenu, xSubContainer );
367 : : }
368 [ # # ]: 0 : }
369 : : }
370 [ # # ]: 0 : catch (const Exception&)
371 : : {
372 : : }
373 [ # # ]: 0 : }
374 : 0 : }
375 : :
376 : 0 : void ActionTriggerHelper::CreateMenuFromActionTriggerContainer(
377 : : Menu* pNewMenu,
378 : : const Reference< XIndexContainer >& rActionTriggerContainer )
379 : : {
380 : 0 : sal_uInt16 nItemId = START_ITEMID;
381 : :
382 [ # # ]: 0 : if ( rActionTriggerContainer.is() )
383 [ # # ]: 0 : InsertSubMenuItems( pNewMenu, nItemId, rActionTriggerContainer );
384 : 0 : }
385 : :
386 : 0 : void ActionTriggerHelper::FillActionTriggerContainerFromMenu(
387 : : Reference< XIndexContainer >& xActionTriggerContainer,
388 : : const Menu* pMenu )
389 : : {
390 : 0 : FillActionTriggerContainerWithMenu( pMenu, xActionTriggerContainer );
391 : 0 : }
392 : :
393 : 0 : Reference< XIndexContainer > ActionTriggerHelper::CreateActionTriggerContainerFromMenu(
394 : : const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,
395 : : const Menu* pMenu,
396 : : const ::rtl::OUString* pMenuIdentifier )
397 : : {
398 [ # # ]: 0 : return new RootActionTriggerContainer( pMenu, pMenuIdentifier, xServiceFactory );
399 : : }
400 : :
401 : : }
402 : :
403 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|