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;
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
;
58 // ----------------------------------------------------------------------------
59 // implementation helper ( menu => ActionTrigger )
60 // ----------------------------------------------------------------------------
62 sal_Bool
IsSeparator( Reference
< XPropertySet
> xPropertySet
)
64 Reference
< XServiceInfo
> xServiceInfo( xPropertySet
, UNO_QUERY
);
67 return xServiceInfo
->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERSEPARATOR
)) );
76 void GetMenuItemAttributes( Reference
< XPropertySet
> xActionTriggerPropertySet
,
78 OUString
& aCommandURL
,
80 Reference
< XBitmap
>& xBitmap
,
81 Reference
< XIndexContainer
>& xSubContainer
)
87 // mandatory properties
88 a
= xActionTriggerPropertySet
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )) );
90 a
= xActionTriggerPropertySet
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )) );
92 a
= xActionTriggerPropertySet
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Image" )) );
94 a
= xActionTriggerPropertySet
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "SubContainer" )) );
101 // optional properties
104 a
= xActionTriggerPropertySet
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "HelpURL" )) );
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
))
133 OGuard
aGuard( Application::GetSolarMutex() );
134 pSubMenu
->InsertSeparator();
140 OUString aCommandURL
;
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
);
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
);
165 pSubMenu
->InsertItem( nNewItemId
, aLabel
);
166 pSubMenu
->SetItemCommand( nNewItemId
, aCommandURL
);
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() );
181 // This is our own optimized implementation of menu images!
182 ImageWrapper
* pImageWrapper
= reinterpret_cast< ImageWrapper
* >( nPointer
);
183 Image aMenuImage
= pImageWrapper
->GetImage();
186 pSubMenu
->SetItemImage( nNewItemId
, aMenuImage
);
188 bImageSet
= sal_True
;
194 // This is an unknown implementation of a XBitmap interface. We have to
195 // use a more time consuming way to build an Image!
199 Sequence
< sal_Int8
> aDIBSeq
;
201 aDIBSeq
= xBitmap
->getDIB();
202 SvMemoryStream
aMem( (void *)aDIBSeq
.getConstArray(), aDIBSeq
.getLength(), STREAM_READ
);
206 aDIBSeq
= xBitmap
->getMaskDIB();
207 if ( aDIBSeq
.getLength() > 0 )
210 SvMemoryStream
aMem( (void *)aDIBSeq
.getConstArray(), aDIBSeq
.getLength(), STREAM_READ
);
212 aImage
= Image( aBitmap
, aMaskBitmap
);
215 aImage
= Image( aBitmap
);
218 pSubMenu
->SetItemImage( nNewItemId
, aImage
);
223 // Support add-on images for context menu interceptors
224 Image aImage
= aAddonOptions
.GetImageFromURL( aCommandURL
, sal_False
, bHiContrast
, sal_True
);
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
)
245 catch ( WrappedTargetException
)
249 catch ( RuntimeException
)
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" )) ),
277 // Retrieve the menu attributes and set them in our PropertySet
278 OUString aLabel
= pMenu
->GetItemText( nItemId
);
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
);
291 xPropSet
->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )), a
);
293 Image aImage
= pMenu
->GetItemImage( nItemId
);
296 // We use our own optimized XBitmap implementation
297 Reference
< XBitmap
> xBitmap( static_cast< cppu::OWeakObject
* >( new ImageWrapper( aImage
)), UNO_QUERY
);
299 xPropSet
->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Image" )), a
);
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" )) ),
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" )) ),
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
);
348 Reference
< XPropertySet
> xPropSet
;
350 if ( nType
== MENUITEM_SEPARATOR
)
352 xPropSet
= CreateActionTriggerSeparator( rActionTriggerContainer
);
355 rActionTriggerContainer
->insertByIndex( nPos
, a
);
359 xPropSet
= CreateActionTrigger( nItemId
, pMenu
, rActionTriggerContainer
);
362 rActionTriggerContainer
->insertByIndex( nPos
, a
);
364 PopupMenu
* pPopupMenu
= pMenu
->GetPopupMenu( nItemId
);
367 // recursive call to build next sub menu
368 Reference
< XIndexContainer
> xSubContainer
= CreateActionTriggerContainer( rActionTriggerContainer
);
371 xPropSet
->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "SubContainer" )), a
);
372 FillActionTriggerContainerWithMenu( pPopupMenu
, xSubContainer
);
382 void ActionTriggerHelper::CreateMenuFromActionTriggerContainer(
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
,
396 FillActionTriggerContainerWithMenu( pMenu
, xActionTriggerContainer
);
399 Reference
< XIndexContainer
> ActionTriggerHelper::CreateActionTriggerContainerFromMenu(
401 const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
>& xServiceFactory
,
403 const ::rtl::OUString
* pMenuIdentifier
)
405 return new RootActionTriggerContainer( pMenu
, pMenuIdentifier
, xServiceFactory
);