1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26
27 #ifndef __FRAMEWORK_UIELEMENT_COMPLEXTOOLBARCONTROLLER_HXX
28 #include "uielement/complextoolbarcontroller.hxx"
29 #endif
30
31 //_________________________________________________________________________________________________________________
32 // my own includes
33 //_________________________________________________________________________________________________________________
34
35 #ifndef __FRAMEWORK_TOOLBAR_HXX_
36 #include "uielement/toolbar.hxx"
37 #endif
38
39 //_________________________________________________________________________________________________________________
40 // interface includes
41 //_________________________________________________________________________________________________________________
42 #include <com/sun/star/util/XURLTransformer.hpp>
43 #include <com/sun/star/frame/XDispatchProvider.hpp>
44 #include <com/sun/star/beans/PropertyValue.hpp>
45 #include <com/sun/star/lang/DisposedException.hpp>
46 #include <com/sun/star/frame/status/ItemStatus.hpp>
47 #include <com/sun/star/frame/status/ItemState.hpp>
48 #include <com/sun/star/frame/status/Visibility.hpp>
49 #include <com/sun/star/frame/XControlNotificationListener.hpp>
50
51 //_________________________________________________________________________________________________________________
52 // other includes
53 //_________________________________________________________________________________________________________________
54 #include <svtools/toolboxcontroller.hxx>
55 #include <vos/mutex.hxx>
56 #include <vcl/svapp.hxx>
57 #ifndef _VCL_MNEMONIC_HXX_
58 #include <vcl/mnemonic.hxx>
59 #endif
60 #include <tools/urlobj.hxx>
61 #include <dispatch/uieventloghelper.hxx>
62
63 using namespace ::com::sun::star;
64 using namespace ::com::sun::star::awt;
65 using namespace ::com::sun::star::uno;
66 using namespace ::com::sun::star::beans;
67 using namespace ::com::sun::star::lang;
68 using namespace ::com::sun::star::frame;
69 using namespace ::com::sun::star::frame::status;
70 using namespace ::com::sun::star::util;
71
72 namespace framework
73 {
74
75 // ------------------------------------------------------------------
76
ComplexToolbarController(const Reference<XMultiServiceFactory> & rServiceManager,const Reference<XFrame> & rFrame,ToolBox * pToolbar,sal_uInt16 nID,const::rtl::OUString & aCommand)77 ComplexToolbarController::ComplexToolbarController(
78 const Reference< XMultiServiceFactory >& rServiceManager,
79 const Reference< XFrame >& rFrame,
80 ToolBox* pToolbar,
81 sal_uInt16 nID,
82 const ::rtl::OUString& aCommand ) :
83 svt::ToolboxController( rServiceManager, rFrame, aCommand )
84 , m_pToolbar( pToolbar )
85 , m_nID( nID )
86 , m_bMadeInvisible( sal_False )
87 {
88 m_xURLTransformer.set( m_xServiceManager->createInstance(
89 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))),
90 UNO_QUERY_THROW );
91 }
92
93 // ------------------------------------------------------------------
94
~ComplexToolbarController()95 ComplexToolbarController::~ComplexToolbarController()
96 {
97 }
98
99 // ------------------------------------------------------------------
100
dispose()101 void SAL_CALL ComplexToolbarController::dispose()
102 throw ( RuntimeException )
103 {
104 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
105
106 m_pToolbar->SetItemWindow( m_nID, 0 );
107 svt::ToolboxController::dispose();
108
109 m_xURLTransformer.clear();
110 m_pToolbar = 0;
111 m_nID = 0;
112 }
113
114 // ------------------------------------------------------------------
getExecuteArgs(sal_Int16 KeyModifier) const115 Sequence<PropertyValue> ComplexToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const
116 {
117 Sequence<PropertyValue> aArgs( 1 );
118
119 // Add key modifier to argument list
120 aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" ));
121 aArgs[0].Value <<= KeyModifier;
122 return aArgs;
123 }
124 // -----------------------------------------------------------------------------
execute(sal_Int16 KeyModifier)125 void SAL_CALL ComplexToolbarController::execute( sal_Int16 KeyModifier )
126 throw ( RuntimeException )
127 {
128 Reference< XDispatch > xDispatch;
129 Reference< XURLTransformer > xURLTransformer;
130 ::rtl::OUString aCommandURL;
131 ::com::sun::star::util::URL aTargetURL;
132 Sequence<PropertyValue> aArgs;
133
134 {
135 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
136
137 if ( m_bDisposed )
138 throw DisposedException();
139
140 if ( m_bInitialized &&
141 m_xFrame.is() &&
142 m_xServiceManager.is() &&
143 m_aCommandURL.getLength() )
144 {
145 xURLTransformer = m_xURLTransformer;
146 xDispatch = getDispatchFromCommand( m_aCommandURL );
147 aCommandURL = m_aCommandURL;
148 aTargetURL = getInitializedURL();
149 aArgs = getExecuteArgs(KeyModifier);
150 }
151 }
152
153 if ( xDispatch.is() && aTargetURL.Complete.getLength() > 0 )
154 {
155 // Execute dispatch asynchronously
156 ExecuteInfo* pExecuteInfo = new ExecuteInfo;
157 pExecuteInfo->xDispatch = xDispatch;
158 pExecuteInfo->aTargetURL = aTargetURL;
159 pExecuteInfo->aArgs = aArgs;
160 if(::comphelper::UiEventsLogger::isEnabled()) //#i88653#
161 UiEventLogHelper(::rtl::OUString::createFromAscii("ComplexToolbarController")).log(
162 m_xServiceManager,
163 m_xFrame,
164 aTargetURL,
165 aArgs);
166 Application::PostUserEvent( STATIC_LINK(0, ComplexToolbarController , ExecuteHdl_Impl), pExecuteInfo );
167 }
168 }
169
170 // ------------------------------------------------------------------
171
statusChanged(const FeatureStateEvent & Event)172 void ComplexToolbarController::statusChanged( const FeatureStateEvent& Event )
173 throw ( RuntimeException )
174 {
175 vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
176
177 if ( m_bDisposed )
178 return;
179
180 if ( m_pToolbar )
181 {
182 m_pToolbar->EnableItem( m_nID, Event.IsEnabled );
183
184 sal_uInt16 nItemBits = m_pToolbar->GetItemBits( m_nID );
185 nItemBits &= ~TIB_CHECKABLE;
186 TriState eTri = STATE_NOCHECK;
187
188 sal_Bool bValue = sal_Bool();
189 rtl::OUString aStrValue;
190 ItemStatus aItemState;
191 Visibility aItemVisibility;
192 ControlCommand aControlCommand;
193
194 if ( Event.State >>= bValue )
195 {
196 // Boolean, treat it as checked/unchecked
197 if ( m_bMadeInvisible )
198 m_pToolbar->ShowItem( m_nID, sal_True );
199 m_pToolbar->CheckItem( m_nID, bValue );
200 if ( bValue )
201 eTri = STATE_CHECK;
202 nItemBits |= TIB_CHECKABLE;
203 }
204 else if ( Event.State >>= aStrValue )
205 {
206 ::rtl::OUString aText( MnemonicGenerator::EraseAllMnemonicChars( aStrValue ) );
207 m_pToolbar->SetItemText( m_nID, aText );
208 m_pToolbar->SetQuickHelpText( m_nID, aText );
209
210 if ( m_bMadeInvisible )
211 m_pToolbar->ShowItem( m_nID, sal_True );
212 }
213 else if ( Event.State >>= aItemState )
214 {
215 eTri = STATE_DONTKNOW;
216 nItemBits |= TIB_CHECKABLE;
217 if ( m_bMadeInvisible )
218 m_pToolbar->ShowItem( m_nID, sal_True );
219 }
220 else if ( Event.State >>= aItemVisibility )
221 {
222 m_pToolbar->ShowItem( m_nID, aItemVisibility.bVisible );
223 m_bMadeInvisible = !aItemVisibility.bVisible;
224 }
225 else if ( Event.State >>= aControlCommand )
226 {
227 executeControlCommand( aControlCommand );
228 if ( m_bMadeInvisible )
229 m_pToolbar->ShowItem( m_nID, sal_True );
230 }
231
232 else if ( m_bMadeInvisible )
233 m_pToolbar->ShowItem( m_nID, sal_True );
234
235 m_pToolbar->SetItemState( m_nID, eTri );
236 m_pToolbar->SetItemBits( m_nID, nItemBits );
237 }
238 }
239
240 // ------------------------------------------------------------------
241
IMPL_STATIC_LINK_NOINSTANCE(ComplexToolbarController,ExecuteHdl_Impl,ExecuteInfo *,pExecuteInfo)242 IMPL_STATIC_LINK_NOINSTANCE( ComplexToolbarController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
243 {
244 const sal_uInt32 nRef = Application::ReleaseSolarMutex();
245 try
246 {
247 // Asynchronous execution as this can lead to our own destruction!
248 // Framework can recycle our current frame and the layout manager disposes all user interface
249 // elements if a component gets detached from its frame!
250 pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
251 }
252 catch ( Exception& )
253 {
254 }
255
256 Application::AcquireSolarMutex( nRef );
257 delete pExecuteInfo;
258 return 0;
259 }
260
261 // ------------------------------------------------------------------
262
IMPL_STATIC_LINK_NOINSTANCE(ComplexToolbarController,Notify_Impl,NotifyInfo *,pNotifyInfo)263 IMPL_STATIC_LINK_NOINSTANCE( ComplexToolbarController, Notify_Impl, NotifyInfo*, pNotifyInfo )
264 {
265 const sal_uInt32 nRef = Application::ReleaseSolarMutex();
266 try
267 {
268 // Asynchronous execution: As this can lead to our own destruction!
269 // Framework can recycle our current frame and the layout manager disposes all user interface
270 // elements if a component gets detached from its frame!
271 frame::ControlEvent aEvent;
272 aEvent.aURL = pNotifyInfo->aSourceURL;
273 aEvent.Event = pNotifyInfo->aEventName;
274 aEvent.aInformation = pNotifyInfo->aInfoSeq;
275 pNotifyInfo->xNotifyListener->controlEvent( aEvent );
276 }
277 catch ( Exception& )
278 {
279 }
280
281 Application::AcquireSolarMutex( nRef );
282 delete pNotifyInfo;
283 return 0;
284 }
285
286 // ------------------------------------------------------------------
287
addNotifyInfo(const rtl::OUString & aEventName,const uno::Reference<frame::XDispatch> & xDispatch,const uno::Sequence<beans::NamedValue> & rInfo)288 void ComplexToolbarController::addNotifyInfo(
289 const rtl::OUString& aEventName,
290 const uno::Reference< frame::XDispatch >& xDispatch,
291 const uno::Sequence< beans::NamedValue >& rInfo )
292 {
293 uno::Reference< frame::XControlNotificationListener > xControlNotify( xDispatch, uno::UNO_QUERY );
294
295 if ( xControlNotify.is() )
296 {
297 // Execute notification asynchronously
298 NotifyInfo* pNotifyInfo = new NotifyInfo;
299
300 pNotifyInfo->aEventName = aEventName;
301 pNotifyInfo->xNotifyListener = xControlNotify;
302 pNotifyInfo->aSourceURL = getInitializedURL();
303
304 // Add frame as source to the information sequence
305 sal_Int32 nCount = rInfo.getLength();
306 uno::Sequence< beans::NamedValue > aInfoSeq( rInfo );
307 aInfoSeq.realloc( nCount+1 );
308 aInfoSeq[nCount].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Source" ));
309 aInfoSeq[nCount].Value = uno::makeAny( getFrameInterface() );
310 pNotifyInfo->aInfoSeq = aInfoSeq;
311
312 Application::PostUserEvent( STATIC_LINK(0, ComplexToolbarController, Notify_Impl), pNotifyInfo );
313 }
314 }
315
316 // --------------------------------------------------------
getFontSizePixel(const Window * pWindow)317 sal_Int32 ComplexToolbarController::getFontSizePixel( const Window* pWindow )
318 {
319 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
320 const Font& rFont = rSettings.GetAppFont();
321
322 // Calculate height of the application font used by window
323 sal_Int32 nHeight = sal_Int32( rFont.GetHeight() );
324 ::Size aPixelSize = pWindow->LogicToPixel( ::Size( 0, nHeight ), MAP_APPFONT );
325 return aPixelSize.Height();
326 }
327
328 // --------------------------------------------------------
329
getDispatchFromCommand(const rtl::OUString & aCommand) const330 uno::Reference< frame::XDispatch > ComplexToolbarController::getDispatchFromCommand( const rtl::OUString& aCommand ) const
331 {
332 uno::Reference< frame::XDispatch > xDispatch;
333
334 if ( m_bInitialized && m_xFrame.is() && m_xServiceManager.is() && aCommand.getLength() )
335 {
336 URLToDispatchMap::const_iterator pIter = m_aListenerMap.find( aCommand );
337 if ( pIter != m_aListenerMap.end() )
338 xDispatch = pIter->second;
339 }
340
341 return xDispatch;
342 }
343
344 // --------------------------------------------------------
345
getInitializedURL()346 const ::com::sun::star::util::URL& ComplexToolbarController::getInitializedURL()
347 {
348 if ( m_aURL.Complete.getLength() == 0 )
349 {
350 m_aURL.Complete = m_aCommandURL;
351 m_xURLTransformer->parseStrict( m_aURL );
352 }
353 return m_aURL;
354 }
355
notifyFocusGet()356 void ComplexToolbarController::notifyFocusGet()
357 {
358 // send focus get notification
359 uno::Sequence< beans::NamedValue > aInfo;
360 addNotifyInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FocusSet" )),
361 getDispatchFromCommand( m_aCommandURL ),
362 aInfo );
363 }
364
notifyFocusLost()365 void ComplexToolbarController::notifyFocusLost()
366 {
367 // send focus lost notification
368 uno::Sequence< beans::NamedValue > aInfo;
369 addNotifyInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FocusLost" )),
370 getDispatchFromCommand( m_aCommandURL ),
371 aInfo );
372 }
373
notifyTextChanged(const::rtl::OUString & aText)374 void ComplexToolbarController::notifyTextChanged( const ::rtl::OUString& aText )
375 {
376 // send text changed notification
377 uno::Sequence< beans::NamedValue > aInfo( 1 );
378 aInfo[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" ));
379 aInfo[0].Value <<= aText;
380 addNotifyInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TextChanged" )),
381 getDispatchFromCommand( m_aCommandURL ),
382 aInfo );
383 }
384
385 } // namespace
386
387