merge the formfield patch from ooo-build
[ooovba.git] / framework / source / helper / actiontriggerhelper.cxx
blob3224803892d40da75d937c92f422b27d8d51e2f8
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: actiontriggerhelper.cxx,v $
10 * $Revision: 1.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
33 #include <helper/actiontriggerhelper.hxx>
34 #include <classes/actiontriggerseparatorpropertyset.hxx>
35 #include <classes/rootactiontriggercontainer.hxx>
36 #include <classes/imagewrapper.hxx>
37 #include <classes/addonsoptions.hxx>
38 #include <com/sun/star/lang/XServiceInfo.hpp>
39 #include <com/sun/star/beans/XPropertySet.hpp>
40 #include <com/sun/star/awt/XBitmap.hpp>
41 #include <vcl/svapp.hxx>
42 #include <vos/mutex.hxx>
43 #include <tools/stream.hxx>
44 #include <cppuhelper/weak.hxx>
45 #include <comphelper/processfactory.hxx>
48 const USHORT START_ITEMID = 1000;
50 using namespace rtl;
51 using namespace vos;
52 using namespace com::sun::star::awt;
53 using namespace com::sun::star::uno;
54 using namespace com::sun::star::lang;
55 using namespace com::sun::star::beans;
56 using namespace com::sun::star::container;
58 namespace framework
61 // ----------------------------------------------------------------------------
62 // implementation helper ( menu => ActionTrigger )
63 // ----------------------------------------------------------------------------
65 sal_Bool IsSeparator( Reference< XPropertySet > xPropertySet )
67 Reference< XServiceInfo > xServiceInfo( xPropertySet, UNO_QUERY );
68 try
70 return xServiceInfo->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERSEPARATOR )) );
72 catch ( Exception& )
76 return sal_False;
79 void GetMenuItemAttributes( Reference< XPropertySet > xActionTriggerPropertySet,
80 OUString& aMenuLabel,
81 OUString& aCommandURL,
82 OUString& aHelpURL,
83 Reference< XBitmap >& xBitmap,
84 Reference< XIndexContainer >& xSubContainer )
86 Any a;
88 try
90 // mandatory properties
91 a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )) );
92 a >>= aMenuLabel;
93 a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )) );
94 a >>= aCommandURL;
95 a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Image" )) );
96 a >>= xBitmap;
97 a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "SubContainer" )) );
98 a >>= xSubContainer;
100 catch ( Exception& )
104 // optional properties
107 a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "HelpURL" )) );
108 a >>= aHelpURL;
110 catch ( Exception& )
115 void InsertSubMenuItems( Menu* pSubMenu, USHORT& nItemId, Reference< XIndexContainer > xActionTriggerContainer )
117 Reference< XIndexAccess > xIndexAccess( xActionTriggerContainer, UNO_QUERY );
118 if ( xIndexAccess.is() )
120 AddonsOptions aAddonOptions;
121 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
122 sal_Bool bHiContrast = rSettings.GetHighContrastMode();
124 OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
126 for ( sal_Int32 i = 0; i < xIndexAccess->getCount(); i++ )
130 Reference< XPropertySet > xPropSet;
131 if (( xIndexAccess->getByIndex( i ) >>= xPropSet ) && ( xPropSet.is() ))
133 if ( IsSeparator( xPropSet ))
135 // Separator
136 OGuard aGuard( Application::GetSolarMutex() );
137 pSubMenu->InsertSeparator();
139 else
141 // Menu item
142 OUString aLabel;
143 OUString aCommandURL;
144 OUString aHelpURL;
145 Reference< XBitmap > xBitmap;
146 Reference< XIndexContainer > xSubContainer;
147 sal_Bool bSpecialItemId = sal_False;
149 USHORT nNewItemId = nItemId++;
150 GetMenuItemAttributes( xPropSet, aLabel, aCommandURL, aHelpURL, xBitmap, xSubContainer );
152 OGuard aGuard( Application::GetSolarMutex() );
154 // insert new menu item
155 sal_Int32 nIndex = aCommandURL.indexOf( aSlotURL );
156 if ( nIndex >= 0 )
158 // Special code for our menu implementation: some menu items don't have a
159 // command url but uses the item id as a unqiue identifier. These entries
160 // got a special url during conversion from menu=>actiontriggercontainer.
161 // Now we have to extract this special url and set the correct item id!!!
162 bSpecialItemId = sal_True;
163 nNewItemId = (USHORT)aCommandURL.copy( nIndex+aSlotURL.getLength() ).toInt32();
164 pSubMenu->InsertItem( nNewItemId, aLabel );
166 else
168 pSubMenu->InsertItem( nNewItemId, aLabel );
169 pSubMenu->SetItemCommand( nNewItemId, aCommandURL );
172 // handle bitmap
173 if ( xBitmap.is() )
175 sal_Bool bImageSet = sal_False;
177 Reference< XUnoTunnel > xUnoTunnel( xBitmap, UNO_QUERY );
178 if ( xUnoTunnel.is() )
180 // Try to get implementation pointer through XUnoTunnel
181 sal_Int64 nPointer = xUnoTunnel->getSomething( ImageWrapper::GetUnoTunnelId() );
182 if ( nPointer )
184 // This is our own optimized implementation of menu images!
185 ImageWrapper* pImageWrapper = reinterpret_cast< ImageWrapper * >( nPointer );
186 Image aMenuImage = pImageWrapper->GetImage();
188 if ( !!aMenuImage )
189 pSubMenu->SetItemImage( nNewItemId, aMenuImage );
191 bImageSet = sal_True;
195 if ( !bImageSet )
197 // This is an unknown implementation of a XBitmap interface. We have to
198 // use a more time consuming way to build an Image!
199 Image aImage;
200 Bitmap aBitmap;
202 Sequence< sal_Int8 > aDIBSeq;
204 aDIBSeq = xBitmap->getDIB();
205 SvMemoryStream aMem( (void *)aDIBSeq.getConstArray(), aDIBSeq.getLength(), STREAM_READ );
206 aMem >> aBitmap;
209 aDIBSeq = xBitmap->getMaskDIB();
210 if ( aDIBSeq.getLength() > 0 )
212 Bitmap aMaskBitmap;
213 SvMemoryStream aMem( (void *)aDIBSeq.getConstArray(), aDIBSeq.getLength(), STREAM_READ );
214 aMem >> aMaskBitmap;
215 aImage = Image( aBitmap, aMaskBitmap );
217 else
218 aImage = Image( aBitmap );
220 if ( !!aImage )
221 pSubMenu->SetItemImage( nNewItemId, aImage );
224 else
226 // Support add-on images for context menu interceptors
227 Image aImage = aAddonOptions.GetImageFromURL( aCommandURL, sal_False, bHiContrast, sal_True );
228 if ( !!aImage )
229 pSubMenu->SetItemImage( nNewItemId, aImage );
232 if ( xSubContainer.is() )
234 PopupMenu* pNewSubMenu = new PopupMenu;
236 // Sub menu (recursive call CreateSubMenu )
237 InsertSubMenuItems( pNewSubMenu, nItemId, xSubContainer );
238 pSubMenu->SetPopupMenu( nNewItemId, pNewSubMenu );
244 catch ( IndexOutOfBoundsException )
246 return;
248 catch ( WrappedTargetException )
250 return;
252 catch ( RuntimeException )
254 return;
261 // ----------------------------------------------------------------------------
262 // implementation helper ( ActionTrigger => menu )
263 // ----------------------------------------------------------------------------
265 Reference< XPropertySet > CreateActionTrigger( USHORT nItemId, const Menu* pMenu, const Reference< XIndexContainer >& rActionTriggerContainer ) throw ( RuntimeException )
267 Reference< XPropertySet > xPropSet;
269 Reference< XMultiServiceFactory > xMultiServiceFactory( rActionTriggerContainer, UNO_QUERY );
270 if ( xMultiServiceFactory.is() )
272 xPropSet = Reference< XPropertySet >( xMultiServiceFactory->createInstance(
273 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.ActionTrigger" )) ),
274 UNO_QUERY );
276 Any a;
280 // Retrieve the menu attributes and set them in our PropertySet
281 OUString aLabel = pMenu->GetItemText( nItemId );
282 a <<= aLabel;
283 xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )), a );
285 OUString aCommandURL = pMenu->GetItemCommand( nItemId );
287 if ( aCommandURL.getLength() == 0 )
289 aCommandURL = OUString( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
290 aCommandURL += OUString::valueOf( (sal_Int32)nItemId );
293 a <<= aCommandURL;
294 xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )), a );
296 Image aImage = pMenu->GetItemImage( nItemId );
297 if ( !!aImage )
299 // We use our own optimized XBitmap implementation
300 Reference< XBitmap > xBitmap( static_cast< cppu::OWeakObject* >( new ImageWrapper( aImage )), UNO_QUERY );
301 a <<= xBitmap;
302 xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Image" )), a );
305 catch ( Exception& )
310 return xPropSet;
313 Reference< XPropertySet > CreateActionTriggerSeparator( const Reference< XIndexContainer >& rActionTriggerContainer ) throw ( RuntimeException )
315 Reference< XMultiServiceFactory > xMultiServiceFactory( rActionTriggerContainer, UNO_QUERY );
316 if ( xMultiServiceFactory.is() )
318 return Reference< XPropertySet >( xMultiServiceFactory->createInstance(
319 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.ActionTriggerSeparator" )) ),
320 UNO_QUERY );
323 return Reference< XPropertySet >();
326 Reference< XIndexContainer > CreateActionTriggerContainer( const Reference< XIndexContainer >& rActionTriggerContainer ) throw ( RuntimeException )
328 Reference< XMultiServiceFactory > xMultiServiceFactory( rActionTriggerContainer, UNO_QUERY );
329 if ( xMultiServiceFactory.is() )
331 return Reference< XIndexContainer >( xMultiServiceFactory->createInstance(
332 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.ActionTriggerContainer" )) ),
333 UNO_QUERY );
336 return Reference< XIndexContainer >();
339 void FillActionTriggerContainerWithMenu( const Menu* pMenu, Reference< XIndexContainer >& rActionTriggerContainer )
341 OGuard aGuard( Application::GetSolarMutex() );
343 for ( USHORT nPos = 0; nPos < pMenu->GetItemCount(); nPos++ )
345 USHORT nItemId = pMenu->GetItemId( nPos );
346 MenuItemType nType = pMenu->GetItemType( nPos );
350 Any a;
351 Reference< XPropertySet > xPropSet;
353 if ( nType == MENUITEM_SEPARATOR )
355 xPropSet = CreateActionTriggerSeparator( rActionTriggerContainer );
357 a <<= xPropSet;
358 rActionTriggerContainer->insertByIndex( nPos, a );
360 else
362 xPropSet = CreateActionTrigger( nItemId, pMenu, rActionTriggerContainer );
364 a <<= xPropSet;
365 rActionTriggerContainer->insertByIndex( nPos, a );
367 PopupMenu* pPopupMenu = pMenu->GetPopupMenu( nItemId );
368 if ( pPopupMenu )
370 // recursive call to build next sub menu
371 Reference< XIndexContainer > xSubContainer = CreateActionTriggerContainer( rActionTriggerContainer );
373 a <<= xSubContainer;
374 xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "SubContainer" )), a );
375 FillActionTriggerContainerWithMenu( pPopupMenu, xSubContainer );
379 catch ( Exception& )
385 void ActionTriggerHelper::CreateMenuFromActionTriggerContainer(
386 Menu* pNewMenu,
387 const Reference< XIndexContainer >& rActionTriggerContainer )
389 USHORT nItemId = START_ITEMID;
391 if ( rActionTriggerContainer.is() )
392 InsertSubMenuItems( pNewMenu, nItemId, rActionTriggerContainer );
395 void ActionTriggerHelper::FillActionTriggerContainerFromMenu(
396 Reference< XIndexContainer >& xActionTriggerContainer,
397 const Menu* pMenu )
399 FillActionTriggerContainerWithMenu( pMenu, xActionTriggerContainer );
402 Reference< XIndexContainer > ActionTriggerHelper::CreateActionTriggerContainerFromMenu(
403 // #110897#
404 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,
405 const Menu* pMenu,
406 const ::rtl::OUString* pMenuIdentifier )
408 return new RootActionTriggerContainer( pMenu, pMenuIdentifier, xServiceFactory );