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 <tools/SlotStateListener.hxx>
21 #include <com/sun/star/frame/XDispatchProvider.hpp>
22 #include <com/sun/star/frame/XDispatch.hpp>
23 #include <com/sun/star/util/URLTransformer.hpp>
24 #include <com/sun/star/util/XURLTransformer.hpp>
25 
26 #include <comphelper/processfactory.hxx>
27 
28 using namespace ::com::sun::star;
29 
30 namespace sd { namespace tools {
31 
SlotStateListener(Link<const OUString &,void> const & rCallback,const uno::Reference<frame::XDispatchProvider> & rxDispatchProvider,const OUString & rSlotName)32 SlotStateListener::SlotStateListener (
33     Link<const OUString&,void> const & rCallback,
34     const uno::Reference<frame::XDispatchProvider>& rxDispatchProvider,
35     const OUString& rSlotName)
36     : SlotStateListenerInterfaceBase(maMutex),
37       maCallback(),
38       mxDispatchProviderWeak(nullptr)
39 {
40     SetCallback(rCallback);
41     ConnectToDispatchProvider(rxDispatchProvider);
42     ObserveSlot(rSlotName);
43 }
44 
~SlotStateListener()45 SlotStateListener::~SlotStateListener()
46 {
47     ReleaseListeners();
48 }
49 
SetCallback(const Link<const OUString &,void> & rCallback)50 void SlotStateListener::SetCallback (const Link<const OUString&,void>& rCallback)
51 {
52     ThrowIfDisposed();
53 
54     maCallback = rCallback;
55 }
56 
ConnectToDispatchProvider(const uno::Reference<frame::XDispatchProvider> & rxDispatchProvider)57 void SlotStateListener::ConnectToDispatchProvider (
58     const uno::Reference<frame::XDispatchProvider>& rxDispatchProvider)
59 {
60     ThrowIfDisposed();
61 
62     // When we are listening to state changes of slots of another frame then
63     // release these listeners first.
64     if ( ! maRegisteredURLList.empty())
65         ReleaseListeners();
66 
67     mxDispatchProviderWeak = rxDispatchProvider;
68 }
69 
ObserveSlot(const OUString & rSlotName)70 void SlotStateListener::ObserveSlot (const OUString& rSlotName)
71 {
72     ThrowIfDisposed();
73 
74     if (maCallback.IsSet())
75     {
76         // Connect the state change listener.
77         util::URL aURL (MakeURL(rSlotName));
78         uno::Reference<frame::XDispatch> xDispatch (GetDispatch(aURL));
79         if (xDispatch.is())
80         {
81             maRegisteredURLList.push_back(aURL);
82             xDispatch->addStatusListener(this,aURL);
83         }
84     }
85 }
86 
disposing()87 void SlotStateListener::disposing()
88 {
89     ReleaseListeners();
90     mxDispatchProviderWeak = uno::WeakReference<frame::XDispatchProvider>(nullptr);
91     maCallback = Link<const OUString&,void>();
92 }
93 
MakeURL(const OUString & rSlotName)94 util::URL SlotStateListener::MakeURL (const OUString& rSlotName)
95 {
96     util::URL aURL;
97     aURL.Complete = rSlotName;
98 
99     uno::Reference<util::XURLTransformer> xTransformer(util::URLTransformer::create(::comphelper::getProcessComponentContext()));
100     xTransformer->parseStrict(aURL);
101 
102     return aURL;
103 }
104 
105 uno::Reference<frame::XDispatch>
GetDispatch(const util::URL & rURL) const106     SlotStateListener::GetDispatch (const util::URL& rURL) const
107 {
108     uno::Reference<frame::XDispatch> xDispatch;
109 
110     uno::Reference<frame::XDispatchProvider> xDispatchProvider (mxDispatchProviderWeak);
111     if (xDispatchProvider.is())
112         xDispatch = xDispatchProvider->queryDispatch(rURL, OUString(), 0);
113 
114     return xDispatch;
115 }
116 
statusChanged(const frame::FeatureStateEvent & rState)117 void SlotStateListener::statusChanged (
118     const frame::FeatureStateEvent& rState)
119 {
120     ThrowIfDisposed();
121     OUString sSlotName (rState.FeatureURL.Complete);
122     maCallback.Call(sSlotName);
123 }
124 
ReleaseListeners()125 void SlotStateListener::ReleaseListeners()
126 {
127     for (const auto& rURL : maRegisteredURLList)
128     {
129         uno::Reference<frame::XDispatch> xDispatch (GetDispatch(rURL));
130         if (xDispatch.is())
131         {
132             xDispatch->removeStatusListener(this,rURL);
133         }
134     }
135 }
136 
137 //=====  lang::XEventListener  ================================================
138 
disposing(const lang::EventObject &)139 void SAL_CALL SlotStateListener::disposing (
140     const lang::EventObject& )
141 {
142 }
143 
ThrowIfDisposed()144 void SlotStateListener::ThrowIfDisposed()
145 {
146     if (rBHelper.bDisposed || rBHelper.bInDispose)
147     {
148         throw lang::DisposedException ("SlideSorterController object has already been disposed",
149             static_cast<uno::XWeak*>(this));
150     }
151 }
152 
153 } } // end of namespace ::sd::tools
154 
155 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
156