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/generictoolbarcontroller.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 :
34 : #include <comphelper/processfactory.hxx>
35 : #include <svtools/toolboxcontroller.hxx>
36 : #include <osl/mutex.hxx>
37 : #include <vcl/svapp.hxx>
38 : #include <vcl/mnemonic.hxx>
39 : #include <tools/urlobj.hxx>
40 : #include <classes/resource.hrc>
41 : #include <classes/fwkresid.hxx>
42 : #include <framework/menuconfiguration.hxx>
43 : #include <uielement/menubarmanager.hxx>
44 :
45 : using namespace ::com::sun::star::awt;
46 : using namespace ::com::sun::star::uno;
47 : using namespace ::com::sun::star::beans;
48 : using namespace ::com::sun::star::lang;
49 : using namespace ::com::sun::star::frame;
50 : using namespace ::com::sun::star::frame::status;
51 : using namespace ::com::sun::star::util;
52 : using namespace ::com::sun::star::container;
53 :
54 : namespace framework
55 : {
56 :
57 2124 : static sal_Bool isEnumCommand( const rtl::OUString& rCommand )
58 : {
59 2124 : INetURLObject aURL( rCommand );
60 :
61 4248 : if (( aURL.GetProtocol() == INET_PROT_UNO ) &&
62 2124 : ( aURL.GetURLPath().indexOf( '.' ) != -1))
63 0 : return sal_True;
64 :
65 2124 : return sal_False;
66 : }
67 :
68 2124 : static rtl::OUString getEnumCommand( const rtl::OUString& rCommand )
69 : {
70 2124 : INetURLObject aURL( rCommand );
71 :
72 2124 : rtl::OUString aEnumCommand;
73 2124 : String aURLPath = aURL.GetURLPath();
74 2124 : xub_StrLen nIndex = aURLPath.Search( '.' );
75 2124 : if (( nIndex > 0 ) && ( nIndex < aURLPath.Len() ))
76 2124 : aEnumCommand = aURLPath.Copy( nIndex+1 );
77 :
78 2124 : return aEnumCommand;
79 : }
80 :
81 0 : static rtl::OUString getMasterCommand( const rtl::OUString& rCommand )
82 : {
83 0 : rtl::OUString aMasterCommand( rCommand );
84 0 : INetURLObject aURL( rCommand );
85 0 : if ( aURL.GetProtocol() == INET_PROT_UNO )
86 : {
87 0 : sal_Int32 nIndex = aURL.GetURLPath().indexOf( '.' );
88 0 : if ( nIndex )
89 : {
90 0 : aURL.SetURLPath( aURL.GetURLPath().copy( 0, nIndex ) );
91 0 : aMasterCommand = aURL.GetMainURL( INetURLObject::NO_DECODE );
92 : }
93 : }
94 0 : return aMasterCommand;
95 : }
96 :
97 0 : struct ExecuteInfo
98 : {
99 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDispatch;
100 : ::com::sun::star::util::URL aTargetURL;
101 : ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs;
102 : };
103 :
104 2124 : GenericToolbarController::GenericToolbarController( const Reference< XMultiServiceFactory >& rServiceManager,
105 : const Reference< XFrame >& rFrame,
106 : ToolBox* pToolbar,
107 : sal_uInt16 nID,
108 : const ::rtl::OUString& aCommand ) :
109 : svt::ToolboxController( rServiceManager, rFrame, aCommand )
110 : , m_pToolbar( pToolbar )
111 : , m_nID( nID )
112 2124 : , m_bEnumCommand( isEnumCommand( aCommand ))
113 : , m_bMadeInvisible( sal_False )
114 4248 : , m_aEnumCommand( getEnumCommand( aCommand ))
115 : {
116 2124 : if ( m_bEnumCommand )
117 0 : addStatusListener( getMasterCommand( aCommand ) );
118 2124 : }
119 :
120 1134 : GenericToolbarController::~GenericToolbarController()
121 : {
122 1134 : }
123 :
124 567 : void SAL_CALL GenericToolbarController::dispose()
125 : throw ( RuntimeException )
126 : {
127 567 : SolarMutexGuard aSolarMutexGuard;
128 :
129 567 : svt::ToolboxController::dispose();
130 :
131 567 : m_pToolbar = 0;
132 567 : m_nID = 0;
133 567 : }
134 :
135 0 : void SAL_CALL GenericToolbarController::execute( sal_Int16 KeyModifier )
136 : throw ( RuntimeException )
137 : {
138 0 : Reference< XDispatch > xDispatch;
139 0 : Reference< XURLTransformer > xURLTransformer;
140 0 : ::rtl::OUString aCommandURL;
141 :
142 : {
143 0 : SolarMutexGuard aSolarMutexGuard;
144 :
145 0 : if ( m_bDisposed )
146 0 : throw DisposedException();
147 :
148 0 : if ( m_bInitialized &&
149 0 : m_xFrame.is() &&
150 0 : m_xServiceManager.is() &&
151 0 : !m_aCommandURL.isEmpty() )
152 : {
153 0 : xURLTransformer = URLTransformer::create(::comphelper::getComponentContext(m_xServiceManager));
154 :
155 0 : aCommandURL = m_aCommandURL;
156 0 : URLToDispatchMap::iterator pIter = m_aListenerMap.find( m_aCommandURL );
157 0 : if ( pIter != m_aListenerMap.end() )
158 0 : xDispatch = pIter->second;
159 0 : }
160 : }
161 :
162 0 : if ( xDispatch.is() && xURLTransformer.is() )
163 : {
164 0 : com::sun::star::util::URL aTargetURL;
165 0 : Sequence<PropertyValue> aArgs( 1 );
166 :
167 : // Add key modifier to argument list
168 0 : aArgs[0].Name = rtl::OUString( "KeyModifier" );
169 0 : aArgs[0].Value <<= KeyModifier;
170 :
171 0 : aTargetURL.Complete = aCommandURL;
172 0 : xURLTransformer->parseStrict( aTargetURL );
173 :
174 : // Execute dispatch asynchronously
175 0 : ExecuteInfo* pExecuteInfo = new ExecuteInfo;
176 0 : pExecuteInfo->xDispatch = xDispatch;
177 0 : pExecuteInfo->aTargetURL = aTargetURL;
178 0 : pExecuteInfo->aArgs = aArgs;
179 0 : Application::PostUserEvent( STATIC_LINK(0, GenericToolbarController , ExecuteHdl_Impl), pExecuteInfo );
180 0 : }
181 0 : }
182 :
183 2124 : void GenericToolbarController::statusChanged( const FeatureStateEvent& Event )
184 : throw ( RuntimeException )
185 : {
186 2124 : SolarMutexGuard aSolarMutexGuard;
187 :
188 2124 : if ( m_bDisposed )
189 2124 : return;
190 :
191 2124 : if ( m_pToolbar )
192 : {
193 2124 : m_pToolbar->EnableItem( m_nID, Event.IsEnabled );
194 :
195 2124 : sal_uInt16 nItemBits = m_pToolbar->GetItemBits( m_nID );
196 2124 : nItemBits &= ~TIB_CHECKABLE;
197 2124 : TriState eTri = STATE_NOCHECK;
198 :
199 2124 : sal_Bool bValue = sal_Bool();
200 2124 : rtl::OUString aStrValue;
201 2124 : ItemStatus aItemState;
202 2124 : Visibility aItemVisibility;
203 :
204 2124 : if (( Event.State >>= bValue ) && !m_bEnumCommand )
205 : {
206 : // Boolean, treat it as checked/unchecked
207 0 : if ( m_bMadeInvisible )
208 0 : m_pToolbar->ShowItem( m_nID, sal_True );
209 0 : m_pToolbar->CheckItem( m_nID, bValue );
210 0 : if ( bValue )
211 0 : eTri = STATE_CHECK;
212 0 : nItemBits |= TIB_CHECKABLE;
213 : }
214 2124 : else if ( Event.State >>= aStrValue )
215 : {
216 0 : if ( m_bEnumCommand )
217 : {
218 0 : if ( aStrValue == m_aEnumCommand )
219 0 : bValue = sal_True;
220 : else
221 0 : bValue = sal_False;
222 :
223 0 : m_pToolbar->CheckItem( m_nID, bValue );
224 0 : if ( bValue )
225 0 : eTri = STATE_CHECK;
226 0 : nItemBits |= TIB_CHECKABLE;
227 : }
228 : else
229 : {
230 : // Replacement for place holders
231 0 : if ( aStrValue.matchAsciiL( "($1)", 4 ))
232 : {
233 0 : String aResStr = String( FwkResId( STR_UPDATEDOC ));
234 0 : rtl::OUString aTmp( aResStr );
235 0 : aTmp += rtl::OUString( " " );
236 0 : aTmp += aStrValue.copy( 4 );
237 0 : aStrValue = aTmp;
238 : }
239 0 : else if ( aStrValue.matchAsciiL( "($2)", 4 ))
240 : {
241 0 : String aResStr = String( FwkResId( STR_CLOSEDOC_ANDRETURN ));
242 0 : rtl::OUString aTmp( aResStr );
243 0 : aTmp += aStrValue.copy( 4 );
244 0 : aStrValue = aTmp;
245 : }
246 0 : else if ( aStrValue.matchAsciiL( "($3)", 4 ))
247 : {
248 0 : String aResStr = String( FwkResId( STR_SAVECOPYDOC ));
249 0 : rtl::OUString aTmp( aResStr );
250 0 : aTmp += aStrValue.copy( 4 );
251 0 : aStrValue = aTmp;
252 : }
253 0 : ::rtl::OUString aText( MnemonicGenerator::EraseAllMnemonicChars( aStrValue ) );
254 0 : m_pToolbar->SetItemText( m_nID, aText );
255 0 : m_pToolbar->SetQuickHelpText( m_nID, aText );
256 : }
257 :
258 0 : if ( m_bMadeInvisible )
259 0 : m_pToolbar->ShowItem( m_nID, sal_True );
260 : }
261 2124 : else if (( Event.State >>= aItemState ) && !m_bEnumCommand )
262 : {
263 0 : eTri = STATE_DONTKNOW;
264 0 : nItemBits |= TIB_CHECKABLE;
265 0 : if ( m_bMadeInvisible )
266 0 : m_pToolbar->ShowItem( m_nID, sal_True );
267 : }
268 2124 : else if ( Event.State >>= aItemVisibility )
269 : {
270 0 : m_pToolbar->ShowItem( m_nID, aItemVisibility.bVisible );
271 0 : m_bMadeInvisible = !aItemVisibility.bVisible;
272 : }
273 2124 : else if ( m_bMadeInvisible )
274 0 : m_pToolbar->ShowItem( m_nID, sal_True );
275 :
276 2124 : m_pToolbar->SetItemState( m_nID, eTri );
277 2124 : m_pToolbar->SetItemBits( m_nID, nItemBits );
278 2124 : }
279 : }
280 :
281 0 : IMPL_STATIC_LINK_NOINSTANCE( GenericToolbarController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
282 : {
283 0 : const sal_uInt32 nRef = Application::ReleaseSolarMutex();
284 : try
285 : {
286 : // Asynchronous execution as this can lead to our own destruction!
287 : // Framework can recycle our current frame and the layout manager disposes all user interface
288 : // elements if a component gets detached from its frame!
289 0 : pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
290 : }
291 0 : catch ( const Exception& )
292 : {
293 : }
294 :
295 0 : Application::AcquireSolarMutex( nRef );
296 0 : delete pExecuteInfo;
297 0 : return 0;
298 : }
299 :
300 0 : MenuToolbarController::MenuToolbarController( const Reference< XMultiServiceFactory >& rServiceManager, const Reference< XFrame >& rFrame, ToolBox* pToolBar, sal_uInt16 nID, const rtl::OUString& aCommand, const rtl::OUString& aModuleIdentifier, const Reference< XIndexAccess >& xMenuDesc ) : GenericToolbarController( rServiceManager, rFrame, pToolBar, nID, aCommand ), m_xMenuDesc( xMenuDesc ), pMenu( NULL ), m_aModuleIdentifier( aModuleIdentifier )
301 : {
302 0 : }
303 :
304 0 : MenuToolbarController::~MenuToolbarController()
305 : {
306 : try
307 : {
308 0 : if ( m_xMenuManager.is() )
309 0 : m_xMenuManager->dispose();
310 : }
311 0 : catch( const Exception& ) {}
312 0 : if ( pMenu )
313 : {
314 0 : delete pMenu;
315 0 : pMenu = NULL;
316 : }
317 :
318 0 : }
319 :
320 : class Toolbarmenu : public PopupMenu
321 : {
322 : public:
323 : Toolbarmenu();
324 : ~Toolbarmenu();
325 : };
326 :
327 0 : Toolbarmenu::Toolbarmenu()
328 : {
329 : OSL_TRACE("**** contstructing Toolbarmenu 0x%x", this );
330 0 : }
331 :
332 0 : Toolbarmenu::~Toolbarmenu()
333 : {
334 : OSL_TRACE("**** destructing Toolbarmenu 0x%x", this );
335 0 : }
336 :
337 0 : void SAL_CALL MenuToolbarController::click() throw (RuntimeException)
338 : {
339 0 : createPopupWindow();
340 0 : }
341 :
342 : Reference< XWindow > SAL_CALL
343 0 : MenuToolbarController::createPopupWindow() throw (::com::sun::star::uno::RuntimeException)
344 : {
345 0 : if ( !pMenu )
346 : {
347 0 : Reference< XDispatchProvider > xDispatch;
348 0 : Reference< XURLTransformer > xURLTransformer = URLTransformer::create(::comphelper::getComponentContext(m_xServiceManager));
349 0 : pMenu = new Toolbarmenu();
350 0 : m_xMenuManager.set( new MenuBarManager( m_xServiceManager, m_xFrame, xURLTransformer, xDispatch, m_aModuleIdentifier, pMenu, sal_True, sal_True ) );
351 0 : if ( m_xMenuManager.is() )
352 : {
353 0 : MenuBarManager* pMgr = dynamic_cast< MenuBarManager* >( m_xMenuManager.get() );
354 0 : pMgr->SetItemContainer( m_xMenuDesc );
355 0 : }
356 : }
357 :
358 0 : ::Rectangle aRect( m_pToolbar->GetItemRect( m_nID ) );
359 0 : pMenu->Execute( m_pToolbar, aRect, POPUPMENU_EXECUTE_DOWN );
360 0 : return NULL;
361 : }
362 : } // namespace
363 :
364 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|