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