1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <cppuhelper/implbase1.hxx>
21 #include <cppuhelper/supportsservice.hxx>
22 #include <comphelper/processfactory.hxx>
23 #include <framework/menuconfiguration.hxx>
24 #include <rtl/ref.hxx>
25 #include <svtools/imagemgr.hxx>
26 #include <svtools/miscopt.hxx>
27 #include <svtools/toolboxcontroller.hxx>
28 #include <toolkit/awt/vclxmenu.hxx>
29 #include <toolkit/helper/vclunohelper.hxx>
30 #include <tools/urlobj.hxx>
31 #include <unotools/moduleoptions.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/toolbox.hxx>
35 #include <com/sun/star/awt/PopupMenuDirection.hpp>
36 #include <com/sun/star/awt/XPopupMenu.hpp>
37 #include <com/sun/star/frame/thePopupMenuControllerFactory.hpp>
38 #include <com/sun/star/frame/XDispatchProvider.hpp>
39 #include <com/sun/star/frame/XPopupMenuController.hpp>
40 #include <com/sun/star/frame/XUIControllerFactory.hpp>
41 #include <com/sun/star/lang/XServiceInfo.hpp>
42 #include <com/sun/star/ucb/CommandFailedException.hpp>
43 #include <com/sun/star/ucb/ContentCreationException.hpp>
45 #define UNO_COMMAND_RECENT_FILE_LIST ".uno:RecentFileList"
47 using namespace framework
;
51 typedef cppu::ImplInheritanceHelper1
< svt::ToolboxController
,
52 css::lang::XServiceInfo
>
55 class PopupMenuToolbarController
: public ToolBarBase
58 virtual ~PopupMenuToolbarController();
61 virtual void SAL_CALL
dispose() throw ( css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
63 virtual void SAL_CALL
initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
) throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
65 virtual css::uno::Reference
< css::awt::XWindow
> SAL_CALL
createPopupWindow() throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
67 virtual void SAL_CALL
statusChanged( const css::frame::FeatureStateEvent
& rEvent
) throw ( css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
70 PopupMenuToolbarController( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
,
71 const OUString
&rPopupCommand
= OUString() );
72 virtual void functionExecuted( const OUString
&rCommand
);
73 virtual ToolBoxItemBits
getDropDownStyle() const;
74 void createPopupMenuController();
76 css::uno::Reference
< css::uno::XComponentContext
> m_xContext
;
77 bool m_bHasController
;
78 css::uno::Reference
< css::awt::XPopupMenu
> m_xPopupMenu
;
81 OUString m_aPopupCommand
;
82 css::uno::Reference
< css::frame::XUIControllerFactory
> m_xPopupMenuFactory
;
83 css::uno::Reference
< css::frame::XPopupMenuController
> m_xPopupMenuController
;
86 PopupMenuToolbarController::PopupMenuToolbarController(
87 const css::uno::Reference
< css::uno::XComponentContext
>& xContext
,
88 const OUString
&rPopupCommand
)
89 : m_xContext( xContext
)
90 , m_bHasController( false )
91 , m_aPopupCommand( rPopupCommand
)
95 PopupMenuToolbarController::~PopupMenuToolbarController()
99 void SAL_CALL
PopupMenuToolbarController::dispose()
100 throw ( css::uno::RuntimeException
, std::exception
)
102 svt::ToolboxController::dispose();
104 osl::MutexGuard
aGuard( m_aMutex
);
105 if( m_xPopupMenuController
.is() )
107 css::uno::Reference
< css::lang::XComponent
> xComponent(
108 m_xPopupMenuController
, css::uno::UNO_QUERY
);
109 if( xComponent
.is() )
113 xComponent
->dispose();
118 m_xPopupMenuController
.clear();
122 m_xPopupMenuFactory
.clear();
123 m_xPopupMenu
.clear();
126 void SAL_CALL
PopupMenuToolbarController::initialize(
127 const css::uno::Sequence
< css::uno::Any
>& aArguments
)
128 throw ( css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
130 ToolboxController::initialize( aArguments
);
132 osl::MutexGuard
aGuard( m_aMutex
);
133 if ( !m_aPopupCommand
.getLength() )
134 m_aPopupCommand
= m_aCommandURL
;
138 m_xPopupMenuFactory
.set(
139 css::frame::thePopupMenuControllerFactory::get( m_xContext
) );
140 m_bHasController
= m_xPopupMenuFactory
->hasController(
141 m_aPopupCommand
, getModuleName() );
143 catch (const css::uno::Exception
& e
)
145 SAL_INFO( "fwk.uielement", "Caught an exception: " << e
.Message
);
148 SolarMutexGuard aSolarLock
;
149 VclPtr
< ToolBox
> pToolBox
= static_cast< ToolBox
* >( VCLUnoHelper::GetWindow( getParent() ).get() );
152 ToolBoxItemBits
nCurStyle( pToolBox
->GetItemBits( m_nToolBoxId
) );
153 ToolBoxItemBits
nSetStyle( getDropDownStyle() );
154 pToolBox
->SetItemBits( m_nToolBoxId
,
156 nCurStyle
| nSetStyle
:
157 nCurStyle
& ~nSetStyle
);
162 void SAL_CALL
PopupMenuToolbarController::statusChanged( const css::frame::FeatureStateEvent
& rEvent
)
163 throw ( css::uno::RuntimeException
, std::exception
)
165 // TODO move to base class
167 svt::ToolboxController::statusChanged( rEvent
);
168 enable( rEvent
.IsEnabled
);
171 css::uno::Reference
< css::awt::XWindow
> SAL_CALL
172 PopupMenuToolbarController::createPopupWindow()
173 throw ( css::uno::RuntimeException
, std::exception
)
175 css::uno::Reference
< css::awt::XWindow
> xRet
;
177 osl::MutexGuard
aGuard( m_aMutex
);
178 if ( !m_bHasController
)
181 createPopupMenuController();
183 SolarMutexGuard aSolarLock
;
184 VclPtr
< ToolBox
> pToolBox
= static_cast< ToolBox
* >( VCLUnoHelper::GetWindow( getParent() ).get() );
188 pToolBox
->SetItemDown( m_nToolBoxId
, true );
189 WindowAlign
eAlign( pToolBox
->GetAlign() );
190 sal_uInt16 nId
= m_xPopupMenu
->execute(
191 css::uno::Reference
< css::awt::XWindowPeer
>( getParent(), css::uno::UNO_QUERY
),
192 VCLUnoHelper::ConvertToAWTRect( pToolBox
->GetItemRect( m_nToolBoxId
) ),
193 ( eAlign
== WINDOWALIGN_TOP
|| eAlign
== WINDOWALIGN_BOTTOM
) ?
194 css::awt::PopupMenuDirection::EXECUTE_DOWN
:
195 css::awt::PopupMenuDirection::EXECUTE_RIGHT
);
196 pToolBox
->SetItemDown( m_nToolBoxId
, false );
199 functionExecuted( m_xPopupMenu
->getCommand( nId
) );
204 void PopupMenuToolbarController::functionExecuted( const OUString
&/*rCommand*/)
208 ToolBoxItemBits
PopupMenuToolbarController::getDropDownStyle() const
210 return ToolBoxItemBits::DROPDOWN
;
213 void PopupMenuToolbarController::createPopupMenuController()
215 if( !m_bHasController
)
218 if ( !m_xPopupMenuController
.is() )
220 css::uno::Sequence
< css::uno::Any
> aArgs( 2 );
221 css::beans::PropertyValue aProp
;
223 aProp
.Name
= "Frame";
224 aProp
.Value
<<= m_xFrame
;
227 aProp
.Name
= "ModuleIdentifier";
228 aProp
.Value
<<= getModuleName();
233 m_xContext
->getServiceManager()->createInstanceWithContext(
234 "com.sun.star.awt.PopupMenu", m_xContext
),
235 css::uno::UNO_QUERY_THROW
);
236 m_xPopupMenuController
.set(
237 m_xPopupMenuFactory
->createInstanceWithArgumentsAndContext(
238 m_aPopupCommand
, aArgs
, m_xContext
), css::uno::UNO_QUERY_THROW
);
240 m_xPopupMenuController
->setPopupMenu( m_xPopupMenu
);
242 catch ( const css::uno::Exception
&e
)
244 m_xPopupMenu
.clear();
245 SAL_INFO( "fwk.uielement", "Caught an exception: " << e
.Message
);
250 class WizardsToolbarController
: public PopupMenuToolbarController
253 WizardsToolbarController( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
);
256 virtual OUString SAL_CALL
getImplementationName() throw (css::uno::RuntimeException
) SAL_OVERRIDE
;
258 virtual sal_Bool SAL_CALL
supportsService(OUString
const & rServiceName
) throw (css::uno::RuntimeException
) SAL_OVERRIDE
;
260 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() throw (css::uno::RuntimeException
) SAL_OVERRIDE
;
263 ToolBoxItemBits
getDropDownStyle() const SAL_OVERRIDE
;
266 WizardsToolbarController::WizardsToolbarController(
267 const css::uno::Reference
< css::uno::XComponentContext
>& xContext
)
268 : PopupMenuToolbarController( xContext
)
272 OUString
WizardsToolbarController::getImplementationName()
273 throw (css::uno::RuntimeException
)
275 return OUString("org.apache.openoffice.comp.framework.WizardsToolbarController");
278 sal_Bool
WizardsToolbarController::supportsService(OUString
const & rServiceName
)
279 throw (css::uno::RuntimeException
)
281 return cppu::supportsService( this, rServiceName
);
284 css::uno::Sequence
<OUString
> WizardsToolbarController::getSupportedServiceNames()
285 throw (css::uno::RuntimeException
)
287 css::uno::Sequence
< OUString
> aRet(1);
288 OUString
* pArray
= aRet
.getArray();
289 pArray
[0] = "com.sun.star.frame.ToolbarController";
293 ToolBoxItemBits
WizardsToolbarController::getDropDownStyle() const
295 return ToolBoxItemBits::DROPDOWNONLY
;
298 class OpenToolbarController
: public PopupMenuToolbarController
301 OpenToolbarController( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
);
304 virtual OUString SAL_CALL
getImplementationName() throw (css::uno::RuntimeException
) SAL_OVERRIDE
;
306 virtual sal_Bool SAL_CALL
supportsService(OUString
const & rServiceName
) throw (css::uno::RuntimeException
) SAL_OVERRIDE
;
308 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() throw (css::uno::RuntimeException
) SAL_OVERRIDE
;
311 OpenToolbarController::OpenToolbarController(
312 const css::uno::Reference
< css::uno::XComponentContext
>& xContext
)
313 : PopupMenuToolbarController( xContext
, UNO_COMMAND_RECENT_FILE_LIST
)
317 OUString
OpenToolbarController::getImplementationName()
318 throw (css::uno::RuntimeException
)
320 return OUString("org.apache.openoffice.comp.framework.OpenToolbarController");
323 sal_Bool
OpenToolbarController::supportsService(OUString
const & rServiceName
)
324 throw (css::uno::RuntimeException
)
326 return cppu::supportsService( this, rServiceName
);
329 css::uno::Sequence
<OUString
> OpenToolbarController::getSupportedServiceNames()
330 throw (css::uno::RuntimeException
)
332 css::uno::Sequence
< OUString
> aRet(1);
333 OUString
* pArray
= aRet
.getArray();
334 pArray
[0] = "com.sun.star.frame.ToolbarController";
338 class NewToolbarController
: public PopupMenuToolbarController
341 NewToolbarController( const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
);
344 OUString SAL_CALL
getImplementationName()
345 throw (css::uno::RuntimeException
) SAL_OVERRIDE
;
347 virtual sal_Bool SAL_CALL
supportsService(OUString
const & rServiceName
) throw (css::uno::RuntimeException
) SAL_OVERRIDE
;
349 css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames()
350 throw (css::uno::RuntimeException
) SAL_OVERRIDE
;
352 void SAL_CALL
initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
) throw (css::uno::Exception
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
355 void functionExecuted( const OUString
&rCommand
) SAL_OVERRIDE
;
356 void SAL_CALL
statusChanged( const css::frame::FeatureStateEvent
& rEvent
) throw ( css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
357 void SAL_CALL
execute( sal_Int16 KeyModifier
) throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
358 void setItemImage( const OUString
&rCommand
);
363 NewToolbarController::NewToolbarController(
364 const css::uno::Reference
< css::uno::XComponentContext
>& xContext
)
365 : PopupMenuToolbarController( xContext
)
369 OUString
NewToolbarController::getImplementationName()
370 throw (css::uno::RuntimeException
)
372 return OUString("org.apache.openoffice.comp.framework.NewToolbarController");
375 sal_Bool
NewToolbarController::supportsService(OUString
const & rServiceName
)
376 throw (css::uno::RuntimeException
)
378 return cppu::supportsService( this, rServiceName
);
381 css::uno::Sequence
<OUString
> NewToolbarController::getSupportedServiceNames()
382 throw (css::uno::RuntimeException
)
384 css::uno::Sequence
< OUString
> aRet(1);
385 OUString
* pArray
= aRet
.getArray();
386 pArray
[0] = "com.sun.star.frame.ToolbarController";
390 void SAL_CALL
NewToolbarController::initialize( const css::uno::Sequence
< css::uno::Any
>& aArguments
)
391 throw ( css::uno::Exception
, css::uno::RuntimeException
, std::exception
)
393 PopupMenuToolbarController::initialize( aArguments
);
395 osl::MutexGuard
aGuard( m_aMutex
);
396 createPopupMenuController();
399 void SAL_CALL
NewToolbarController::statusChanged( const css::frame::FeatureStateEvent
& rEvent
)
400 throw ( css::uno::RuntimeException
, std::exception
)
402 if ( rEvent
.IsEnabled
)
405 rEvent
.State
>>= aState
;
408 // set the image even if the state is not a string
409 // this will set the image of the default module
410 setItemImage( aState
);
412 catch (const css::ucb::CommandFailedException
&)
415 catch (const css::ucb::ContentCreationException
&)
420 enable( rEvent
.IsEnabled
);
423 void SAL_CALL
NewToolbarController::execute( sal_Int16
/*KeyModifier*/ )
424 throw ( css::uno::RuntimeException
, std::exception
)
426 osl::MutexGuard
aGuard( m_aMutex
);
427 if ( !m_aLastURL
.getLength() )
430 OUString
aTarget( "_default" );
431 if ( m_xPopupMenu
.is() )
433 // TODO investigate how to wrap Get/SetUserValue in css::awt::XMenu
434 MenuAttributes
* pMenuAttributes( 0 );
435 VCLXPopupMenu
* pTkPopupMenu
=
436 static_cast<VCLXPopupMenu
*>( VCLXMenu::GetImplementation( m_xPopupMenu
) );
438 SolarMutexGuard aSolarMutexGuard
;
439 PopupMenu
* pVCLPopupMenu
= pTkPopupMenu
?
440 dynamic_cast< PopupMenu
* >( pTkPopupMenu
->GetMenu() ) : NULL
;
443 pMenuAttributes
= reinterpret_cast< MenuAttributes
* >(
444 pVCLPopupMenu
->GetUserValue( pVCLPopupMenu
->GetCurItemId() ) );
446 if ( pMenuAttributes
)
447 aTarget
= pMenuAttributes
->aTargetFrame
;
450 css::uno::Sequence
< css::beans::PropertyValue
> aArgs( 1 );
451 aArgs
[0].Name
= "Referer";
452 aArgs
[0].Value
<<= OUString( "private:user" );
454 dispatchCommand( m_aLastURL
, aArgs
, aTarget
);
457 void NewToolbarController::functionExecuted( const OUString
&rCommand
)
459 setItemImage( rCommand
);
463 it return the existing state of the given URL in the popupmenu of this toolbox control.
465 If the given URL can be located as an action command of one menu item of the
466 popup menu of this control, we return sal_True. Otherwhise we return sal_False.
467 Further we return a fallback URL, in case we have to return sal_False. Because
468 the outside code must select a valid item of the popup menu every time ...
469 and we define it here. By the way this m ethod was written to handle
470 error situations gracefully. E.g. it can be called during creation time
471 but then we have no valid menu. For this case we know another fallback URL.
472 Then we return the private:factory/ URL of the default factory.
475 pounts to the popup menu, on which item we try to locate the given URL
476 Can be NULL! Search will be suppressed then.
479 the URL for searching
482 contains the fallback URL in case we return FALSE
483 Must point to valid memory!
486 contains the image of the menu for the URL.
488 @return sal_True - if URL could be located as an item of the popup menu.
489 sal_False - otherwhise.
491 static bool Impl_ExistURLInMenu(
492 const css::uno::Reference
< css::awt::XPopupMenu
> &rPopupMenu
,
497 bool bValidFallback( false );
498 sal_uInt16
nCount( 0 );
499 if ( rPopupMenu
.is() && ( nCount
= rPopupMenu
->getItemCount() ) != 0 && sURL
.getLength() )
501 for ( sal_uInt16 n
= 0; n
< nCount
; ++n
)
503 sal_uInt16 nId
= rPopupMenu
->getItemId( n
);
504 OUString
aCmd( rPopupMenu
->getCommand( nId
) );
506 if ( !bValidFallback
&& aCmd
.getLength() )
509 bValidFallback
= true;
512 // match even if the menu command is more detailed
513 // (maybe an additional query) #i28667#
514 if ( aCmd
.match( sURL
) )
517 const css::uno::Reference
< css::graphic::XGraphic
> xGraphic(
518 rPopupMenu
->getItemImage( nId
) );
520 aImage
= Image( xGraphic
);
526 if ( !bValidFallback
)
528 OUStringBuffer aBuffer
;
529 aBuffer
.append( "private:factory/" );
530 aBuffer
.append( SvtModuleOptions().GetDefaultModuleName() );
531 sFallback
= aBuffer
.makeStringAndClear();
537 /** We accept URL's here only, which exist as items of our internal popup menu.
538 All other ones will be ignored and a fallback is used.
540 void NewToolbarController::setItemImage( const OUString
&rCommand
)
542 SolarMutexGuard aSolarLock
;
543 VclPtr
< ToolBox
> pToolBox
= static_cast< ToolBox
* >( VCLUnoHelper::GetWindow( getParent() ).get() );
547 OUString aURL
= rCommand
;
551 bool bValid( Impl_ExistURLInMenu( m_xPopupMenu
, aURL
, sFallback
, aMenuImage
) );
555 bool bBig
= SvtMiscOptions().AreCurrentSymbolsLarge();
557 INetURLObject
aURLObj( aURL
);
558 Image aImage
= SvFileInformationManager::GetImageNoDefault( aURLObj
, bBig
);
560 aImage
= !!aMenuImage
?
562 SvFileInformationManager::GetImage( aURLObj
, bBig
);
564 // if everything failed, just use the image associated with the toolbar item command
568 Size
aBigSize( pToolBox
->GetDefaultImageSize() );
569 if ( bBig
&& aImage
.GetSizePixel() != aBigSize
)
571 BitmapEx
aScaleBmpEx( aImage
.GetBitmapEx() );
572 aScaleBmpEx
.Scale( aBigSize
, BmpScaleFlag::Interpolate
);
573 pToolBox
->SetItemImage( m_nToolBoxId
, Image( aScaleBmpEx
) );
576 pToolBox
->SetItemImage( m_nToolBoxId
, aImage
);
583 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
* SAL_CALL
584 org_apache_openoffice_comp_framework_WizardsToolbarController_get_implementation(
585 css::uno::XComponentContext
*context
,
586 css::uno::Sequence
<css::uno::Any
> const &)
588 return cppu::acquire(new WizardsToolbarController(context
));
591 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
* SAL_CALL
592 org_apache_openoffice_comp_framework_OpenToolbarController_get_implementation(
593 css::uno::XComponentContext
*context
,
594 css::uno::Sequence
<css::uno::Any
> const &)
596 return cppu::acquire(new OpenToolbarController(context
));
599 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
* SAL_CALL
600 org_apache_openoffice_comp_framework_NewToolbarController_get_implementation(
601 css::uno::XComponentContext
*context
,
602 css::uno::Sequence
<css::uno::Any
> const &)
604 return cppu::acquire(new NewToolbarController(context
));
607 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */