1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "precompiled_sd.hxx"
29 
30 #include "ReadOnlyModeObserver.hxx"
31 
32 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
33 #include <com/sun/star/lang/DisposedException.hpp>
34 #include <com/sun/star/util/XURLTransformer.hpp>
35 #include <comphelper/processfactory.hxx>
36 #include <cppuhelper/interfacecontainer.hxx>
37 
38 #include "tools/SlotStateListener.hxx"
39 #include "framework/FrameworkHelper.hxx"
40 
41 using namespace ::com::sun::star::uno;
42 using namespace ::com::sun::star;
43 using namespace ::com::sun::star::drawing::framework;
44 using ::rtl::OUString;
45 
46 namespace sd { namespace framework {
47 
48 class ReadOnlyModeObserver::ModifyBroadcaster
49     : public ::cppu::OBroadcastHelper
50 {
51 public:
52     explicit ModifyBroadcaster (::osl::Mutex& rOslMutex) : ::cppu::OBroadcastHelper(rOslMutex) {}
53 };
54 
55 
56 
57 
58 ReadOnlyModeObserver::ReadOnlyModeObserver (
59     const Reference<frame::XController>& rxController)
60     : ReadOnlyModeObserverInterfaceBase(maMutex),
61       maSlotNameURL(),
62       mxController(rxController),
63       mxConfigurationController(NULL),
64       mxDispatch(NULL),
65       mpBroadcaster(new ModifyBroadcaster(maMutex))
66 {
67     // Create a URL object for the slot name.
68     maSlotNameURL.Complete = OUString::createFromAscii(".uno:EditDoc");
69     uno::Reference<lang::XMultiServiceFactory> xServiceManager (
70         ::comphelper::getProcessServiceFactory());
71     if (xServiceManager.is())
72     {
73         Reference<util::XURLTransformer> xTransformer(xServiceManager->createInstance(
74             OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))),
75             UNO_QUERY);
76         if (xTransformer.is())
77             xTransformer->parseStrict(maSlotNameURL);
78     }
79 
80     if ( ! ConnectToDispatch())
81     {
82         // The controller is not yet connected to a frame.  This means that
83         // the dispatcher is not yet set up.  We wait for this to happen by
84         // waiting for configuration updates and try again.
85         Reference<XControllerManager> xControllerManager (rxController, UNO_QUERY);
86         if (xControllerManager.is())
87         {
88             mxConfigurationController = xControllerManager->getConfigurationController();
89             if (mxConfigurationController.is())
90             {
91                 mxConfigurationController->addConfigurationChangeListener(
92                     this,
93                     FrameworkHelper::msConfigurationUpdateStartEvent,
94                     Any());
95             }
96         }
97     }
98 }
99 
100 
101 
102 
103 ReadOnlyModeObserver::~ReadOnlyModeObserver (void)
104 {
105 }
106 
107 
108 
109 
110 void SAL_CALL ReadOnlyModeObserver::disposing (void)
111 {
112     if (mxController.is())
113     {
114         mxController = NULL;
115     }
116     if (mxConfigurationController.is())
117     {
118         mxConfigurationController->removeConfigurationChangeListener(this);
119         mxConfigurationController = NULL;
120     }
121     if (mxDispatch.is())
122     {
123         mxDispatch->removeStatusListener(this, maSlotNameURL);
124         mxDispatch = NULL;
125     }
126 
127     lang::EventObject aEvent;
128     aEvent.Source = static_cast<XWeak*>(this);
129     ::cppu::OInterfaceContainerHelper* pIterator
130         = mpBroadcaster->getContainer(getCppuType((Reference<frame::XStatusListener>*)NULL));
131     pIterator->disposeAndClear(aEvent);
132 }
133 
134 
135 
136 
137 void ReadOnlyModeObserver::AddStatusListener (
138     const Reference<frame::XStatusListener>& rxListener)
139 {
140     mpBroadcaster->addListener(
141         getCppuType((Reference<frame::XStatusListener>*)NULL),
142         rxListener);
143 }
144 
145 
146 
147 
148 bool ReadOnlyModeObserver::ConnectToDispatch (void)
149 {
150     if ( ! mxDispatch.is())
151     {
152         // Get the dispatch object.
153         Reference<frame::XDispatchProvider> xProvider (mxController->getFrame(), UNO_QUERY);
154         if (xProvider.is())
155         {
156             mxDispatch = xProvider->queryDispatch(maSlotNameURL, OUString(), 0);
157             if (mxDispatch.is())
158             {
159                 mxDispatch->addStatusListener(this, maSlotNameURL);
160             }
161         }
162     }
163 
164     return mxDispatch.is();
165 }
166 
167 
168 
169 
170 void ReadOnlyModeObserver::statusChanged (const frame::FeatureStateEvent& rEvent)
171     throw (RuntimeException)
172 {
173     ::cppu::OInterfaceContainerHelper* pIterator
174           = mpBroadcaster->getContainer(getCppuType((Reference<frame::XStatusListener>*)NULL));
175     if (pIterator != NULL)
176     {
177         pIterator->notifyEach(&frame::XStatusListener::statusChanged, rEvent);
178     }
179 }
180 
181 
182 
183 
184 //----- XEventListener --------------------------------------------------------
185 
186 void SAL_CALL ReadOnlyModeObserver::disposing (
187     const lang::EventObject& rEvent)
188     throw (RuntimeException)
189 {
190     if (rEvent.Source == mxConfigurationController)
191         mxConfigurationController = NULL;
192     else if (rEvent.Source == mxDispatch)
193         mxDispatch = NULL;
194 
195     dispose();
196 }
197 
198 
199 
200 
201 void SAL_CALL ReadOnlyModeObserver::notifyConfigurationChange (
202     const ConfigurationChangeEvent& rEvent)
203     throw (RuntimeException)
204 {
205     if (rEvent.Type.equals(FrameworkHelper::msConfigurationUpdateStartEvent))
206     {
207         if (mxController.is() && mxController->getFrame().is())
208         {
209             if (ConnectToDispatch())
210             {
211                 // We have connected successfully to the dispatcher and
212                 // therefore can disconnect from the configuration controller.
213                 mxConfigurationController->removeConfigurationChangeListener(this);
214                 mxConfigurationController = NULL;
215             }
216         }
217     }
218 }
219 
220 } } // end of namespace sd::framework
221