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 110854 : static bool isEnumCommand( const OUString& rCommand )
55 : {
56 110854 : INetURLObject aURL( rCommand );
57 :
58 401062 : if (( aURL.GetProtocol() == INET_PROT_UNO ) &&
59 316354 : ( aURL.GetURLPath().indexOf( '.' ) != -1))
60 252 : return true;
61 :
62 110602 : return false;
63 : }
64 :
65 110854 : static OUString getEnumCommand( const OUString& rCommand )
66 : {
67 110854 : INetURLObject aURL( rCommand );
68 :
69 110854 : OUString aEnumCommand;
70 221708 : OUString aURLPath = aURL.GetURLPath();
71 110854 : sal_Int32 nIndex = aURLPath.indexOf( '.' );
72 110854 : if (( nIndex > 0 ) && ( nIndex < aURLPath.getLength() ))
73 42606 : aEnumCommand = aURLPath.copy( nIndex+1 );
74 :
75 221708 : return aEnumCommand;
76 : }
77 :
78 252 : static OUString getMasterCommand( const OUString& rCommand )
79 : {
80 252 : OUString aMasterCommand( rCommand );
81 504 : INetURLObject aURL( rCommand );
82 252 : if ( aURL.GetProtocol() == INET_PROT_UNO )
83 : {
84 252 : sal_Int32 nIndex = aURL.GetURLPath().indexOf( '.' );
85 252 : if ( nIndex )
86 : {
87 252 : aURL.SetURLPath( aURL.GetURLPath().copy( 0, nIndex ) );
88 252 : aMasterCommand = aURL.GetMainURL( INetURLObject::NO_DECODE );
89 : }
90 : }
91 504 : 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 110854 : 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 110854 : , m_bEnumCommand( isEnumCommand( aCommand ))
110 : , m_bMadeInvisible( false )
111 221708 : , m_aEnumCommand( getEnumCommand( aCommand ))
112 : {
113 110854 : if ( m_bEnumCommand )
114 252 : addStatusListener( getMasterCommand( aCommand ) );
115 110854 : }
116 :
117 221672 : GenericToolbarController::~GenericToolbarController()
118 : {
119 221672 : }
120 :
121 110836 : void SAL_CALL GenericToolbarController::dispose()
122 : throw ( RuntimeException, std::exception )
123 : {
124 110836 : SolarMutexGuard aSolarMutexGuard;
125 :
126 110836 : svt::ToolboxController::dispose();
127 :
128 110836 : m_pToolbar = 0;
129 110836 : m_nID = 0;
130 110836 : }
131 :
132 4 : void SAL_CALL GenericToolbarController::execute( sal_Int16 KeyModifier )
133 : throw ( RuntimeException, std::exception )
134 : {
135 4 : Reference< XDispatch > xDispatch;
136 8 : Reference< XURLTransformer > xURLTransformer;
137 8 : OUString aCommandURL;
138 :
139 : {
140 4 : SolarMutexGuard aSolarMutexGuard;
141 :
142 4 : if ( m_bDisposed )
143 0 : throw DisposedException();
144 :
145 8 : if ( m_bInitialized &&
146 8 : m_xFrame.is() &&
147 4 : !m_aCommandURL.isEmpty() )
148 : {
149 4 : xURLTransformer = URLTransformer::create(m_xContext);
150 :
151 4 : aCommandURL = m_aCommandURL;
152 4 : URLToDispatchMap::iterator pIter = m_aListenerMap.find( m_aCommandURL );
153 4 : if ( pIter != m_aListenerMap.end() )
154 4 : xDispatch = pIter->second;
155 4 : }
156 : }
157 :
158 4 : if ( xDispatch.is() && xURLTransformer.is() )
159 : {
160 4 : com::sun::star::util::URL aTargetURL;
161 8 : Sequence<PropertyValue> aArgs( 1 );
162 :
163 : // Add key modifier to argument list
164 4 : aArgs[0].Name = "KeyModifier";
165 4 : aArgs[0].Value <<= KeyModifier;
166 :
167 4 : aTargetURL.Complete = aCommandURL;
168 4 : xURLTransformer->parseStrict( aTargetURL );
169 :
170 : // Execute dispatch asynchronously
171 4 : ExecuteInfo* pExecuteInfo = new ExecuteInfo;
172 4 : pExecuteInfo->xDispatch = xDispatch;
173 4 : pExecuteInfo->aTargetURL = aTargetURL;
174 4 : pExecuteInfo->aArgs = aArgs;
175 8 : Application::PostUserEvent( STATIC_LINK(0, GenericToolbarController , ExecuteHdl_Impl), pExecuteInfo );
176 4 : }
177 4 : }
178 :
179 114480 : void GenericToolbarController::statusChanged( const FeatureStateEvent& Event )
180 : throw ( RuntimeException, std::exception )
181 : {
182 114480 : SolarMutexGuard aSolarMutexGuard;
183 :
184 114480 : if ( m_bDisposed )
185 114480 : return;
186 :
187 114480 : if ( m_pToolbar )
188 : {
189 114480 : m_pToolbar->EnableItem( m_nID, Event.IsEnabled );
190 :
191 114480 : ToolBoxItemBits nItemBits = m_pToolbar->GetItemBits( m_nID );
192 114480 : nItemBits &= ~ToolBoxItemBits::CHECKABLE;
193 114480 : TriState eTri = TRISTATE_FALSE;
194 :
195 : bool bValue;
196 114480 : OUString aStrValue;
197 228960 : ItemStatus aItemState;
198 114480 : Visibility aItemVisibility;
199 :
200 114480 : if (( Event.State >>= bValue ) && !m_bEnumCommand )
201 : {
202 : // Boolean, treat it as checked/unchecked
203 31421 : if ( m_bMadeInvisible )
204 0 : m_pToolbar->ShowItem( m_nID, true );
205 31421 : m_pToolbar->CheckItem( m_nID, bValue );
206 31421 : if ( bValue )
207 6102 : eTri = TRISTATE_TRUE;
208 31421 : nItemBits |= ToolBoxItemBits::CHECKABLE;
209 : }
210 83059 : else if ( Event.State >>= aStrValue )
211 : {
212 3471 : 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 |= ToolBoxItemBits::CHECKABLE;
223 : }
224 : else
225 : {
226 : // Replacement for place holders
227 3471 : 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 3471 : 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 3471 : 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 3471 : m_pToolbar->SetItemText( m_nID, aStrValue );
247 : }
248 :
249 3471 : if ( m_bMadeInvisible )
250 0 : m_pToolbar->ShowItem( m_nID, true );
251 : }
252 79588 : else if (( Event.State >>= aItemState ) && !m_bEnumCommand )
253 : {
254 10 : eTri = TRISTATE_INDET;
255 10 : nItemBits |= ToolBoxItemBits::CHECKABLE;
256 10 : if ( m_bMadeInvisible )
257 0 : m_pToolbar->ShowItem( m_nID, true );
258 : }
259 79578 : else if ( Event.State >>= aItemVisibility )
260 : {
261 0 : m_pToolbar->ShowItem( m_nID, aItemVisibility.bVisible );
262 0 : m_bMadeInvisible = !aItemVisibility.bVisible;
263 : }
264 79578 : else if ( m_bMadeInvisible )
265 0 : m_pToolbar->ShowItem( m_nID, true );
266 :
267 114480 : m_pToolbar->SetItemState( m_nID, eTri );
268 228960 : m_pToolbar->SetItemBits( m_nID, nItemBits );
269 114480 : }
270 : }
271 :
272 8 : IMPL_STATIC_LINK_NOINSTANCE( GenericToolbarController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
273 : {
274 4 : const sal_uInt32 nRef = Application::ReleaseSolarMutex();
275 : try
276 : {
277 : // Asynchronous execution as this can lead to our own destruction!
278 : // Framework can recycle our current frame and the layout manager disposes all user interface
279 : // elements if a component gets detached from its frame!
280 4 : pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
281 : }
282 0 : catch ( const Exception& )
283 : {
284 : }
285 :
286 4 : Application::AcquireSolarMutex( nRef );
287 4 : delete pExecuteInfo;
288 4 : return 0;
289 : }
290 :
291 0 : MenuToolbarController::MenuToolbarController( const Reference< XComponentContext >& rxContext,
292 : const Reference< XFrame >& rFrame,
293 : ToolBox* pToolBar,
294 : sal_uInt16 nID,
295 : const OUString& aCommand,
296 : const OUString& aModuleIdentifier,
297 : const Reference< XIndexAccess >& xMenuDesc )
298 : : GenericToolbarController( rxContext, rFrame, pToolBar, nID, aCommand ),
299 : m_xMenuDesc( xMenuDesc ),
300 : pMenu( NULL ),
301 0 : m_aModuleIdentifier( aModuleIdentifier )
302 : {
303 0 : }
304 :
305 0 : MenuToolbarController::~MenuToolbarController()
306 : {
307 : try
308 : {
309 0 : if ( m_xMenuManager.is() )
310 0 : m_xMenuManager->dispose();
311 : }
312 0 : catch( const Exception& ) {}
313 0 : if ( pMenu )
314 : {
315 0 : delete pMenu;
316 0 : pMenu = NULL;
317 : }
318 :
319 0 : }
320 :
321 : class Toolbarmenu : public ::PopupMenu
322 : {
323 : public:
324 : Toolbarmenu();
325 : virtual ~Toolbarmenu();
326 : };
327 :
328 0 : Toolbarmenu::Toolbarmenu()
329 : {
330 : OSL_TRACE("**** contstructing Toolbarmenu 0x%x", this );
331 0 : }
332 :
333 0 : Toolbarmenu::~Toolbarmenu()
334 : {
335 : OSL_TRACE("**** destructing Toolbarmenu 0x%x", this );
336 0 : }
337 :
338 0 : void SAL_CALL MenuToolbarController::click() throw (RuntimeException, std::exception)
339 : {
340 0 : createPopupWindow();
341 0 : }
342 :
343 : Reference< XWindow > SAL_CALL
344 0 : MenuToolbarController::createPopupWindow() throw (::com::sun::star::uno::RuntimeException, std::exception)
345 : {
346 0 : if ( !pMenu )
347 : {
348 0 : Reference< XDispatchProvider > xDispatch;
349 0 : Reference< XURLTransformer > xURLTransformer = URLTransformer::create( m_xContext );
350 0 : pMenu = new Toolbarmenu();
351 0 : m_xMenuManager.set( new MenuBarManager( m_xContext, m_xFrame, xURLTransformer, xDispatch, m_aModuleIdentifier, pMenu, true, true ) );
352 0 : if (m_xMenuManager.is())
353 : {
354 0 : MenuBarManager& rMgr = dynamic_cast<MenuBarManager&>(*m_xMenuManager.get());
355 0 : rMgr.SetItemContainer(m_xMenuDesc);
356 0 : }
357 : }
358 :
359 0 : if ( !pMenu || !m_pToolbar )
360 0 : return NULL;
361 :
362 : OSL_ENSURE ( pMenu->GetItemCount(), "Empty PopupMenu!" );
363 :
364 0 : ::Rectangle aRect( m_pToolbar->GetItemRect( m_nID ) );
365 0 : pMenu->Execute( m_pToolbar, aRect, POPUPMENU_EXECUTE_DOWN );
366 :
367 0 : return NULL;
368 : }
369 951 : } // namespace
370 :
371 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|