LibreOffice Module svtools (master) 1
framestatuslistener.cxx
Go to the documentation of this file.
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
21#include <com/sun/star/frame/XDispatchProvider.hpp>
22#include <com/sun/star/lang/DisposedException.hpp>
23#include <com/sun/star/util/URLTransformer.hpp>
25#include <vcl/svapp.hxx>
26
27using namespace ::cppu;
28using namespace css::awt;
29using namespace css::uno;
30using namespace css::util;
31using namespace css::beans;
32using namespace css::lang;
33using namespace css::frame;
34
35namespace svt
36{
37
39 const Reference< XComponentContext >& rxContext,
40 const Reference< XFrame >& xFrame ) :
41 OWeakObject()
42 , m_bDisposed( false )
43 , m_xFrame( xFrame )
44 , m_xContext( rxContext )
45{
46}
47
49{
50}
51
52// XInterface
54{
55 Any a = ::cppu::queryInterface(
56 rType ,
57 static_cast< XComponent* >( this ),
58 static_cast< XFrameActionListener* >( this ),
59 static_cast< XStatusListener* >( this ),
60 static_cast< XEventListener* >( static_cast< XStatusListener* >( this )),
61 static_cast< XEventListener* >( static_cast< XFrameActionListener* >( this )));
62
63 if ( a.hasValue() )
64 return a;
65
66 return OWeakObject::queryInterface( rType );
67}
68
69void SAL_CALL FrameStatusListener::acquire() noexcept
70{
71 OWeakObject::acquire();
72}
73
74void SAL_CALL FrameStatusListener::release() noexcept
75{
76 OWeakObject::release();
77}
78
79// XComponent
81{
82 Reference< XComponent > xThis = this;
83
84 SolarMutexGuard aSolarMutexGuard;
85 if ( m_bDisposed )
86 return;
87
88 for (auto const& listener : m_aListenerMap)
89 {
90 try
91 {
92 Reference< XDispatch > xDispatch( listener.second );
93 Reference< XURLTransformer > xURLTransformer( css::util::URLTransformer::create( m_xContext ) );
94 css::util::URL aTargetURL;
95 aTargetURL.Complete = listener.first;
96 xURLTransformer->parseStrict( aTargetURL );
97
98 if ( xDispatch.is() )
99 xDispatch->removeStatusListener( this, aTargetURL );
100 }
101 catch (const Exception&)
102 {
103 }
104 }
105
106 m_bDisposed = true;
107}
108
110{
111 // helper class for status updates - no need to support listener
112}
113
115{
116 // helper class for status updates - no need to support listener
117}
118
119// XEventListener
120void SAL_CALL FrameStatusListener::disposing( const EventObject& Source )
121{
122 Reference< XInterface > xSource( Source.Source );
123
124 SolarMutexGuard aSolarMutexGuard;
125
126 for (auto & listener : m_aListenerMap)
127 {
128 // Compare references and release dispatch references if they are equal.
129 Reference< XInterface > xIfac( listener.second, UNO_QUERY );
130 if ( xSource == xIfac )
131 listener.second.clear();
132 }
133
134 Reference< XInterface > xIfac( m_xFrame, UNO_QUERY );
135 if ( xIfac == xSource )
136 m_xFrame.clear();
137}
138
139void FrameStatusListener::frameAction( const FrameActionEvent& Action )
140{
141 if ( Action.Action == FrameAction_CONTEXT_CHANGED )
142 bindListener();
143}
144
145void FrameStatusListener::addStatusListener( const OUString& aCommandURL )
146{
148 Reference< XStatusListener > xStatusListener;
149 css::util::URL aTargetURL;
150
151 {
152 SolarMutexGuard aSolarMutexGuard;
153 URLToDispatchMap::iterator pIter = m_aListenerMap.find( aCommandURL );
154
155 // Already in the list of status listener. Do nothing.
156 if ( pIter != m_aListenerMap.end() )
157 return;
158
159 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
160 if ( m_xContext.is() && xDispatchProvider.is() )
161 {
162 Reference< XURLTransformer > xURLTransformer( css::util::URLTransformer::create( m_xContext ) );
163 aTargetURL.Complete = aCommandURL;
164 xURLTransformer->parseStrict( aTargetURL );
165 xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
166
167 xStatusListener = this;
168 URLToDispatchMap::iterator aIter = m_aListenerMap.find( aCommandURL );
169 if ( aIter != m_aListenerMap.end() )
170 {
171 Reference< XDispatch > xOldDispatch( aIter->second );
172 aIter->second = xDispatch;
173
174 try
175 {
176 if ( xOldDispatch.is() )
177 xOldDispatch->removeStatusListener( xStatusListener, aTargetURL );
178 }
179 catch (const Exception&)
180 {
181 }
182 }
183 else
184 m_aListenerMap.emplace( aCommandURL, xDispatch );
185 }
186 }
187
188 // Call without locked mutex as we are called back from dispatch implementation
189 try
190 {
191 if ( xDispatch.is() )
192 xDispatch->addStatusListener( xStatusListener, aTargetURL );
193 }
194 catch (const Exception&)
195 {
196 }
197}
198
199
201{
202 std::vector< Listener > aDispatchVector;
203 Reference< XStatusListener > xStatusListener;
204
205 {
206 SolarMutexGuard aSolarMutexGuard;
207
208 // Collect all registered command URL's and store them temporary
209 Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY );
210 if ( m_xContext.is() && xDispatchProvider.is() )
211 {
212 xStatusListener = this;
213 for (auto & listener : m_aListenerMap)
214 {
215 Reference< XURLTransformer > xURLTransformer( css::util::URLTransformer::create( m_xContext ) );
216 css::util::URL aTargetURL;
217 aTargetURL.Complete = listener.first;
218 xURLTransformer->parseStrict( aTargetURL );
219
220 Reference< XDispatch > xDispatch( listener.second );
221 if ( xDispatch.is() )
222 {
223 // We already have a dispatch object => we have to requery.
224 // Release old dispatch object and remove it as listener
225 try
226 {
227 xDispatch->removeStatusListener( xStatusListener, aTargetURL );
228 }
229 catch (const Exception&)
230 {
231 }
232 }
233
234 // Query for dispatch object. Old dispatch will be released with this, too.
235 try
236 {
237 xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 );
238 }
239 catch (const Exception&)
240 {
241 }
242 listener.second = xDispatch;
243
244 aDispatchVector.push_back( Listener( std::move(aTargetURL), xDispatch ) );
245 }
246 }
247 }
248
249 // Call without locked mutex as we are called back from dispatch implementation
250 if ( !xStatusListener.is() )
251 return;
252
253 try
254 {
255 for (Listener & rListener : aDispatchVector)
256 {
257 if ( rListener.xDispatch.is() )
258 rListener.xDispatch->addStatusListener( xStatusListener, rListener.aURL );
259 }
260 }
261 catch (const Exception&)
262 {
263 }
264}
265
266} // svt
267
268/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XComponentContext > m_xContext
css::uno::Reference< css::lang::XComponent > m_xFrame
virtual void SAL_CALL acquire() noexcept override
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
void addStatusListener(const OUString &aCommandURL)
virtual void SAL_CALL dispose() override
virtual ~FrameStatusListener() override
virtual void SAL_CALL release() noexcept override
css::uno::Reference< css::uno::XComponentContext > m_xContext
css::uno::Reference< css::frame::XFrame > m_xFrame
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &aListener) override
virtual void SAL_CALL frameAction(const css::frame::FrameActionEvent &Action) override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &aType) override
FrameStatusListener(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::frame::XFrame > &xFrame)
Reference< XDispatch > xDispatch
bool m_bDisposed
uno_Any a
@ Exception
Type
Reference< XFrame > xFrame
OUString aTargetURL