1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "precompiled_sd.hxx"
25 
26 #include "ReadOnlyModeObserver.hxx"
27 
28 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
29 #include <com/sun/star/lang/DisposedException.hpp>
30 #include <com/sun/star/util/XURLTransformer.hpp>
31 #include <comphelper/processfactory.hxx>
32 #include <cppuhelper/interfacecontainer.hxx>
33 
34 #include "tools/SlotStateListener.hxx"
35 #include "framework/FrameworkHelper.hxx"
36 
37 using namespace ::com::sun::star::uno;
38 using namespace ::com::sun::star;
39 using namespace ::com::sun::star::drawing::framework;
40 using ::rtl::OUString;
41 
42 namespace sd { namespace framework {
43 
44 class ReadOnlyModeObserver::ModifyBroadcaster
45     : public ::cppu::OBroadcastHelper
46 {
47 public:
48     explicit ModifyBroadcaster (::osl::Mutex& rOslMutex) : ::cppu::OBroadcastHelper(rOslMutex) {}
49 };
50 
51 
52 
53 
54 ReadOnlyModeObserver::ReadOnlyModeObserver (
55     const Reference<frame::XController>& rxController)
56     : ReadOnlyModeObserverInterfaceBase(maMutex),
57       maSlotNameURL(),
58       mxController(rxController),
59       mxConfigurationController(NULL),
60       mxDispatch(NULL),
61       mpBroadcaster(new ModifyBroadcaster(maMutex))
62 {
63     // Create a URL object for the slot name.
64     maSlotNameURL.Complete = OUString::createFromAscii(".uno:EditDoc");
65     uno::Reference<lang::XMultiServiceFactory> xServiceManager (
66         ::comphelper::getProcessServiceFactory());
67     if (xServiceManager.is())
68     {
69         Reference<util::XURLTransformer> xTransformer(xServiceManager->createInstance(
70             OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))),
71             UNO_QUERY);
72         if (xTransformer.is())
73             xTransformer->parseStrict(maSlotNameURL);
74     }
75 
76     if ( ! ConnectToDispatch())
77     {
78         // The controller is not yet connected to a frame.  This means that
79         // the dispatcher is not yet set up.  We wait for this to happen by
80         // waiting for configuration updates and try again.
81         Reference<XControllerManager> xControllerManager (rxController, UNO_QUERY);
82         if (xControllerManager.is())
83         {
84             mxConfigurationController = xControllerManager->getConfigurationController();
85             if (mxConfigurationController.is())
86             {
87                 mxConfigurationController->addConfigurationChangeListener(
88                     this,
89                     FrameworkHelper::msConfigurationUpdateStartEvent,
90                     Any());
91             }
92         }
93     }
94 }
95 
96 
97 
98 
99 ReadOnlyModeObserver::~ReadOnlyModeObserver (void)
100 {
101 }
102 
103 
104 
105 
106 void SAL_CALL ReadOnlyModeObserver::disposing (void)
107 {
108     if (mxController.is())
109     {
110         mxController = NULL;
111     }
112     if (mxConfigurationController.is())
113     {
114         mxConfigurationController->removeConfigurationChangeListener(this);
115         mxConfigurationController = NULL;
116     }
117     if (mxDispatch.is())
118     {
119         mxDispatch->removeStatusListener(this, maSlotNameURL);
120         mxDispatch = NULL;
121     }
122 
123     lang::EventObject aEvent;
124     aEvent.Source = static_cast<XWeak*>(this);
125     ::cppu::OInterfaceContainerHelper* pIterator
126         = mpBroadcaster->getContainer(getCppuType((Reference<frame::XStatusListener>*)NULL));
127     pIterator->disposeAndClear(aEvent);
128 }
129 
130 
131 
132 
133 void ReadOnlyModeObserver::AddStatusListener (
134     const Reference<frame::XStatusListener>& rxListener)
135 {
136     mpBroadcaster->addListener(
137         getCppuType((Reference<frame::XStatusListener>*)NULL),
138         rxListener);
139 }
140 
141 
142 
143 
144 bool ReadOnlyModeObserver::ConnectToDispatch (void)
145 {
146     if ( ! mxDispatch.is())
147     {
148         // Get the dispatch object.
149         Reference<frame::XDispatchProvider> xProvider (mxController->getFrame(), UNO_QUERY);
150         if (xProvider.is())
151         {
152             mxDispatch = xProvider->queryDispatch(maSlotNameURL, OUString(), 0);
153             if (mxDispatch.is())
154             {
155                 mxDispatch->addStatusListener(this, maSlotNameURL);
156             }
157         }
158     }
159 
160     return mxDispatch.is();
161 }
162 
163 
164 
165 
166 void ReadOnlyModeObserver::statusChanged (const frame::FeatureStateEvent& rEvent)
167     throw (RuntimeException)
168 {
169     ::cppu::OInterfaceContainerHelper* pIterator
170           = mpBroadcaster->getContainer(getCppuType((Reference<frame::XStatusListener>*)NULL));
171     if (pIterator != NULL)
172     {
173         pIterator->notifyEach(&frame::XStatusListener::statusChanged, rEvent);
174     }
175 }
176 
177 
178 
179 
180 //----- XEventListener --------------------------------------------------------
181 
182 void SAL_CALL ReadOnlyModeObserver::disposing (
183     const lang::EventObject& rEvent)
184     throw (RuntimeException)
185 {
186     if (rEvent.Source == mxConfigurationController)
187         mxConfigurationController = NULL;
188     else if (rEvent.Source == mxDispatch)
189         mxDispatch = NULL;
190 
191     dispose();
192 }
193 
194 
195 
196 
197 void SAL_CALL ReadOnlyModeObserver::notifyConfigurationChange (
198     const ConfigurationChangeEvent& rEvent)
199     throw (RuntimeException)
200 {
201     if (rEvent.Type.equals(FrameworkHelper::msConfigurationUpdateStartEvent))
202     {
203         if (mxController.is() && mxController->getFrame().is())
204         {
205             if (ConnectToDispatch())
206             {
207                 // We have connected successfully to the dispatcher and
208                 // therefore can disconnect from the configuration controller.
209                 mxConfigurationController->removeConfigurationChangeListener(this);
210                 mxConfigurationController = NULL;
211             }
212         }
213     }
214 }
215 
216 } } // end of namespace sd::framework
217