1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: actiontriggerhelper.cxx,v $
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;
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
;
61 // ----------------------------------------------------------------------------
62 // implementation helper ( menu => ActionTrigger )
63 // ----------------------------------------------------------------------------
65 sal_Bool
IsSeparator( Reference
< XPropertySet
> xPropertySet
)
67 Reference
< XServiceInfo
> xServiceInfo( xPropertySet
, UNO_QUERY
);
70 return xServiceInfo
->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_ACTIONTRIGGERSEPARATOR
)) );
79 void GetMenuItemAttributes( Reference
< XPropertySet
> xActionTriggerPropertySet
,
81 OUString
& aCommandURL
,
83 Reference
< XBitmap
>& xBitmap
,
84 Reference
< XIndexContainer
>& xSubContainer
)
90 // mandatory properties
91 a
= xActionTriggerPropertySet
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" )) );
93 a
= xActionTriggerPropertySet
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )) );
95 a
= xActionTriggerPropertySet
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Image" )) );
97 a
= xActionTriggerPropertySet
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "SubContainer" )) );
104 // optional properties
107 a
= xActionTriggerPropertySet
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "HelpURL" )) );
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
))
136 OGuard
aGuard( Application::GetSolarMutex() );
137 pSubMenu
->InsertSeparator();
143 OUString aCommandURL
;
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
);
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
);
168 pSubMenu
->InsertItem( nNewItemId
, aLabel
);
169 pSubMenu
->SetItemCommand( nNewItemId
, aCommandURL
);
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() );
184 // This is our own optimized implementation of menu images!
185 ImageWrapper
* pImageWrapper
= reinterpret_cast< ImageWrapper
* >( nPointer
);
186 Image aMenuImage
= pImageWrapper
->GetImage();
189 pSubMenu
->SetItemImage( nNewItemId
, aMenuImage
);
191 bImageSet
= sal_True
;
197 // This is an unknown implementation of a XBitmap interface. We have to
198 // use a more time consuming way to build an Image!
202 Sequence
< sal_Int8
> aDIBSeq
;
204 aDIBSeq
= xBitmap
->getDIB();
205 SvMemoryStream
aMem( (void *)aDIBSeq
.getConstArray(), aDIBSeq
.getLength(), STREAM_READ
);
209 aDIBSeq
= xBitmap
->getMaskDIB();
210 if ( aDIBSeq
.getLength() > 0 )
213 SvMemoryStream
aMem( (void *)aDIBSeq
.getConstArray(), aDIBSeq
.getLength(), STREAM_READ
);
215 aImage
= Image( aBitmap
, aMaskBitmap
);
218 aImage
= Image( aBitmap
);
221 pSubMenu
->SetItemImage( nNewItemId
, aImage
);
226 // Support add-on images for context menu interceptors
227 Image aImage
= aAddonOptions
.GetImageFromURL( aCommandURL
, sal_False
, bHiContrast
, sal_True
);
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
)
248 catch ( WrappedTargetException
)
252 catch ( RuntimeException
)
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" )) ),
280 // Retrieve the menu attributes and set them in our PropertySet
281 OUString aLabel
= pMenu
->GetItemText( nItemId
);
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
);
294 xPropSet
->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )), a
);
296 Image aImage
= pMenu
->GetItemImage( nItemId
);
299 // We use our own optimized XBitmap implementation
300 Reference
< XBitmap
> xBitmap( static_cast< cppu::OWeakObject
* >( new ImageWrapper( aImage
)), UNO_QUERY
);
302 xPropSet
->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Image" )), a
);
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" )) ),
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" )) ),
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
);
351 Reference
< XPropertySet
> xPropSet
;
353 if ( nType
== MENUITEM_SEPARATOR
)
355 xPropSet
= CreateActionTriggerSeparator( rActionTriggerContainer
);
358 rActionTriggerContainer
->insertByIndex( nPos
, a
);
362 xPropSet
= CreateActionTrigger( nItemId
, pMenu
, rActionTriggerContainer
);
365 rActionTriggerContainer
->insertByIndex( nPos
, a
);
367 PopupMenu
* pPopupMenu
= pMenu
->GetPopupMenu( nItemId
);
370 // recursive call to build next sub menu
371 Reference
< XIndexContainer
> xSubContainer
= CreateActionTriggerContainer( rActionTriggerContainer
);
374 xPropSet
->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "SubContainer" )), a
);
375 FillActionTriggerContainerWithMenu( pPopupMenu
, xSubContainer
);
385 void ActionTriggerHelper::CreateMenuFromActionTriggerContainer(
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
,
399 FillActionTriggerContainerWithMenu( pMenu
, xActionTriggerContainer
);
402 Reference
< XIndexContainer
> ActionTriggerHelper::CreateActionTriggerContainerFromMenu(
404 const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XMultiServiceFactory
>& xServiceFactory
,
406 const ::rtl::OUString
* pMenuIdentifier
)
408 return new RootActionTriggerContainer( pMenu
, pMenuIdentifier
, xServiceFactory
);