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 #include "precompiled_sd.hxx"
23 
24 #include "SidebarFactory.hxx"
25 #include "framework/FrameworkHelper.hxx"
26 #include "framework/Pane.hxx"
27 #include "ViewShellBase.hxx"
28 #include "UIElementWrapper.hxx"
29 
30 #include <sfx2/viewfrm.hxx>
31 #include <comphelper/namedvaluecollection.hxx>
32 #include <vcl/window.hxx>
33 #include <toolkit/helper/vclunohelper.hxx>
34 
35 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
36 
37 using namespace css;
38 using namespace cssu;
39 using namespace css::drawing::framework;
40 using namespace ::sd::framework;
41 using ::rtl::OUString;
42 
43 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
44 
45 namespace sd { namespace sidebar {
46 
47 namespace {
48     /** Note that these names have to be identical to (the tail of)
49         the entries in officecfg/registry/data/org/openoffice/Office/Impress.xcu
50         for the TaskPanelFactory.
51     */
52     const static char* gsResourceNameCustomAnimations = "/CustomAnimations";
53     const static char* gsResourceNameLayouts = "/Layouts";
54     const static char* gsResourceNameAllMasterPages = "/AllMasterPages";
55     const static char* gsResourceNameRecentMasterPages = "/RecentMasterPages";
56     const static char* gsResourceNameUsedMasterPages = "/UsedMasterPages";
57     const static char* gsResourceNameSlideTransitions = "/SlideTransitions";
58     const static char* gsResourceNameTableDesign = "/TableDesign";
59 }
60 
61 class SidebarFactory::Implementation
62 {
63 public:
64     Reference<cssdf::XConfigurationController> mxConfigurationController;
65     rtl::Reference<framework::Pane> mxPane;
66     Reference<ui::XUIElement> mxUIElement;
67     Reference<frame::XController> mxController;
68     Reference<awt::XWindow> mxParentWindow;
69     bool mbIsDisposed;
70 
71     Implementation (const Reference<frame::XController>& rxController);
72     ~Implementation (void);
73     void Dispose (void);
74 };
75 
76 
77 SidebarFactory::ControllerToImplementationMap SidebarFactory::maControllerToImplementationMap;
78 Reference<lang::XEventListener> mxControllerDisposeListener;
79 
80 
81 
82 // ----- Service functions ----------------------------------------------------
83 
84 Reference<XInterface> SAL_CALL SidebarFactory_createInstance (
85     const Reference<XComponentContext>& rxContext)
86 {
87     return Reference<XInterface>(static_cast<XWeak*>(new SidebarFactory(rxContext)));
88 }
89 
90 
91 
92 
93 ::rtl::OUString SidebarFactory_getImplementationName (void) throw(RuntimeException)
94 {
95     return ::rtl::OUString(
96         RTL_CONSTASCII_USTRINGPARAM("org.openoffice.comp.Draw.framework.SidebarFactory"));
97 }
98 
99 
100 
101 
102 Sequence<rtl::OUString> SAL_CALL SidebarFactory_getSupportedServiceNames (void)
103     throw (RuntimeException)
104 {
105 	static const ::rtl::OUString sServiceName(
106         ::rtl::OUString::createFromAscii("com.sun.star.drawing.framework.SidebarFactory"));
107 	return Sequence<rtl::OUString>(&sServiceName, 1);
108 }
109 
110 
111 
112 
113 //----- SidebarFactory --------------------------------------------------------
114 
115 SidebarFactory::SidebarFactory(
116         const css::uno::Reference<css::uno::XComponentContext>& rxContext)
117     : SidebarFactoryInterfaceBase(m_aMutex),
118       mpImplementation()
119 {
120 }
121 
122 
123 
124 
125 SidebarFactory::~SidebarFactory (void)
126 {
127 }
128 
129 
130 
131 
132 void SAL_CALL SidebarFactory::disposing (void)
133 {
134     SharedImplementation pImplementation;
135     pImplementation.swap(mpImplementation);
136     if (pImplementation)
137         pImplementation->Dispose();
138 }
139 
140 
141 
142 
143 // XInitialization
144 
145 void SAL_CALL SidebarFactory::initialize (const Sequence<Any>& aArguments)
146     throw (Exception, RuntimeException)
147 {
148     if (aArguments.getLength() > 0)
149     {
150         mpImplementation = GetImplementationForController(
151             Reference<frame::XController>(aArguments[0], UNO_QUERY));
152     }
153 }
154 
155 
156 
157 
158 // XUIElementFactory
159 
160 Reference<ui::XUIElement> SAL_CALL SidebarFactory::createUIElement (
161     const ::rtl::OUString& rsUIElementResourceURL,
162     const ::cssu::Sequence<css::beans::PropertyValue>& rArguments)
163     throw(
164         css::container::NoSuchElementException,
165         css::lang::IllegalArgumentException,
166         cssu::RuntimeException)
167 {
168     // Process arguments.
169     const ::comphelper::NamedValueCollection aArguments (rArguments);
170     Reference<frame::XFrame> xFrame (aArguments.getOrDefault("Frame", Reference<frame::XFrame>()));
171     Reference<awt::XWindow> xParentWindow (aArguments.getOrDefault("ParentWindow", Reference<awt::XWindow>()));
172     Reference<ui::XSidebar> xSidebar (aArguments.getOrDefault("Sidebar", Reference<ui::XSidebar>()));
173 
174     // Throw exceptions when the arguments are not as expected.
175     ::Window* pParentWindow = VCLUnoHelper::GetWindow(xParentWindow);
176     if ( ! xParentWindow.is() || pParentWindow==NULL)
177         throw RuntimeException(
178             A2S("SidebarFactory::createUIElement called without ParentWindow"),
179             NULL);
180     if ( ! xFrame.is())
181         throw RuntimeException(
182             A2S("SidebarFactory::createUIElement called without XFrame"),
183             NULL);
184     mpImplementation = GetImplementationForController(xFrame->getController());
185     if ( ! mpImplementation)
186         throw RuntimeException(
187             A2S("SidebarFactory::createUIElement called without XController"),
188             NULL);
189     if (mpImplementation->mxConfigurationController.is())
190         mpImplementation->mxConfigurationController->addResourceFactory(
191             FrameworkHelper::msSidebarPaneURL+A2S("*"), this);
192 
193     //  Remember the parent window, so that following calls to
194     //  createResource() can access it.
195     mpImplementation->mxParentWindow = xParentWindow;
196     if (mpImplementation->mxPane.is())
197         mpImplementation->mxPane->SetWindow(VCLUnoHelper::GetWindow(xParentWindow));
198 
199     // Create a framework view.
200     OUString sTaskPanelURL;
201 #define EndsWith(s,t) s.endsWithAsciiL(t,strlen(t))
202     if (EndsWith(rsUIElementResourceURL, gsResourceNameCustomAnimations))
203         sTaskPanelURL = FrameworkHelper::msCustomAnimationTaskPanelURL;
204     else if (EndsWith(rsUIElementResourceURL, gsResourceNameLayouts))
205         sTaskPanelURL = FrameworkHelper::msLayoutTaskPanelURL;
206     else if (EndsWith(rsUIElementResourceURL, gsResourceNameAllMasterPages))
207         sTaskPanelURL = FrameworkHelper::msAllMasterPagesTaskPanelURL;
208     else if (EndsWith(rsUIElementResourceURL, gsResourceNameRecentMasterPages))
209         sTaskPanelURL = FrameworkHelper::msRecentMasterPagesTaskPanelURL;
210     else if (EndsWith(rsUIElementResourceURL, gsResourceNameUsedMasterPages))
211         sTaskPanelURL = FrameworkHelper::msUsedMasterPagesTaskPanelURL;
212     else if (EndsWith(rsUIElementResourceURL, gsResourceNameSlideTransitions))
213         sTaskPanelURL = FrameworkHelper::msSlideTransitionTaskPanelURL;
214     else if (EndsWith(rsUIElementResourceURL, gsResourceNameTableDesign))
215         sTaskPanelURL = FrameworkHelper::msTableDesignPanelURL;
216 #undef EndsWith
217 
218     if (sTaskPanelURL.getLength() == 0)
219         throw lang::IllegalArgumentException();
220 
221     // Create a wrapper around pane and view and return it as
222     // XUIElement.
223     Reference<ui::XUIElement> xUIElement;
224     try
225     {
226         xUIElement.set(new UIElementWrapper(
227                 rsUIElementResourceURL,
228                 xFrame,
229                 sTaskPanelURL,
230                 xSidebar,
231                 VCLUnoHelper::GetWindow(xParentWindow)));
232     }
233     catch(Exception& rException)
234     {
235         // Creation of XUIElement failed. mxUIElement remains empty.
236     }
237 
238     Reference<lang::XComponent> xComponent (xUIElement, UNO_QUERY);
239     if (xComponent.is())
240         xComponent->addEventListener(this);
241 
242     return xUIElement;
243 }
244 
245 
246 
247 
248 // XResourceFactory
249 
250 Reference<drawing::framework::XResource>
251     SAL_CALL SidebarFactory::createResource (
252         const Reference<drawing::framework::XResourceId>& rxPaneId)
253     throw (RuntimeException, lang::IllegalArgumentException, lang::WrappedTargetException)
254 {
255     if ( ! rxPaneId.is())
256         throw lang::IllegalArgumentException();
257 
258     const OUString sResourceURL (rxPaneId->getResourceURL());
259     if ( ! sResourceURL.equals(FrameworkHelper::msSidebarPaneURL))
260         throw lang::IllegalArgumentException();
261 
262     if ( ! mpImplementation)
263         throw RuntimeException(A2S("SidebarFactory not initialized"), NULL);
264 
265     ::Window* pWindow = VCLUnoHelper::GetWindow(mpImplementation->mxParentWindow);
266     if (pWindow == NULL)
267         throw RuntimeException();
268 
269     mpImplementation->mxPane.set(new Pane(rxPaneId, pWindow));
270     Reference<drawing::framework::XResource> xPane (static_cast<XPane*>(mpImplementation->mxPane.get()));
271     return xPane;
272 }
273 
274 
275 
276 
277 void SAL_CALL SidebarFactory::releaseResource (
278     const Reference<drawing::framework::XResource>& rxPane)
279     throw (RuntimeException)
280 {
281     (void)rxPane;
282 
283     // Any panes created by us are just wrappers around windows whose lifetime
284     // is controlled somewhere else => nothing to do.
285 }
286 
287 
288 
289 
290 void SAL_CALL SidebarFactory::disposing (const ::css::lang::EventObject& rEvent)
291     throw(cssu::RuntimeException)
292 {
293     /*
294     if (mpImplementation
295         && rEvent.Source == mpImplementation->mxUIElement)
296     {
297         mpImplementation->mxUIElement.clear();
298     }
299     */
300 }
301 
302 
303 
304 
305 SidebarFactory::SharedImplementation SidebarFactory::GetImplementationForController (
306     const cssu::Reference<css::frame::XController>& rxController)
307 {
308     SharedImplementation pImplementation;
309     if (rxController.is())
310     {
311         ControllerToImplementationMap::const_iterator iImplementation (
312             maControllerToImplementationMap.find(rxController));
313         if (iImplementation == maControllerToImplementationMap.end())
314         {
315             pImplementation.reset(new Implementation(rxController));
316             maControllerToImplementationMap[rxController] = pImplementation;
317 
318             // Each Implementation object is referenced by two
319             // SidebarFactory objects.  The Implementation object is
320             // destroyed when the first of the SidebarFactory objects
321             // is disposed.
322         }
323         else
324             pImplementation = iImplementation->second;
325     }
326     return pImplementation;
327 }
328 
329 
330 
331 
332 //----- SidebarFactory::Implementation ----------------------------------------
333 
334 SidebarFactory::Implementation::Implementation (const Reference<frame::XController>& rxController)
335     : mxConfigurationController(),
336       mxPane(),
337       mxUIElement(),
338       mxController(rxController),
339       mxParentWindow(),
340       mbIsDisposed(false)
341 {
342     Reference<XControllerManager> xCM (rxController, UNO_QUERY);
343     if (xCM.is())
344     {
345         mxConfigurationController = xCM->getConfigurationController();
346     }
347 }
348 
349 
350 
351 
352 SidebarFactory::Implementation::~Implementation (void)
353 {
354     Dispose();
355 }
356 
357 
358 
359 
360 void SidebarFactory::Implementation::Dispose (void)
361 {
362     if (mbIsDisposed)
363         return;
364 
365     mbIsDisposed = true;
366 
367     // Release the entry in the maControllerToImplementationMap even though there
368     // may be another object that "references" to it.
369     ControllerToImplementationMap::iterator iImplementation (
370         maControllerToImplementationMap.find(mxController));
371         if (iImplementation != maControllerToImplementationMap.end())
372             maControllerToImplementationMap.erase(iImplementation);
373 
374     mxController.clear();
375 }
376 
377 
378 } } // end of namespace sd::sidebar
379