merged tag ooo/OOO330_m14
[LibreOffice.git] / framework / source / helper / actiontriggerhelper.cxx
blobb1c4e50dfe007277ab55db43a9ff94cfbfea2aa3
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 #include <helper/actiontriggerhelper.hxx>
31 #include <classes/actiontriggerseparatorpropertyset.hxx>
32 #include <classes/rootactiontriggercontainer.hxx>
33 #include <classes/imagewrapper.hxx>
34 #include <classes/addonsoptions.hxx>
35 #include <com/sun/star/lang/XServiceInfo.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/awt/XBitmap.hpp>
38 #include <vcl/svapp.hxx>
39 #include <vos/mutex.hxx>
40 #include <tools/stream.hxx>
41 #include <cppuhelper/weak.hxx>
42 #include <comphelper/processfactory.hxx>
45 const USHORT START_ITEMID = 1000;
47 using namespace rtl;
48 using namespace vos;
49 using namespace com::sun::star::awt;
50 using namespace com::sun::star::uno;
51 using namespace com::sun::star::lang;
52 using namespace com::sun::star::beans;
53 using namespace com::sun::star::container;
55 namespace framework
58 // ----------------------------------------------------------------------------
59 // implementation helper ( menu => ActionTrigger )
60 // ----------------------------------------------------------------------------
62 sal_Bool IsSeparator( Reference< XPropertySet > xPropertySet )
64 Reference< XServiceInfo > xServiceInfo( xPropertySet, UNO_QUERY );
65 try
67 return xServiceInfo->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERSEPARATOR )) );
69 catch ( Exception& )
73 return sal_False;
76 void GetMenuItemAttributes( Reference< XPropertySet > xActionTriggerPropertySet,
77 OUString& aMenuLabel,
78 OUString& aCommandURL,
79 OUString& aHelpURL,
80 Reference< XBitmap >& xBitmap,
81 Reference< XIndexContainer >& xSubContainer )
83 Any a;
85 try
87 // mandatory properties
88 a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )) );
89 a >>= aMenuLabel;
90 a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )) );
91 a >>= aCommandURL;
92 a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Image" )) );
93 a >>= xBitmap;
94 a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "SubContainer" )) );
95 a >>= xSubContainer;
97 catch ( Exception& )
101 // optional properties
104 a = xActionTriggerPropertySet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "HelpURL" )) );
105 a >>= aHelpURL;
107 catch ( Exception& )
112 void InsertSubMenuItems( Menu* pSubMenu, USHORT& nItemId, Reference< XIndexContainer > xActionTriggerContainer )
114 Reference< XIndexAccess > xIndexAccess( xActionTriggerContainer, UNO_QUERY );
115 if ( xIndexAccess.is() )
117 AddonsOptions aAddonOptions;
118 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
119 sal_Bool bHiContrast = rSettings.GetHighContrastMode();
121 OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
123 for ( sal_Int32 i = 0; i < xIndexAccess->getCount(); i++ )
127 Reference< XPropertySet > xPropSet;
128 if (( xIndexAccess->getByIndex( i ) >>= xPropSet ) && ( xPropSet.is() ))
130 if ( IsSeparator( xPropSet ))
132 // Separator
133 OGuard aGuard( Application::GetSolarMutex() );
134 pSubMenu->InsertSeparator();
136 else
138 // Menu item
139 OUString aLabel;
140 OUString aCommandURL;
141 OUString aHelpURL;
142 Reference< XBitmap > xBitmap;
143 Reference< XIndexContainer > xSubContainer;
144 sal_Bool bSpecialItemId = sal_False;
146 USHORT nNewItemId = nItemId++;
147 GetMenuItemAttributes( xPropSet, aLabel, aCommandURL, aHelpURL, xBitmap, xSubContainer );
149 OGuard aGuard( Application::GetSolarMutex() );
151 // insert new menu item
152 sal_Int32 nIndex = aCommandURL.indexOf( aSlotURL );
153 if ( nIndex >= 0 )
155 // Special code for our menu implementation: some menu items don't have a
156 // command url but uses the item id as a unqiue identifier. These entries
157 // got a special url during conversion from menu=>actiontriggercontainer.
158 // Now we have to extract this special url and set the correct item id!!!
159 bSpecialItemId = sal_True;
160 nNewItemId = (USHORT)aCommandURL.copy( nIndex+aSlotURL.getLength() ).toInt32();
161 pSubMenu->InsertItem( nNewItemId, aLabel );
163 else
165 pSubMenu->InsertItem( nNewItemId, aLabel );
166 pSubMenu->SetItemCommand( nNewItemId, aCommandURL );
169 // handle bitmap
170 if ( xBitmap.is() )
172 sal_Bool bImageSet = sal_False;
174 Reference< XUnoTunnel > xUnoTunnel( xBitmap, UNO_QUERY );
175 if ( xUnoTunnel.is() )
177 // Try to get implementation pointer through XUnoTunnel
178 sal_Int64 nPointer = xUnoTunnel->getSomething( ImageWrapper::GetUnoTunnelId() );
179 if ( nPointer )
181 // This is our own optimized implementation of menu images!
182 ImageWrapper* pImageWrapper = reinterpret_cast< ImageWrapper * >( nPointer );
183 Image aMenuImage = pImageWrapper->GetImage();
185 if ( !!aMenuImage )
186 pSubMenu->SetItemImage( nNewItemId, aMenuImage );
188 bImageSet = sal_True;
192 if ( !bImageSet )
194 // This is an unknown implementation of a XBitmap interface. We have to
195 // use a more time consuming way to build an Image!
196 Image aImage;
197 Bitmap aBitmap;
199 Sequence< sal_Int8 > aDIBSeq;
201 aDIBSeq = xBitmap->getDIB();
202 SvMemoryStream aMem( (void *)aDIBSeq.getConstArray(), aDIBSeq.getLength(), STREAM_READ );
203 aMem >> aBitmap;
206 aDIBSeq = xBitmap->getMaskDIB();
207 if ( aDIBSeq.getLength() > 0 )
209 Bitmap aMaskBitmap;
210 SvMemoryStream aMem( (void *)aDIBSeq.getConstArray(), aDIBSeq.getLength(), STREAM_READ );
211 aMem >> aMaskBitmap;
212 aImage = Image( aBitmap, aMaskBitmap );
214 else
215 aImage = Image( aBitmap );
217 if ( !!aImage )
218 pSubMenu->SetItemImage( nNewItemId, aImage );
221 else
223 // Support add-on images for context menu interceptors
224 Image aImage = aAddonOptions.GetImageFromURL( aCommandURL, sal_False, bHiContrast, sal_True );
225 if ( !!aImage )
226 pSubMenu->SetItemImage( nNewItemId, aImage );
229 if ( xSubContainer.is() )
231 PopupMenu* pNewSubMenu = new PopupMenu;
233 // Sub menu (recursive call CreateSubMenu )
234 InsertSubMenuItems( pNewSubMenu, nItemId, xSubContainer );
235 pSubMenu->SetPopupMenu( nNewItemId, pNewSubMenu );
241 catch ( IndexOutOfBoundsException )
243 return;
245 catch ( WrappedTargetException )
247 return;
249 catch ( RuntimeException )
251 return;
258 // ----------------------------------------------------------------------------
259 // implementation helper ( ActionTrigger => menu )
260 // ----------------------------------------------------------------------------
262 Reference< XPropertySet > CreateActionTrigger( USHORT nItemId, const Menu* pMenu, const Reference< XIndexContainer >& rActionTriggerContainer ) throw ( RuntimeException )
264 Reference< XPropertySet > xPropSet;
266 Reference< XMultiServiceFactory > xMultiServiceFactory( rActionTriggerContainer, UNO_QUERY );
267 if ( xMultiServiceFactory.is() )
269 xPropSet = Reference< XPropertySet >( xMultiServiceFactory->createInstance(
270 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.ActionTrigger" )) ),
271 UNO_QUERY );
273 Any a;
277 // Retrieve the menu attributes and set them in our PropertySet
278 OUString aLabel = pMenu->GetItemText( nItemId );
279 a <<= aLabel;
280 xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )), a );
282 OUString aCommandURL = pMenu->GetItemCommand( nItemId );
284 if ( aCommandURL.getLength() == 0 )
286 aCommandURL = OUString( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
287 aCommandURL += OUString::valueOf( (sal_Int32)nItemId );
290 a <<= aCommandURL;
291 xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )), a );
293 Image aImage = pMenu->GetItemImage( nItemId );
294 if ( !!aImage )
296 // We use our own optimized XBitmap implementation
297 Reference< XBitmap > xBitmap( static_cast< cppu::OWeakObject* >( new ImageWrapper( aImage )), UNO_QUERY );
298 a <<= xBitmap;
299 xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Image" )), a );
302 catch ( Exception& )
307 return xPropSet;
310 Reference< XPropertySet > CreateActionTriggerSeparator( const Reference< XIndexContainer >& rActionTriggerContainer ) throw ( RuntimeException )
312 Reference< XMultiServiceFactory > xMultiServiceFactory( rActionTriggerContainer, UNO_QUERY );
313 if ( xMultiServiceFactory.is() )
315 return Reference< XPropertySet >( xMultiServiceFactory->createInstance(
316 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.ActionTriggerSeparator" )) ),
317 UNO_QUERY );
320 return Reference< XPropertySet >();
323 Reference< XIndexContainer > CreateActionTriggerContainer( const Reference< XIndexContainer >& rActionTriggerContainer ) throw ( RuntimeException )
325 Reference< XMultiServiceFactory > xMultiServiceFactory( rActionTriggerContainer, UNO_QUERY );
326 if ( xMultiServiceFactory.is() )
328 return Reference< XIndexContainer >( xMultiServiceFactory->createInstance(
329 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.ActionTriggerContainer" )) ),
330 UNO_QUERY );
333 return Reference< XIndexContainer >();
336 void FillActionTriggerContainerWithMenu( const Menu* pMenu, Reference< XIndexContainer >& rActionTriggerContainer )
338 OGuard aGuard( Application::GetSolarMutex() );
340 for ( USHORT nPos = 0; nPos < pMenu->GetItemCount(); nPos++ )
342 USHORT nItemId = pMenu->GetItemId( nPos );
343 MenuItemType nType = pMenu->GetItemType( nPos );
347 Any a;
348 Reference< XPropertySet > xPropSet;
350 if ( nType == MENUITEM_SEPARATOR )
352 xPropSet = CreateActionTriggerSeparator( rActionTriggerContainer );
354 a <<= xPropSet;
355 rActionTriggerContainer->insertByIndex( nPos, a );
357 else
359 xPropSet = CreateActionTrigger( nItemId, pMenu, rActionTriggerContainer );
361 a <<= xPropSet;
362 rActionTriggerContainer->insertByIndex( nPos, a );
364 PopupMenu* pPopupMenu = pMenu->GetPopupMenu( nItemId );
365 if ( pPopupMenu )
367 // recursive call to build next sub menu
368 Reference< XIndexContainer > xSubContainer = CreateActionTriggerContainer( rActionTriggerContainer );
370 a <<= xSubContainer;
371 xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "SubContainer" )), a );
372 FillActionTriggerContainerWithMenu( pPopupMenu, xSubContainer );
376 catch ( Exception& )
382 void ActionTriggerHelper::CreateMenuFromActionTriggerContainer(
383 Menu* pNewMenu,
384 const Reference< XIndexContainer >& rActionTriggerContainer )
386 USHORT nItemId = START_ITEMID;
388 if ( rActionTriggerContainer.is() )
389 InsertSubMenuItems( pNewMenu, nItemId, rActionTriggerContainer );
392 void ActionTriggerHelper::FillActionTriggerContainerFromMenu(
393 Reference< XIndexContainer >& xActionTriggerContainer,
394 const Menu* pMenu )
396 FillActionTriggerContainerWithMenu( pMenu, xActionTriggerContainer );
399 Reference< XIndexContainer > ActionTriggerHelper::CreateActionTriggerContainerFromMenu(
400 // #110897#
401 const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceFactory,
402 const Menu* pMenu,
403 const ::rtl::OUString* pMenuIdentifier )
405 return new RootActionTriggerContainer( pMenu, pMenuIdentifier, xServiceFactory );