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 "PresenterPaneFactory.hxx"
21 #include "PresenterController.hxx"
22 #include "PresenterPane.hxx"
23 #include "PresenterPaneBorderPainter.hxx"
24 #include "PresenterPaneContainer.hxx"
25 #include "PresenterSpritePane.hxx"
26 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
27 #include <com/sun/star/lang/XComponent.hpp>
28 
29 using namespace ::com::sun::star;
30 using namespace ::com::sun::star::uno;
31 using namespace ::com::sun::star::lang;
32 using namespace ::com::sun::star::drawing::framework;
33 
34 namespace sdext::presenter {
35 
36 //===== PresenterPaneFactory ==================================================
37 
Create(const Reference<uno::XComponentContext> & rxContext,const Reference<frame::XController> & rxController,const::rtl::Reference<PresenterController> & rpPresenterController)38 Reference<drawing::framework::XResourceFactory> PresenterPaneFactory::Create (
39     const Reference<uno::XComponentContext>& rxContext,
40     const Reference<frame::XController>& rxController,
41     const ::rtl::Reference<PresenterController>& rpPresenterController)
42 {
43     rtl::Reference<PresenterPaneFactory> pFactory (
44         new PresenterPaneFactory(rxContext,rpPresenterController));
45     pFactory->Register(rxController);
46     return Reference<drawing::framework::XResourceFactory>(
47         static_cast<XWeak*>(pFactory.get()), UNO_QUERY);
48 }
49 
PresenterPaneFactory(const Reference<uno::XComponentContext> & rxContext,const::rtl::Reference<PresenterController> & rpPresenterController)50 PresenterPaneFactory::PresenterPaneFactory (
51     const Reference<uno::XComponentContext>& rxContext,
52     const ::rtl::Reference<PresenterController>& rpPresenterController)
53     : PresenterPaneFactoryInterfaceBase(m_aMutex),
54       mxComponentContextWeak(rxContext),
55       mxConfigurationControllerWeak(),
56       mpPresenterController(rpPresenterController),
57       mpResourceCache()
58 {
59 }
60 
Register(const Reference<frame::XController> & rxController)61 void PresenterPaneFactory::Register (const Reference<frame::XController>& rxController)
62 {
63     Reference<XConfigurationController> xCC;
64     try
65     {
66         // Get the configuration controller.
67         Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW);
68         xCC.set(xCM->getConfigurationController());
69         mxConfigurationControllerWeak = xCC;
70         if ( ! xCC.is())
71         {
72             throw RuntimeException();
73         }
74         xCC->addResourceFactory(
75             "private:resource/pane/Presenter/*",
76              this);
77     }
78     catch (RuntimeException&)
79     {
80         OSL_ASSERT(false);
81         if (xCC.is())
82             xCC->removeResourceFactoryForReference(this);
83         mxConfigurationControllerWeak = WeakReference<XConfigurationController>();
84 
85         throw;
86     }
87 }
88 
~PresenterPaneFactory()89 PresenterPaneFactory::~PresenterPaneFactory()
90 {
91 }
92 
disposing()93 void SAL_CALL PresenterPaneFactory::disposing()
94 {
95     Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
96     if (xCC.is())
97         xCC->removeResourceFactoryForReference(this);
98     mxConfigurationControllerWeak = WeakReference<XConfigurationController>();
99 
100     // Dispose the panes in the cache.
101     if (mpResourceCache != nullptr)
102     {
103         for (const auto& rxPane : *mpResourceCache)
104         {
105             Reference<lang::XComponent> xPaneComponent (rxPane.second, UNO_QUERY);
106             if (xPaneComponent.is())
107                 xPaneComponent->dispose();
108         }
109         mpResourceCache.reset();
110     }
111 }
112 
113 //----- XPaneFactory ----------------------------------------------------------
114 
createResource(const Reference<XResourceId> & rxPaneId)115 Reference<XResource> SAL_CALL PresenterPaneFactory::createResource (
116     const Reference<XResourceId>& rxPaneId)
117 {
118     ThrowIfDisposed();
119 
120     if ( ! rxPaneId.is())
121         return nullptr;
122 
123     const OUString sPaneURL (rxPaneId->getResourceURL());
124     if (sPaneURL.isEmpty())
125         return nullptr;
126 
127     if (mpResourceCache != nullptr)
128     {
129         // Has the requested resource already been created?
130         ResourceContainer::const_iterator iResource (mpResourceCache->find(sPaneURL));
131         if (iResource != mpResourceCache->end())
132         {
133             // Yes.  Mark it as active.
134             rtl::Reference<PresenterPaneContainer> pPaneContainer(
135                 mpPresenterController->GetPaneContainer());
136             PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
137                 pPaneContainer->FindPaneURL(sPaneURL));
138             if (pDescriptor)
139             {
140                 pDescriptor->SetActivationState(true);
141                 if (pDescriptor->mxBorderWindow.is())
142                     pDescriptor->mxBorderWindow->setVisible(true);
143                 pPaneContainer->StorePane(pDescriptor->mxPane);
144             }
145 
146             return iResource->second;
147         }
148     }
149 
150     // No.  Create a new one.
151     Reference<XResource> xResource = CreatePane(rxPaneId);
152     return xResource;
153 }
154 
releaseResource(const Reference<XResource> & rxResource)155 void SAL_CALL PresenterPaneFactory::releaseResource (const Reference<XResource>& rxResource)
156 {
157     ThrowIfDisposed();
158 
159     if ( ! rxResource.is())
160         throw lang::IllegalArgumentException();
161 
162     // Mark the pane as inactive.
163     rtl::Reference<PresenterPaneContainer> pPaneContainer(
164         mpPresenterController->GetPaneContainer());
165     const OUString sPaneURL (rxResource->getResourceId()->getResourceURL());
166     PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
167         pPaneContainer->FindPaneURL(sPaneURL));
168     if (!pDescriptor)
169         return;
170 
171     pDescriptor->SetActivationState(false);
172     if (pDescriptor->mxBorderWindow.is())
173         pDescriptor->mxBorderWindow->setVisible(false);
174 
175     if (mpResourceCache != nullptr)
176     {
177         // Store the pane in the cache.
178         (*mpResourceCache)[sPaneURL] = rxResource;
179     }
180     else
181     {
182         // Dispose the pane.
183         Reference<lang::XComponent> xPaneComponent (rxResource, UNO_QUERY);
184         if (xPaneComponent.is())
185             xPaneComponent->dispose();
186     }
187 }
188 
189 
CreatePane(const Reference<XResourceId> & rxPaneId)190 Reference<XResource> PresenterPaneFactory::CreatePane (
191     const Reference<XResourceId>& rxPaneId)
192 {
193     if ( ! rxPaneId.is())
194         return nullptr;
195 
196     Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
197     if ( ! xCC.is())
198         return nullptr;
199 
200     Reference<XComponentContext> xContext (mxComponentContextWeak);
201     if ( ! xContext.is())
202         return nullptr;
203 
204     Reference<XPane> xParentPane (xCC->getResource(rxPaneId->getAnchor()), UNO_QUERY);
205     if ( ! xParentPane.is())
206         return nullptr;
207 
208     try
209     {
210         return CreatePane(
211             rxPaneId,
212             xParentPane,
213             rxPaneId->getFullResourceURL().Arguments == "Sprite=1");
214     }
215     catch (Exception&)
216     {
217         OSL_ASSERT(false);
218     }
219 
220     return nullptr;
221 }
222 
CreatePane(const Reference<XResourceId> & rxPaneId,const Reference<drawing::framework::XPane> & rxParentPane,const bool bIsSpritePane)223 Reference<XResource> PresenterPaneFactory::CreatePane (
224     const Reference<XResourceId>& rxPaneId,
225     const Reference<drawing::framework::XPane>& rxParentPane,
226     const bool bIsSpritePane)
227 {
228     Reference<XComponentContext> xContext (mxComponentContextWeak);
229     Reference<lang::XMultiComponentFactory> xFactory (
230         xContext->getServiceManager(), UNO_SET_THROW);
231 
232     // Create a border window and canvas and store it in the pane
233     // container.
234 
235     // Create the pane.
236     ::rtl::Reference<PresenterPaneBase> xPane;
237     if (bIsSpritePane)
238     {
239         xPane.set( new PresenterSpritePane(xContext, mpPresenterController));
240     }
241     else
242     {
243         xPane.set( new PresenterPane(xContext, mpPresenterController));
244     }
245 
246     // Supply arguments.
247     Sequence<Any> aArguments (6);
248     aArguments[0] <<= rxPaneId;
249     aArguments[1] <<= rxParentPane->getWindow();
250     aArguments[2] <<= rxParentPane->getCanvas();
251     aArguments[3] <<= OUString();
252     aArguments[4] <<= Reference<drawing::framework::XPaneBorderPainter>(
253         static_cast<XWeak*>(mpPresenterController->GetPaneBorderPainter().get()),
254         UNO_QUERY);
255     aArguments[5] <<= !bIsSpritePane;
256     xPane->initialize(aArguments);
257 
258     // Store pane and canvases and windows in container.
259     ::rtl::Reference<PresenterPaneContainer> pContainer (
260         mpPresenterController->GetPaneContainer());
261     PresenterPaneContainer::SharedPaneDescriptor pDescriptor(
262         pContainer->StoreBorderWindow(rxPaneId, xPane->GetBorderWindow()));
263     pContainer->StorePane(xPane);
264     if (pDescriptor)
265     {
266         pDescriptor->mbIsSprite = bIsSpritePane;
267 
268         // Get the window of the frame and make that visible.
269         Reference<awt::XWindow> xWindow (pDescriptor->mxBorderWindow, UNO_SET_THROW);
270         xWindow->setVisible(true);
271     }
272 
273     return Reference<XResource>(static_cast<XWeak*>(xPane.get()), UNO_QUERY_THROW);
274 }
275 
ThrowIfDisposed() const276 void PresenterPaneFactory::ThrowIfDisposed() const
277 {
278     if (rBHelper.bDisposed || rBHelper.bInDispose)
279     {
280         throw lang::DisposedException (
281             "PresenterPaneFactory object has already been disposed",
282             const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
283     }
284 }
285 
286 } // end of namespace sdext::presenter
287 
288 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
289