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