xref: /trunk/main/framework/source/uielement/complextoolbarcontroller.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 {
103     vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
104 
105     m_pToolbar->SetItemWindow( m_nID, 0 );
106     svt::ToolboxController::dispose();
107 
108     m_xURLTransformer.clear();
109     m_pToolbar = 0;
110     m_nID = 0;
111 }
112 
113 // ------------------------------------------------------------------
getExecuteArgs(sal_Int16 KeyModifier) const114 Sequence<PropertyValue> ComplexToolbarController::getExecuteArgs(sal_Int16 KeyModifier) const
115 {
116     Sequence<PropertyValue> aArgs( 1 );
117 
118     // Add key modifier to argument list
119     aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "KeyModifier" ));
120     aArgs[0].Value <<= KeyModifier;
121     return aArgs;
122 }
123 // -----------------------------------------------------------------------------
execute(sal_Int16 KeyModifier)124 void SAL_CALL ComplexToolbarController::execute( sal_Int16 KeyModifier )
125 {
126     Reference< XDispatch >       xDispatch;
127     Reference< XURLTransformer > xURLTransformer;
128     ::rtl::OUString                     aCommandURL;
129     ::com::sun::star::util::URL  aTargetURL;
130     Sequence<PropertyValue> aArgs;
131 
132     {
133         vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
134 
135         if ( m_bDisposed )
136             throw DisposedException();
137 
138         if ( m_bInitialized &&
139              m_xFrame.is() &&
140              m_xServiceManager.is() &&
141              m_aCommandURL.getLength() )
142         {
143             xURLTransformer = m_xURLTransformer;
144             xDispatch = getDispatchFromCommand( m_aCommandURL );
145             aCommandURL = m_aCommandURL;
146             aTargetURL = getInitializedURL();
147             aArgs = getExecuteArgs(KeyModifier);
148         }
149     }
150 
151     if ( xDispatch.is() && aTargetURL.Complete.getLength() > 0 )
152     {
153         // Execute dispatch asynchronously
154         ExecuteInfo* pExecuteInfo = new ExecuteInfo;
155         pExecuteInfo->xDispatch     = xDispatch;
156         pExecuteInfo->aTargetURL    = aTargetURL;
157         pExecuteInfo->aArgs         = aArgs;
158         if(::comphelper::UiEventsLogger::isEnabled()) //#i88653#
159             UiEventLogHelper(::rtl::OUString::createFromAscii("ComplexToolbarController")).log(
160                 m_xServiceManager,
161                 m_xFrame,
162                 aTargetURL,
163                 aArgs);
164         Application::PostUserEvent( STATIC_LINK(0, ComplexToolbarController , ExecuteHdl_Impl), pExecuteInfo );
165     }
166 }
167 
168 // ------------------------------------------------------------------
169 
statusChanged(const FeatureStateEvent & Event)170 void ComplexToolbarController::statusChanged( const FeatureStateEvent& Event )
171 {
172     vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() );
173 
174     if ( m_bDisposed )
175         return;
176 
177     if ( m_pToolbar )
178     {
179         m_pToolbar->EnableItem( m_nID, Event.IsEnabled );
180 
181         sal_uInt16 nItemBits = m_pToolbar->GetItemBits( m_nID );
182         nItemBits &= ~TIB_CHECKABLE;
183         TriState eTri = STATE_NOCHECK;
184 
185         sal_Bool        bValue = sal_Bool();
186         rtl::OUString   aStrValue;
187         ItemStatus      aItemState;
188         Visibility      aItemVisibility;
189         ControlCommand  aControlCommand;
190 
191         if ( Event.State >>= bValue )
192         {
193             // Boolean, treat it as checked/unchecked
194             if ( m_bMadeInvisible )
195                 m_pToolbar->ShowItem( m_nID, sal_True );
196             m_pToolbar->CheckItem( m_nID, bValue );
197             if ( bValue )
198                 eTri = STATE_CHECK;
199             nItemBits |= TIB_CHECKABLE;
200         }
201         else if ( Event.State >>= aStrValue )
202         {
203             ::rtl::OUString aText( MnemonicGenerator::EraseAllMnemonicChars( aStrValue ) );
204             m_pToolbar->SetItemText( m_nID, aText );
205             m_pToolbar->SetQuickHelpText( m_nID, aText );
206 
207             if ( m_bMadeInvisible )
208                 m_pToolbar->ShowItem( m_nID, sal_True );
209         }
210         else if ( Event.State >>= aItemState )
211         {
212             eTri = STATE_DONTKNOW;
213             nItemBits |= TIB_CHECKABLE;
214             if ( m_bMadeInvisible )
215                 m_pToolbar->ShowItem( m_nID, sal_True );
216         }
217         else if ( Event.State >>= aItemVisibility )
218         {
219             m_pToolbar->ShowItem( m_nID, aItemVisibility.bVisible );
220             m_bMadeInvisible = !aItemVisibility.bVisible;
221         }
222         else if ( Event.State >>= aControlCommand )
223         {
224             executeControlCommand( aControlCommand );
225             if ( m_bMadeInvisible )
226                 m_pToolbar->ShowItem( m_nID, sal_True );
227         }
228 
229         else if ( m_bMadeInvisible )
230             m_pToolbar->ShowItem( m_nID, sal_True );
231 
232         m_pToolbar->SetItemState( m_nID, eTri );
233         m_pToolbar->SetItemBits( m_nID, nItemBits );
234     }
235 }
236 
237 // ------------------------------------------------------------------
238 
IMPL_STATIC_LINK_NOINSTANCE(ComplexToolbarController,ExecuteHdl_Impl,ExecuteInfo *,pExecuteInfo)239 IMPL_STATIC_LINK_NOINSTANCE( ComplexToolbarController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
240 {
241    const sal_uInt32 nRef = Application::ReleaseSolarMutex();
242    try
243    {
244        // Asynchronous execution as this can lead to our own destruction!
245        // Framework can recycle our current frame and the layout manager disposes all user interface
246        // elements if a component gets detached from its frame!
247        pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
248    }
249    catch ( Exception& )
250    {
251    }
252 
253    Application::AcquireSolarMutex( nRef );
254    delete pExecuteInfo;
255    return 0;
256 }
257 
258 // ------------------------------------------------------------------
259 
IMPL_STATIC_LINK_NOINSTANCE(ComplexToolbarController,Notify_Impl,NotifyInfo *,pNotifyInfo)260 IMPL_STATIC_LINK_NOINSTANCE( ComplexToolbarController, Notify_Impl, NotifyInfo*, pNotifyInfo )
261 {
262    const sal_uInt32 nRef = Application::ReleaseSolarMutex();
263    try
264    {
265        // Asynchronous execution: As this can lead to our own destruction!
266        // Framework can recycle our current frame and the layout manager disposes all user interface
267        // elements if a component gets detached from its frame!
268        frame::ControlEvent aEvent;
269        aEvent.aURL  = pNotifyInfo->aSourceURL;
270        aEvent.Event = pNotifyInfo->aEventName;
271        aEvent.aInformation = pNotifyInfo->aInfoSeq;
272        pNotifyInfo->xNotifyListener->controlEvent( aEvent );
273    }
274    catch ( Exception& )
275    {
276    }
277 
278    Application::AcquireSolarMutex( nRef );
279    delete pNotifyInfo;
280    return 0;
281 }
282 
283 // ------------------------------------------------------------------
284 
addNotifyInfo(const rtl::OUString & aEventName,const uno::Reference<frame::XDispatch> & xDispatch,const uno::Sequence<beans::NamedValue> & rInfo)285 void ComplexToolbarController::addNotifyInfo(
286     const rtl::OUString&                      aEventName,
287     const uno::Reference< frame::XDispatch >& xDispatch,
288     const uno::Sequence< beans::NamedValue >& rInfo )
289 {
290     uno::Reference< frame::XControlNotificationListener > xControlNotify( xDispatch, uno::UNO_QUERY );
291 
292     if ( xControlNotify.is() )
293     {
294         // Execute notification asynchronously
295         NotifyInfo* pNotifyInfo = new NotifyInfo;
296 
297         pNotifyInfo->aEventName      = aEventName;
298         pNotifyInfo->xNotifyListener = xControlNotify;
299         pNotifyInfo->aSourceURL      = getInitializedURL();
300 
301         // Add frame as source to the information sequence
302         sal_Int32 nCount = rInfo.getLength();
303         uno::Sequence< beans::NamedValue > aInfoSeq( rInfo );
304         aInfoSeq.realloc( nCount+1 );
305         aInfoSeq[nCount].Name  = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Source" ));
306         aInfoSeq[nCount].Value = uno::makeAny( getFrameInterface() );
307         pNotifyInfo->aInfoSeq  = aInfoSeq;
308 
309         Application::PostUserEvent( STATIC_LINK(0, ComplexToolbarController, Notify_Impl), pNotifyInfo );
310     }
311 }
312 
313 // --------------------------------------------------------
getFontSizePixel(const Window * pWindow)314 sal_Int32 ComplexToolbarController::getFontSizePixel( const Window* pWindow )
315 {
316     const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
317     const Font&          rFont     = rSettings.GetAppFont();
318 
319     // Calculate height of the application font used by window
320     sal_Int32 nHeight = sal_Int32( rFont.GetHeight() );
321     ::Size aPixelSize = pWindow->LogicToPixel( ::Size( 0, nHeight ), MAP_APPFONT );
322     return aPixelSize.Height();
323 }
324 
325 // --------------------------------------------------------
326 
getDispatchFromCommand(const rtl::OUString & aCommand) const327 uno::Reference< frame::XDispatch > ComplexToolbarController::getDispatchFromCommand( const rtl::OUString& aCommand ) const
328 {
329     uno::Reference< frame::XDispatch > xDispatch;
330 
331     if ( m_bInitialized && m_xFrame.is() && m_xServiceManager.is() && aCommand.getLength() )
332     {
333         URLToDispatchMap::const_iterator pIter = m_aListenerMap.find( aCommand );
334         if ( pIter != m_aListenerMap.end() )
335             xDispatch = pIter->second;
336     }
337 
338     return xDispatch;
339 }
340 
341 // --------------------------------------------------------
342 
getInitializedURL()343 const ::com::sun::star::util::URL& ComplexToolbarController::getInitializedURL()
344 {
345     if ( m_aURL.Complete.getLength() == 0 )
346     {
347         m_aURL.Complete = m_aCommandURL;
348         m_xURLTransformer->parseStrict( m_aURL );
349     }
350     return m_aURL;
351 }
352 
notifyFocusGet()353 void ComplexToolbarController::notifyFocusGet()
354 {
355     // send focus get notification
356     uno::Sequence< beans::NamedValue > aInfo;
357     addNotifyInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FocusSet" )),
358                     getDispatchFromCommand( m_aCommandURL ),
359                     aInfo );
360 }
361 
notifyFocusLost()362 void ComplexToolbarController::notifyFocusLost()
363 {
364     // send focus lost notification
365     uno::Sequence< beans::NamedValue > aInfo;
366     addNotifyInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FocusLost" )),
367                     getDispatchFromCommand( m_aCommandURL ),
368                     aInfo );
369 }
370 
notifyTextChanged(const::rtl::OUString & aText)371 void ComplexToolbarController::notifyTextChanged( const ::rtl::OUString& aText )
372 {
373     // send text changed notification
374     uno::Sequence< beans::NamedValue > aInfo( 1 );
375     aInfo[0].Name  = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" ));
376     aInfo[0].Value <<= aText;
377     addNotifyInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TextChanged" )),
378                    getDispatchFromCommand( m_aCommandURL ),
379                    aInfo );
380 }
381 
382 } // namespace
383