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 64915 : static bool isEnumCommand( const OUString& rCommand )
55 : {
56 64915 : INetURLObject aURL( rCommand );
57 :
58 234838 : if (( aURL.GetProtocol() == INetProtocol::Uno ) &&
59 185194 : ( aURL.GetURLPath().indexOf( '.' ) != -1))
60 122 : return true;
61 :
62 64793 : return false;
63 : }
64 :
65 64915 : static OUString getEnumCommand( const OUString& rCommand )
66 : {
67 64915 : INetURLObject aURL( rCommand );
68 :
69 64915 : OUString aEnumCommand;
70 129830 : OUString aURLPath = aURL.GetURLPath();
71 64915 : sal_Int32 nIndex = aURLPath.indexOf( '.' );
72 64915 : if (( nIndex > 0 ) && ( nIndex < aURLPath.getLength() ))
73 24944 : aEnumCommand = aURLPath.copy( nIndex+1 );
74 :
75 129830 : return aEnumCommand;
76 : }
77 :
78 122 : static OUString getMasterCommand( const OUString& rCommand )
79 : {
80 122 : OUString aMasterCommand( rCommand );
81 244 : INetURLObject aURL( rCommand );
82 122 : if ( aURL.GetProtocol() == INetProtocol::Uno )
83 : {
84 122 : sal_Int32 nIndex = aURL.GetURLPath().indexOf( '.' );
85 122 : if ( nIndex )
86 : {
87 122 : aURL.SetURLPath( aURL.GetURLPath().copy( 0, nIndex ) );
88 122 : aMasterCommand = aURL.GetMainURL( INetURLObject::NO_DECODE );
89 : }
90 : }
91 244 : 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 64915 : 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 64915 : , m_bEnumCommand( isEnumCommand( aCommand ))
110 : , m_bMadeInvisible( false )
111 129830 : , m_aEnumCommand( getEnumCommand( aCommand ))
112 : {
113 64915 : if ( m_bEnumCommand )
114 122 : addStatusListener( getMasterCommand( aCommand ) );
115 64915 : }
116 :
117 129776 : GenericToolbarController::~GenericToolbarController()
118 : {
119 129776 : }
120 :
121 64888 : void SAL_CALL GenericToolbarController::dispose()
122 : throw ( RuntimeException, std::exception )
123 : {
124 64888 : SolarMutexGuard aSolarMutexGuard;
125 :
126 64888 : svt::ToolboxController::dispose();
127 :
128 64888 : m_pToolbar.clear();
129 64888 : m_nID = 0;
130 64888 : }
131 :
132 2 : void SAL_CALL GenericToolbarController::execute( sal_Int16 KeyModifier )
133 : throw ( RuntimeException, std::exception )
134 : {
135 2 : Reference< XDispatch > xDispatch;
136 4 : Reference< XURLTransformer > xURLTransformer;
137 4 : OUString aCommandURL;
138 :
139 : {
140 2 : SolarMutexGuard aSolarMutexGuard;
141 :
142 2 : if ( m_bDisposed )
143 0 : throw DisposedException();
144 :
145 4 : if ( m_bInitialized &&
146 4 : m_xFrame.is() &&
147 2 : !m_aCommandURL.isEmpty() )
148 : {
149 2 : xURLTransformer = URLTransformer::create(m_xContext);
150 :
151 2 : aCommandURL = m_aCommandURL;
152 2 : URLToDispatchMap::iterator pIter = m_aListenerMap.find( m_aCommandURL );
153 2 : if ( pIter != m_aListenerMap.end() )
154 2 : xDispatch = pIter->second;
155 2 : }
156 : }
157 :
158 2 : if ( xDispatch.is() && xURLTransformer.is() )
159 : {
160 2 : com::sun::star::util::URL aTargetURL;
161 4 : Sequence<PropertyValue> aArgs( 1 );
162 :
163 : // Add key modifier to argument list
164 2 : aArgs[0].Name = "KeyModifier";
165 2 : aArgs[0].Value <<= KeyModifier;
166 :
167 2 : aTargetURL.Complete = aCommandURL;
168 2 : xURLTransformer->parseStrict( aTargetURL );
169 :
170 : // Execute dispatch asynchronously
171 2 : ExecuteInfo* pExecuteInfo = new ExecuteInfo;
172 2 : pExecuteInfo->xDispatch = xDispatch;
173 2 : pExecuteInfo->aTargetURL = aTargetURL;
174 2 : pExecuteInfo->aArgs = aArgs;
175 4 : Application::PostUserEvent( LINK(0, GenericToolbarController , ExecuteHdl_Impl), pExecuteInfo );
176 2 : }
177 2 : }
178 :
179 100736 : void GenericToolbarController::statusChanged( const FeatureStateEvent& Event )
180 : throw ( RuntimeException, std::exception )
181 : {
182 100736 : SolarMutexGuard aSolarMutexGuard;
183 :
184 100736 : if ( m_bDisposed )
185 100736 : return;
186 :
187 100736 : if ( m_pToolbar )
188 : {
189 100736 : m_pToolbar->EnableItem( m_nID, Event.IsEnabled );
190 :
191 100736 : ToolBoxItemBits nItemBits = m_pToolbar->GetItemBits( m_nID );
192 100736 : nItemBits &= ~ToolBoxItemBits::CHECKABLE;
193 100736 : TriState eTri = TRISTATE_FALSE;
194 :
195 : bool bValue;
196 100736 : OUString aStrValue;
197 201472 : ItemStatus aItemState;
198 100736 : Visibility aItemVisibility;
199 :
200 100736 : if (( Event.State >>= bValue ) && !m_bEnumCommand )
201 : {
202 : // Boolean, treat it as checked/unchecked
203 25846 : if ( m_bMadeInvisible )
204 0 : m_pToolbar->ShowItem( m_nID, true );
205 25846 : m_pToolbar->CheckItem( m_nID, bValue );
206 25846 : if ( bValue )
207 3850 : eTri = TRISTATE_TRUE;
208 25846 : nItemBits |= ToolBoxItemBits::CHECKABLE;
209 : }
210 74890 : else if ( Event.State >>= aStrValue )
211 : {
212 2379 : 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 2379 : if ( aStrValue.startsWith("($1)") )
228 : {
229 0 : OUString aTmp(FwkResId(STR_UPDATEDOC));
230 0 : aTmp += " ";
231 0 : aTmp += aStrValue.copy( 4 );
232 0 : aStrValue = aTmp;
233 : }
234 2379 : else if ( aStrValue.startsWith("($2)") )
235 : {
236 0 : OUString aTmp(FWK_RESSTR(STR_CLOSEDOC_ANDRETURN));
237 0 : aTmp += aStrValue.copy( 4 );
238 0 : aStrValue = aTmp;
239 : }
240 2379 : else if ( aStrValue.startsWith("($3)") )
241 : {
242 0 : OUString aTmp(FWK_RESSTR(STR_SAVECOPYDOC));
243 0 : aTmp += aStrValue.copy( 4 );
244 0 : aStrValue = aTmp;
245 : }
246 2379 : m_pToolbar->SetItemText( m_nID, aStrValue );
247 : }
248 :
249 2379 : if ( m_bMadeInvisible )
250 0 : m_pToolbar->ShowItem( m_nID, true );
251 : }
252 72511 : 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 72501 : else if ( Event.State >>= aItemVisibility )
260 : {
261 0 : m_pToolbar->ShowItem( m_nID, aItemVisibility.bVisible );
262 0 : m_bMadeInvisible = !aItemVisibility.bVisible;
263 : }
264 72501 : else if ( m_bMadeInvisible )
265 0 : m_pToolbar->ShowItem( m_nID, true );
266 :
267 100736 : m_pToolbar->SetItemState( m_nID, eTri );
268 201472 : m_pToolbar->SetItemBits( m_nID, nItemBits );
269 100736 : }
270 : }
271 :
272 4 : IMPL_STATIC_LINK( GenericToolbarController, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
273 : {
274 2 : SolarMutexReleaser aReleaser;
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 2 : pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
281 : }
282 0 : catch ( const Exception& )
283 : {
284 : }
285 :
286 2 : delete pExecuteInfo;
287 2 : return 0;
288 : }
289 :
290 0 : MenuToolbarController::MenuToolbarController( const Reference< XComponentContext >& rxContext,
291 : const Reference< XFrame >& rFrame,
292 : ToolBox* pToolBar,
293 : sal_uInt16 nID,
294 : const OUString& aCommand,
295 : const OUString& aModuleIdentifier,
296 : const Reference< XIndexAccess >& xMenuDesc )
297 : : GenericToolbarController( rxContext, rFrame, pToolBar, nID, aCommand ),
298 : m_xMenuDesc( xMenuDesc ),
299 : pMenu( NULL ),
300 0 : 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 : virtual ~Toolbarmenu();
325 : };
326 :
327 0 : Toolbarmenu::Toolbarmenu()
328 : {
329 : SAL_INFO("fwk.uielement", "contstructing Toolbarmenu " << this);
330 0 : }
331 :
332 0 : Toolbarmenu::~Toolbarmenu()
333 : {
334 : SAL_INFO("fwk.uielement", "destructing Toolbarmenu " << this);
335 0 : }
336 :
337 0 : void SAL_CALL MenuToolbarController::click() throw (RuntimeException, std::exception)
338 : {
339 0 : createPopupWindow();
340 0 : }
341 :
342 : Reference< XWindow > SAL_CALL
343 0 : MenuToolbarController::createPopupWindow() throw (::com::sun::star::uno::RuntimeException, std::exception)
344 : {
345 0 : if ( !pMenu )
346 : {
347 0 : Reference< XDispatchProvider > xDispatch;
348 0 : Reference< XURLTransformer > xURLTransformer = URLTransformer::create( m_xContext );
349 0 : pMenu = new Toolbarmenu();
350 0 : m_xMenuManager.set( new MenuBarManager( m_xContext, m_xFrame, xURLTransformer, xDispatch, m_aModuleIdentifier, pMenu, true, true ) );
351 0 : if (m_xMenuManager.is())
352 : {
353 0 : MenuBarManager& rMgr = dynamic_cast<MenuBarManager&>(*m_xMenuManager.get());
354 0 : rMgr.SetItemContainer(m_xMenuDesc);
355 0 : }
356 : }
357 :
358 0 : if ( !pMenu || !m_pToolbar )
359 0 : return NULL;
360 :
361 : OSL_ENSURE ( pMenu->GetItemCount(), "Empty PopupMenu!" );
362 :
363 0 : ::Rectangle aRect( m_pToolbar->GetItemRect( m_nID ) );
364 0 : pMenu->Execute( m_pToolbar, aRect, PopupMenuFlags::ExecuteDown );
365 :
366 0 : return NULL;
367 : }
368 : } // namespace
369 :
370 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|