LibreOffice Module framework (master) 1
generictoolbarcontroller.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
21
22#include <com/sun/star/util/XURLTransformer.hpp>
23#include <com/sun/star/frame/XDispatch.hpp>
24#include <com/sun/star/lang/DisposedException.hpp>
25#include <com/sun/star/frame/status/ItemStatus.hpp>
26#include <com/sun/star/frame/status/Visibility.hpp>
27#include <com/sun/star/frame/ControlCommand.hpp>
28
30#include <svl/imageitm.hxx>
32#include <vcl/svapp.hxx>
33#include <vcl/weld.hxx>
34#include <tools/urlobj.hxx>
36#include <strings.hrc>
37#include <classes/fwkresid.hxx>
38
39using namespace ::com::sun::star::uno;
40using namespace ::com::sun::star::beans;
41using namespace ::com::sun::star::lang;
42using namespace ::com::sun::star::frame;
43using namespace ::com::sun::star::frame::status;
44
45namespace framework
46{
47
48static bool isEnumCommand( std::u16string_view rCommand )
49{
50 INetURLObject aURL( rCommand );
51
52 return ( aURL.GetProtocol() == INetProtocol::Uno ) &&
53 ( aURL.GetURLPath().indexOf( '.' ) != -1);
54}
55
56static OUString getEnumCommand( std::u16string_view rCommand )
57{
58 INetURLObject aURL( rCommand );
59
60 OUString aEnumCommand;
61 OUString aURLPath = aURL.GetURLPath();
62 sal_Int32 nIndex = aURLPath.indexOf( '.' );
63 if (( nIndex > 0 ) && ( nIndex < aURLPath.getLength() ))
64 aEnumCommand = aURLPath.copy( nIndex+1 );
65
66 return aEnumCommand;
67}
68
69static OUString getMasterCommand( const OUString& rCommand )
70{
71 OUString aMasterCommand( rCommand );
72 INetURLObject aURL( rCommand );
73 if ( aURL.GetProtocol() == INetProtocol::Uno )
74 {
75 sal_Int32 nIndex = aURL.GetURLPath().indexOf( '.' );
76 if ( nIndex )
77 {
78 aURL.SetURLPath( aURL.GetURLPath().subView( 0, nIndex ) );
79 aMasterCommand = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
80 }
81 }
82 return aMasterCommand;
83}
84
85GenericToolbarController::GenericToolbarController( const Reference< XComponentContext >& rxContext,
86 const Reference< XFrame >& rFrame,
87 ToolBox* pToolbar,
88 ToolBoxItemId nID,
89 const OUString& aCommand ) :
90 svt::ToolboxController( rxContext, rFrame, aCommand )
91 , m_xToolbar( pToolbar )
92 , m_nID( nID )
93 , m_bEnumCommand( isEnumCommand( aCommand ))
94 , m_bMirrored( false )
95 , m_bMadeInvisible( false )
96 , m_aEnumCommand( getEnumCommand( aCommand ))
97{
98 if ( m_bEnumCommand )
99 addStatusListener( getMasterCommand( aCommand ) );
100
101 addStatusListener( aCommand );
102
103 // Initialization is done through ctor
104 m_bInitialized = true;
105}
106
107GenericToolbarController::GenericToolbarController( const Reference< XComponentContext >& rxContext,
108 const Reference< XFrame >& rFrame,
109 weld::Toolbar& rToolbar,
110 const OUString& aCommand ) :
111 GenericToolbarController( rxContext, rFrame, nullptr, ToolBoxItemId(0), aCommand )
112{
113 m_pToolbar = &rToolbar;
114}
115
116GenericToolbarController::~GenericToolbarController()
117{
118}
119
120void SAL_CALL GenericToolbarController::dispose()
121{
122 SolarMutexGuard aSolarMutexGuard;
123
125
126 m_pToolbar = nullptr;
127 m_xToolbar.clear();
128 m_nID = ToolBoxItemId(0);
129}
130
131void SAL_CALL GenericToolbarController::execute( sal_Int16 KeyModifier )
132{
133 Reference< XDispatch > xDispatch;
134 OUString aCommandURL;
135
136 {
137 SolarMutexGuard aSolarMutexGuard;
138
139 if ( m_bDisposed )
140 throw DisposedException();
141
142 if ( m_bInitialized &&
143 m_xFrame.is() &&
144 !m_aCommandURL.isEmpty() )
145 {
146 aCommandURL = m_aCommandURL;
147 URLToDispatchMap::iterator pIter = m_aListenerMap.find( m_aCommandURL );
148 if ( pIter != m_aListenerMap.end() )
149 xDispatch = pIter->second;
150 }
151 }
152
153 if ( !xDispatch.is() )
154 return;
155
156 css::util::URL aTargetURL;
157
158 // Add key modifier to argument list
159 Sequence<PropertyValue> aArgs{ comphelper::makePropertyValue("KeyModifier", KeyModifier) };
160
161 // handle also command aliases
165
166 aTargetURL.Complete = sRealCommand.isEmpty() ? aCommandURL : sRealCommand;
167 if ( m_xUrlTransformer.is() )
168 m_xUrlTransformer->parseStrict( aTargetURL );
169
170 // Execute dispatch asynchronously
171 ExecuteInfo* pExecuteInfo = new ExecuteInfo;
172 pExecuteInfo->xDispatch = xDispatch;
173 pExecuteInfo->aTargetURL = aTargetURL;
174 pExecuteInfo->aArgs = aArgs;
175 Application::PostUserEvent( LINK(nullptr, GenericToolbarController , ExecuteHdl_Impl), pExecuteInfo );
176}
177
178void GenericToolbarController::statusChanged( const FeatureStateEvent& Event )
179{
180 SolarMutexGuard aSolarMutexGuard;
181
182 if ( m_bDisposed )
183 return;
184
185 if ( m_pToolbar )
186 {
187 m_pToolbar->set_item_sensitive(m_aCommandURL, Event.IsEnabled);
188
189 bool bValue;
190 OUString aStrValue;
191 SfxImageItem aImageItem;
192
193 if ( Event.State >>= bValue )
194 {
195 // Boolean, treat it as checked/unchecked
196 m_pToolbar->set_item_active(m_aCommandURL, bValue);
197 }
198 else if ( Event.State >>= aStrValue )
199 {
200 m_pToolbar->set_item_label(m_aCommandURL, aStrValue);
201 }
202 else if ( aImageItem.PutValue( Event.State, 0 ) && aImageItem.IsMirrored() != m_bMirrored )
203 {
204 m_pToolbar->set_item_image_mirrored(m_aCommandURL, aImageItem.IsMirrored());
205 auto xGraphic(vcl::CommandInfoProvider::GetXGraphicForCommand(m_aCommandURL, m_xFrame, m_pToolbar->get_icon_size()));
206 m_pToolbar->set_item_image(m_aCommandURL, xGraphic);
207 m_bMirrored = !m_bMirrored;
208 }
209 else
210 m_pToolbar->set_item_active(m_aCommandURL, false);
211
212 return;
213 }
214
215 if ( !m_xToolbar )
216 return;
217
218 m_xToolbar->EnableItem( m_nID, Event.IsEnabled );
219
220 ToolBoxItemBits nItemBits = m_xToolbar->GetItemBits( m_nID );
221 nItemBits &= ~ToolBoxItemBits::CHECKABLE;
223
224 bool bValue;
225 OUString aStrValue;
226 ItemStatus aItemState;
227 Visibility aItemVisibility;
228 ControlCommand aControlCommand;
229 SfxImageItem aImageItem;
230
231 if (( Event.State >>= bValue ) && !m_bEnumCommand )
232 {
233 // Boolean, treat it as checked/unchecked
234 if ( m_bMadeInvisible )
235 m_xToolbar->ShowItem( m_nID );
236 m_xToolbar->CheckItem( m_nID, bValue );
237 if ( bValue )
238 eTri = TRISTATE_TRUE;
239 nItemBits |= ToolBoxItemBits::CHECKABLE;
240 }
241 else if ( Event.State >>= aStrValue )
242 {
243 if ( m_bEnumCommand )
244 {
245 bValue = aStrValue == m_aEnumCommand;
246
247 m_xToolbar->CheckItem( m_nID, bValue );
248 if ( bValue )
249 eTri = TRISTATE_TRUE;
250 nItemBits |= ToolBoxItemBits::CHECKABLE;
251 }
252 else
253 {
254 // Replacement for place holders
255 if ( aStrValue.startsWith("($1)") )
256 {
257 aStrValue = FwkResId(STR_UPDATEDOC) + " " + aStrValue.subView( 4 );
258 }
259 else if ( aStrValue.startsWith("($2)") )
260 {
261 aStrValue = FwkResId(STR_CLOSEDOC_ANDRETURN) + aStrValue.subView( 4 );
262 }
263 else if ( aStrValue.startsWith("($3)") )
264 {
265 aStrValue = FwkResId(STR_SAVECOPYDOC) + aStrValue.subView( 4 );
266 }
267 m_xToolbar->SetItemText( m_nID, aStrValue );
268 // tdf#124267 strip mnemonic from tooltip
269 m_xToolbar->SetQuickHelpText(m_nID, aStrValue.replaceFirst("~", ""));
270 }
271
272 if ( m_bMadeInvisible )
273 m_xToolbar->ShowItem( m_nID );
274 }
275 else if (( Event.State >>= aItemState ) && !m_bEnumCommand )
276 {
277 eTri = TRISTATE_INDET;
278 nItemBits |= ToolBoxItemBits::CHECKABLE;
279 if ( m_bMadeInvisible )
280 m_xToolbar->ShowItem( m_nID );
281 }
282 else if ( Event.State >>= aItemVisibility )
283 {
284 m_xToolbar->ShowItem( m_nID, aItemVisibility.bVisible );
285 m_bMadeInvisible = !aItemVisibility.bVisible;
286 }
287 else if ( Event.State >>= aControlCommand )
288 {
289 if (aControlCommand.Command == "SetQuickHelpText")
290 {
291 for ( NamedValue const & rArg : std::as_const(aControlCommand.Arguments) )
292 {
293 if (rArg.Name == "HelpText")
294 {
295 OUString aHelpText;
296 rArg.Value >>= aHelpText;
297 m_xToolbar->SetQuickHelpText(m_nID, aHelpText);
298 break;
299 }
300 }
301 }
302 if ( m_bMadeInvisible )
303 m_xToolbar->ShowItem( m_nID );
304 }
305 else if ( aImageItem.PutValue( Event.State, 0 ) && aImageItem.IsMirrored() != m_bMirrored )
306 {
307 m_xToolbar->SetItemImageMirrorMode( m_nID, aImageItem.IsMirrored() );
308 Image aImage( vcl::CommandInfoProvider::GetImageForCommand( m_aCommandURL, m_xFrame, m_xToolbar->GetImageSize() ));
309 m_xToolbar->SetItemImage( m_nID, aImage );
310 m_bMirrored = !m_bMirrored;
311 if ( m_bMadeInvisible )
312 m_xToolbar->ShowItem( m_nID );
313 }
314 else if ( m_bMadeInvisible )
315 m_xToolbar->ShowItem( m_nID );
316
317 m_xToolbar->SetItemState( m_nID, eTri );
318 m_xToolbar->SetItemBits( m_nID, nItemBits );
319}
320
321IMPL_STATIC_LINK( GenericToolbarController, ExecuteHdl_Impl, void*, p, void )
322{
323 ExecuteInfo* pExecuteInfo = static_cast<ExecuteInfo*>(p);
324 SolarMutexReleaser aReleaser;
325 try
326 {
327 // Asynchronous execution as this can lead to our own destruction!
328 // Framework can recycle our current frame and the layout manager disposes all user interface
329 // elements if a component gets detached from its frame!
330 pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
331 }
332 catch ( const Exception& )
333 {
334 }
335
336 delete pExecuteInfo;
337}
338
339ImageOrientationController::ImageOrientationController(const Reference<XComponentContext>& rContext,
340 const Reference<XFrame>& rFrame,
341 const Reference<css::awt::XWindow>& rParentWindow,
342 const OUString& rModuleName)
343 : ToolboxController(rContext, rFrame, ".uno:ImageOrientation")
344 , m_nRotationAngle(0_deg10)
345 , m_bMirrored(false)
346{
347 m_sModuleName = rModuleName;
348 m_xParentWindow = rParentWindow;
349 initialize({});
350 if (!m_pToolbar)
352}
353
355{
356 ToolboxController::dispose();
358 if (pWindow)
359 pWindow->RemoveEventListener(LINK(this, ImageOrientationController, WindowEventListener));
360}
361
362IMPL_LINK(ImageOrientationController, WindowEventListener, VclWindowEvent&, rWindowEvent, void)
363{
364 if (m_bDisposed || rWindowEvent.GetId() != VclEventId::ToolboxItemAdded)
365 return;
366
367 ToolBox* pToolBox = static_cast<ToolBox*>(rWindowEvent.GetWindow());
368 ToolBoxItemId nItemId = pToolBox->GetItemId(reinterpret_cast<sal_IntPtr>(rWindowEvent.GetData()));
369 OUString aCommand = pToolBox->GetItemCommand(nItemId);
370
372 pToolBox->SetItemImageMirrorMode(nItemId, m_bMirrored);
373 if (vcl::CommandInfoProvider::IsRotated(aCommand, getModuleName()))
374 pToolBox->SetItemImageAngle(nItemId, m_nRotationAngle);
375}
376
377void ImageOrientationController::statusChanged(const css::frame::FeatureStateEvent& rEvent)
378{
379 if (m_bDisposed)
380 throw DisposedException();
381
382 SfxImageItem aItem;
383 aItem.PutValue(rEvent.State, 0);
384
385 if (m_bMirrored == aItem.IsMirrored() && m_nRotationAngle == aItem.GetRotation())
386 return;
387
388 m_bMirrored = aItem.IsMirrored();
390
391 if (m_pToolbar)
392 {
393 for (int i = 0, nCount = m_pToolbar->get_n_items(); i < nCount; ++i)
394 {
395 OUString aCommand = m_pToolbar->get_item_ident(i);
397 {
402 }
403 }
404 }
405 else
406 {
407 ToolBox* pToolBox = static_cast<ToolBox*>(VCLUnoHelper::GetWindow(getParent()));
408 for (ToolBox::ImplToolItems::size_type i = 0; i < pToolBox->GetItemCount(); ++i)
409 {
410 ToolBoxItemId nItemId = pToolBox->GetItemId(i);
411 OUString aCommand = pToolBox->GetItemCommand(nItemId);
412 bool bModified = false;
414 {
415 pToolBox->SetItemImageMirrorMode(nItemId, m_bMirrored);
416 bModified = true;
417 }
419 {
420 pToolBox->SetItemImageAngle(nItemId, m_nRotationAngle);
421 bModified = true;
422 }
423 if (bModified)
424 {
426 pToolBox->SetItemImage(nItemId, aImage);
427 }
428 }
429 }
430}
431
432} // namespace
433
434/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PropertiesInfo aProperties
css::uno::Reference< css::lang::XComponent > m_xFrame
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
Degree10 GetRotation() const
virtual bool PutValue(const css::uno::Any &rVal, sal_uInt8 nMemberId) override
bool IsMirrored() const
ToolBoxItemId GetItemId(ImplToolItems::size_type nPos) const
vcl::ImageType GetImageSize() const
OUString GetItemCommand(ToolBoxItemId nItemId) const
void SetItemImageAngle(ToolBoxItemId nItemId, Degree10 nAngle10)
void SetItemImageMirrorMode(ToolBoxItemId nItemId, bool bMirror)
ImplToolItems::size_type GetItemCount() const
void SetItemImage(ToolBoxItemId nItemId, const Image &rImage)
static vcl::Window * GetWindow(const css::uno::Reference< css::awt::XWindow > &rxWindow)
GenericToolbarController(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::frame::XFrame > &rFrame, ToolBox *pToolBar, ToolBoxItemId nID, const OUString &aCommand)
void SAL_CALL statusChanged(const css::frame::FeatureStateEvent &rEvent) override
virtual void SAL_CALL dispose() override
css::uno::Reference< css::awt::XWindow > m_xParentWindow
const OUString & getModuleName() const
const css::uno::Reference< css::awt::XWindow > & getParent() const
weld::Toolbar * m_pToolbar
css::uno::Reference< css::frame::XFrame > m_xFrame
virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &aArguments) override
void AddEventListener(const Link< VclWindowEvent &, void > &rEventListener)
virtual vcl::ImageType get_icon_size() const=0
virtual int get_n_items() const=0
virtual void set_item_image_mirrored(const OUString &rIdent, bool bMirrored)=0
virtual OUString get_item_ident(int nIndex) const=0
virtual void set_item_image(const OUString &rIdent, const css::uno::Reference< css::graphic::XGraphic > &rIcon)=0
int nCount
Reference< XDispatch > xDispatch
URL aURL
OUString FwkResId(TranslateId aId)
Definition: fwkresid.cxx:22
TriState
TRISTATE_FALSE
TRISTATE_INDET
TRISTATE_TRUE
bool m_bDisposed
sal_Int32 nIndex
void * p
@ Exception
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
static OUString getEnumCommand(std::u16string_view rCommand)
IMPL_STATIC_LINK(GenericToolbarController, ExecuteHdl_Impl, void *, p, void)
IMPL_LINK(WindowCommandDispatch, impl_notifyCommand, VclWindowEvent &, rEvent, void)
static bool isEnumCommand(std::u16string_view rCommand)
static OUString getMasterCommand(const OUString &rCommand)
int i
Visibility
Sequence< beans::PropertyValue > GetCommandProperties(const OUString &rsCommandName, const OUString &rsModuleName)
bool IsRotated(const OUString &rsCommandName, const OUString &rsModuleName)
OUString GetRealCommandForCommand(const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
Reference< graphic::XGraphic > GetXGraphicForCommand(const OUString &rsCommandName, const Reference< frame::XFrame > &rxFrame, vcl::ImageType eImageType)
OUString GetModuleIdentifier(const Reference< frame::XFrame > &rxFrame)
Image GetImageForCommand(const OUString &rsCommandName, const Reference< frame::XFrame > &rxFrame, vcl::ImageType eImageType)
bool IsMirrored(const OUString &rsCommandName, const OUString &rsModuleName)
css::uno::Reference< css::frame::XDispatch > xDispatch
css::uno::Sequence< css::beans::PropertyValue > aArgs
OUString aCommand
OUString aTargetURL
ToolBoxItemBits