Line data Source code
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 :
20 :
21 : #include "uielement/complextoolbarcontroller.hxx"
22 :
23 : #include "uielement/toolbar.hxx"
24 :
25 : #include <com/sun/star/util/URLTransformer.hpp>
26 : #include <com/sun/star/util/XURLTransformer.hpp>
27 : #include <com/sun/star/frame/XDispatchProvider.hpp>
28 : #include <com/sun/star/beans/PropertyValue.hpp>
29 : #include <com/sun/star/lang/DisposedException.hpp>
30 : #include <com/sun/star/frame/status/ItemStatus.hpp>
31 : #include <com/sun/star/frame/status/ItemState.hpp>
32 : #include <com/sun/star/frame/status/Visibility.hpp>
33 : #include <com/sun/star/frame/XControlNotificationListener.hpp>
34 :
35 : #include <comphelper/processfactory.hxx>
36 : #include <svtools/toolboxcontroller.hxx>
37 : #include <osl/mutex.hxx>
38 : #include <vcl/svapp.hxx>
39 : #include <vcl/mnemonic.hxx>
40 :
41 : using namespace ::com::sun::star;
42 : using namespace ::com::sun::star::awt;
43 : using namespace ::com::sun::star::uno;
44 : using namespace ::com::sun::star::beans;
45 : using namespace ::com::sun::star::lang;
46 : using namespace ::com::sun::star::frame;
47 : using namespace ::com::sun::star::frame::status;
48 : using namespace ::com::sun::star::util;
49 :
50 : namespace framework
51 : {
52 :
53 : // ------------------------------------------------------------------
54 :
55 236 : ComplexToolbarController::ComplexToolbarController(
56 : const Reference< XMultiServiceFactory >& rServiceManager,
57 : const Reference< XFrame >& rFrame,
58 : ToolBox* pToolbar,
59 : sal_uInt16 nID,
60 : const ::rtl::OUString& aCommand ) :
61 : svt::ToolboxController( rServiceManager, rFrame, aCommand )
62 : , m_pToolbar( pToolbar )
63 : , m_nID( nID )
64 236 : , m_bMadeInvisible( sal_False )
65 : {
66 236 : m_xURLTransformer.set( URLTransformer::create(::comphelper::getComponentContext(m_xServiceManager)) );
67 236 : }
68 :
69 : // ------------------------------------------------------------------
70 :
71 63 : ComplexToolbarController::~ComplexToolbarController()
72 : {
73 63 : }
74 :
75 : // ------------------------------------------------------------------
76 :
77 63 : void SAL_CALL ComplexToolbarController::dispose()
78 : throw ( RuntimeException )
79 : {
80 63 : SolarMutexGuard aSolarMutexGuard;
81 :
82 63 : m_pToolbar->SetItemWindow( m_nID, 0 );
83 63 : svt::ToolboxController::dispose();
84 :
85 63 : m_xURLTransformer.clear();
86 63 : m_pToolbar = 0;
87 63 : m_nID = 0;
88 63 : }
89 :
90 : // ------------------------------------------------------------------
91 0 : Sequence<PropertyValue> ComplexToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const
92 : {
93 0 : Sequence<PropertyValue> aArgs( 1 );
94 :
95 : // Add key modifier to argument list
96 0 : aArgs[0].Name = rtl::OUString( "KeyModifier" );
97 0 : aArgs[0].Value <<= KeyModifier;
98 0 : return aArgs;
99 : }
100 : // -----------------------------------------------------------------------------
101 0 : void SAL_CALL ComplexToolbarController::execute( sal_Int16 KeyModifier )
102 : throw ( RuntimeException )
103 : {
104 0 : Reference< XDispatch > xDispatch;
105 0 : Reference< XURLTransformer > xURLTransformer;
106 0 : ::rtl::OUString aCommandURL;
107 0 : ::com::sun::star::util::URL aTargetURL;
108 0 : Sequence<PropertyValue> aArgs;
109 :
110 : {
111 0 : SolarMutexGuard aSolarMutexGuard;
112 :
113 0 : if ( m_bDisposed )
114 0 : throw DisposedException();
115 :
116 0 : if ( m_bInitialized &&
117 0 : m_xFrame.is() &&
118 0 : m_xServiceManager.is() &&
119 0 : !m_aCommandURL.isEmpty() )
120 : {
121 0 : xURLTransformer = m_xURLTransformer;
122 0 : xDispatch = getDispatchFromCommand( m_aCommandURL );
123 0 : aCommandURL = m_aCommandURL;
124 0 : aTargetURL = getInitializedURL();
125 0 : aArgs = getExecuteArgs(KeyModifier);
126 0 : }
127 : }
128 :
129 0 : if ( xDispatch.is() && !aTargetURL.Complete.isEmpty() )
130 : {
131 : // Execute dispatch asynchronously
132 0 : ExecuteInfo* pExecuteInfo = new ExecuteInfo;
133 0 : pExecuteInfo->xDispatch = xDispatch;
134 0 : pExecuteInfo->aTargetURL = aTargetURL;
135 0 : pExecuteInfo->aArgs = aArgs;
136 0 : Application::PostUserEvent( STATIC_LINK(0, ComplexToolbarController , ExecuteHdl_Impl), pExecuteInfo );
137 0 : }
138 0 : }
139 :
140 : // ------------------------------------------------------------------
141 :
142 236 : void ComplexToolbarController::statusChanged( const FeatureStateEvent& Event )
143 : throw ( RuntimeException )
144 : {
145 236 : SolarMutexGuard aSolarMutexGuard;
146 :
147 236 : if ( m_bDisposed )
148 236 : return;
149 :
150 236 : if ( m_pToolbar )
151 : {
152 236 : m_pToolbar->EnableItem( m_nID, Event.IsEnabled );
153 :
154 236 : sal_uInt16 nItemBits = m_pToolbar->GetItemBits( m_nID );
155 236 : nItemBits &= ~TIB_CHECKABLE;
156 236 : TriState eTri = STATE_NOCHECK;
157 :
158 236 : sal_Bool bValue = sal_Bool();
159 236 : rtl::OUString aStrValue;
160 236 : ItemStatus aItemState;
161 236 : Visibility aItemVisibility;
162 236 : ControlCommand aControlCommand;
163 :
164 236 : if ( Event.State >>= bValue )
165 : {
166 : // Boolean, treat it as checked/unchecked
167 0 : if ( m_bMadeInvisible )
168 0 : m_pToolbar->ShowItem( m_nID, sal_True );
169 0 : m_pToolbar->CheckItem( m_nID, bValue );
170 0 : if ( bValue )
171 0 : eTri = STATE_CHECK;
172 0 : nItemBits |= TIB_CHECKABLE;
173 : }
174 236 : else if ( Event.State >>= aStrValue )
175 : {
176 0 : ::rtl::OUString aText( MnemonicGenerator::EraseAllMnemonicChars( aStrValue ) );
177 0 : m_pToolbar->SetItemText( m_nID, aText );
178 0 : m_pToolbar->SetQuickHelpText( m_nID, aText );
179 :
180 0 : if ( m_bMadeInvisible )
181 0 : m_pToolbar->ShowItem( m_nID, sal_True );
182 : }
183 236 : else if ( Event.State >>= aItemState )
184 : {
185 0 : eTri = STATE_DONTKNOW;
186 0 : nItemBits |= TIB_CHECKABLE;
187 0 : if ( m_bMadeInvisible )
188 0 : m_pToolbar->ShowItem( m_nID, sal_True );
189 : }
190 236 : else if ( Event.State >>= aItemVisibility )
191 : {
192 0 : m_pToolbar->ShowItem( m_nID, aItemVisibility.bVisible );
193 0 : m_bMadeInvisible = !aItemVisibility.bVisible;
194 : }
195 236 : else if ( Event.State >>= aControlCommand )
196 : {
197 0 : executeControlCommand( aControlCommand );
198 0 : if ( m_bMadeInvisible )
199 0 : m_pToolbar->ShowItem( m_nID, sal_True );
200 : }
201 :
202 236 : else if ( m_bMadeInvisible )
203 0 : m_pToolbar->ShowItem( m_nID, sal_True );
204 :
205 236 : m_pToolbar->SetItemState( m_nID, eTri );
206 236 : m_pToolbar->SetItemBits( m_nID, nItemBits );
207 236 : }
208 : }
209 :
210 : // ------------------------------------------------------------------
211 :
212 0 : IMPL_STATIC_LINK_NOINSTANCE( ComplexToolbarController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
213 : {
214 0 : const sal_uInt32 nRef = Application::ReleaseSolarMutex();
215 : try
216 : {
217 : // Asynchronous execution as this can lead to our own destruction!
218 : // Framework can recycle our current frame and the layout manager disposes all user interface
219 : // elements if a component gets detached from its frame!
220 0 : pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
221 : }
222 0 : catch ( const Exception& )
223 : {
224 : }
225 :
226 0 : Application::AcquireSolarMutex( nRef );
227 0 : delete pExecuteInfo;
228 0 : return 0;
229 : }
230 :
231 : // ------------------------------------------------------------------
232 :
233 0 : IMPL_STATIC_LINK_NOINSTANCE( ComplexToolbarController, Notify_Impl, NotifyInfo*, pNotifyInfo )
234 : {
235 0 : const sal_uInt32 nRef = Application::ReleaseSolarMutex();
236 : try
237 : {
238 : // Asynchronous execution: As this can lead to our own destruction!
239 : // Framework can recycle our current frame and the layout manager disposes all user interface
240 : // elements if a component gets detached from its frame!
241 0 : frame::ControlEvent aEvent;
242 0 : aEvent.aURL = pNotifyInfo->aSourceURL;
243 0 : aEvent.Event = pNotifyInfo->aEventName;
244 0 : aEvent.aInformation = pNotifyInfo->aInfoSeq;
245 0 : pNotifyInfo->xNotifyListener->controlEvent( aEvent );
246 : }
247 0 : catch ( const Exception& )
248 : {
249 : }
250 :
251 0 : Application::AcquireSolarMutex( nRef );
252 0 : delete pNotifyInfo;
253 0 : return 0;
254 : }
255 :
256 : // ------------------------------------------------------------------
257 :
258 0 : void ComplexToolbarController::addNotifyInfo(
259 : const rtl::OUString& aEventName,
260 : const uno::Reference< frame::XDispatch >& xDispatch,
261 : const uno::Sequence< beans::NamedValue >& rInfo )
262 : {
263 0 : uno::Reference< frame::XControlNotificationListener > xControlNotify( xDispatch, uno::UNO_QUERY );
264 :
265 0 : if ( xControlNotify.is() )
266 : {
267 : // Execute notification asynchronously
268 0 : NotifyInfo* pNotifyInfo = new NotifyInfo;
269 :
270 0 : pNotifyInfo->aEventName = aEventName;
271 0 : pNotifyInfo->xNotifyListener = xControlNotify;
272 0 : pNotifyInfo->aSourceURL = getInitializedURL();
273 :
274 : // Add frame as source to the information sequence
275 0 : sal_Int32 nCount = rInfo.getLength();
276 0 : uno::Sequence< beans::NamedValue > aInfoSeq( rInfo );
277 0 : aInfoSeq.realloc( nCount+1 );
278 0 : aInfoSeq[nCount].Name = ::rtl::OUString( "Source" );
279 0 : aInfoSeq[nCount].Value = uno::makeAny( getFrameInterface() );
280 0 : pNotifyInfo->aInfoSeq = aInfoSeq;
281 :
282 0 : Application::PostUserEvent( STATIC_LINK(0, ComplexToolbarController, Notify_Impl), pNotifyInfo );
283 0 : }
284 0 : }
285 :
286 : // --------------------------------------------------------
287 236 : sal_Int32 ComplexToolbarController::getFontSizePixel( const Window* pWindow )
288 : {
289 236 : const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
290 236 : const Font& rFont = rSettings.GetAppFont();
291 :
292 : // Calculate height of the application font used by window
293 236 : sal_Int32 nHeight = sal_Int32( rFont.GetHeight() );
294 236 : ::Size aPixelSize = pWindow->LogicToPixel( ::Size( 0, nHeight ), MAP_APPFONT );
295 236 : return aPixelSize.Height();
296 : }
297 :
298 : // --------------------------------------------------------
299 :
300 0 : uno::Reference< frame::XDispatch > ComplexToolbarController::getDispatchFromCommand( const rtl::OUString& aCommand ) const
301 : {
302 0 : uno::Reference< frame::XDispatch > xDispatch;
303 :
304 0 : if ( m_bInitialized && m_xFrame.is() && m_xServiceManager.is() && !aCommand.isEmpty() )
305 : {
306 0 : URLToDispatchMap::const_iterator pIter = m_aListenerMap.find( aCommand );
307 0 : if ( pIter != m_aListenerMap.end() )
308 0 : xDispatch = pIter->second;
309 : }
310 :
311 0 : return xDispatch;
312 : }
313 :
314 : // --------------------------------------------------------
315 :
316 0 : const ::com::sun::star::util::URL& ComplexToolbarController::getInitializedURL()
317 : {
318 0 : if ( m_aURL.Complete.isEmpty() )
319 : {
320 0 : m_aURL.Complete = m_aCommandURL;
321 0 : m_xURLTransformer->parseStrict( m_aURL );
322 : }
323 0 : return m_aURL;
324 : }
325 :
326 0 : void ComplexToolbarController::notifyFocusGet()
327 : {
328 : // send focus get notification
329 0 : uno::Sequence< beans::NamedValue > aInfo;
330 : addNotifyInfo( rtl::OUString( "FocusSet" ),
331 : getDispatchFromCommand( m_aCommandURL ),
332 0 : aInfo );
333 0 : }
334 :
335 0 : void ComplexToolbarController::notifyFocusLost()
336 : {
337 : // send focus lost notification
338 0 : uno::Sequence< beans::NamedValue > aInfo;
339 : addNotifyInfo( rtl::OUString( "FocusLost" ),
340 : getDispatchFromCommand( m_aCommandURL ),
341 0 : aInfo );
342 0 : }
343 :
344 0 : void ComplexToolbarController::notifyTextChanged( const ::rtl::OUString& aText )
345 : {
346 : // send text changed notification
347 0 : uno::Sequence< beans::NamedValue > aInfo( 1 );
348 0 : aInfo[0].Name = rtl::OUString( "Text" );
349 0 : aInfo[0].Value <<= aText;
350 : addNotifyInfo( rtl::OUString( "TextChanged" ),
351 : getDispatchFromCommand( m_aCommandURL ),
352 0 : aInfo );
353 0 : }
354 :
355 : } // namespace
356 :
357 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|