xref: /AOO41X/main/sd/source/ui/framework/factories/BasicPaneFactory.cxx (revision 7a32b0c888def1bf84d1d657c48953bc10dc00c1)
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 "BasicPaneFactory.hxx"
27 
28 #include "ChildWindowPane.hxx"
29 #include "FrameWindowPane.hxx"
30 #include "FullScreenPane.hxx"
31 
32 #include "framework/FrameworkHelper.hxx"
33 #include "ViewShellBase.hxx"
34 #include "PaneChildWindows.hxx"
35 #include "DrawController.hxx"
36 #include "DrawDocShell.hxx"
37 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
38 #include <boost/bind.hpp>
39 
40 
41 using namespace ::com::sun::star;
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::lang;
44 using namespace ::com::sun::star::drawing::framework;
45 
46 using ::rtl::OUString;
47 using ::sd::framework::FrameworkHelper;
48 
49 namespace {
50     enum PaneId {
51         CenterPaneId,
52         FullScreenPaneId,
53         LeftImpressPaneId,
54         LeftDrawPaneId,
55         SidebarPaneId
56     };
57 
58     static const sal_Int32 gnConfigurationUpdateStartEvent(0);
59     static const sal_Int32 gnConfigurationUpdateEndEvent(1);
60 }
61 
62 namespace sd { namespace framework {
63 
64 
65 /** Store URL, XPane reference and (local) PaneId for every pane factory
66     that is registered at the PaneController.
67 */
68 class BasicPaneFactory::PaneDescriptor
69 {
70 public:
71     OUString msPaneURL;
72     Reference<XResource> mxPane;
73     PaneId mePaneId;
74     /** The mbReleased flag is set when the pane has been released.  Some
75         panes are just hidden and destroyed.  When the pane is reused this
76         flag is reset.
77     */
78     bool mbIsReleased;
79     bool mbIsChildWindow;
80 
81     bool CompareURL (const OUString& rsPaneURL) { return msPaneURL.equals(rsPaneURL); }
82     bool ComparePane (const Reference<XResource>& rxPane) { return mxPane==rxPane; }
83 };
84 
85 
86 class BasicPaneFactory::PaneContainer
87     : public ::std::vector<PaneDescriptor>
88 {
89 public:
90     PaneContainer (void) {}
91 };
92 
93 
94 
95 Reference<XInterface> SAL_CALL BasicPaneFactory_createInstance (
96     const Reference<XComponentContext>& rxContext)
97 {
98     return Reference<XInterface>(static_cast<XWeak*>(new BasicPaneFactory(rxContext)));
99 }
100 
101 
102 
103 
104 ::rtl::OUString BasicPaneFactory_getImplementationName (void) throw(RuntimeException)
105 {
106     return ::rtl::OUString(
107         RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.framework.BasicPaneFactory"));
108 }
109 
110 
111 
112 
113 Sequence<rtl::OUString> SAL_CALL BasicPaneFactory_getSupportedServiceNames (void)
114     throw (RuntimeException)
115 {
116 	static const ::rtl::OUString sServiceName(
117         ::rtl::OUString::createFromAscii("com.sun.star.drawing.framework.BasicPaneFactory"));
118 	return Sequence<rtl::OUString>(&sServiceName, 1);
119 }
120 
121 
122 
123 
124 //===== PaneFactory ===========================================================
125 
126 BasicPaneFactory::BasicPaneFactory (
127     const Reference<XComponentContext>& rxContext)
128     : BasicPaneFactoryInterfaceBase(m_aMutex),
129       mxComponentContext(rxContext),
130       mxConfigurationControllerWeak(),
131       mpViewShellBase(NULL),
132       mpPaneContainer(new PaneContainer),
133       mbFirstUpdateSeen(false),
134       mpUpdateLockManager()
135 {
136 }
137 
138 
139 
140 
141 
142 BasicPaneFactory::~BasicPaneFactory (void)
143 {
144 }
145 
146 
147 
148 
149 void SAL_CALL BasicPaneFactory::disposing (void)
150 {
151     Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
152     if (xCC.is())
153     {
154         xCC->removeResourceFactoryForReference(this);
155         xCC->removeConfigurationChangeListener(this);
156         mxConfigurationControllerWeak = Reference<XConfigurationController>();
157     }
158 
159     for (PaneContainer::const_iterator iDescriptor = mpPaneContainer->begin();
160          iDescriptor != mpPaneContainer->end();
161          ++iDescriptor)
162     {
163         if (iDescriptor->mbIsReleased)
164         {
165             Reference<XComponent> xComponent (iDescriptor->mxPane, UNO_QUERY);
166             if (xComponent.is())
167             {
168                 xComponent->removeEventListener(this);
169                 xComponent->dispose();
170             }
171         }
172     }
173 }
174 
175 
176 
177 
178 void SAL_CALL BasicPaneFactory::initialize (const Sequence<Any>& aArguments)
179     throw (Exception, RuntimeException)
180 {
181     if (aArguments.getLength() > 0)
182     {
183         try
184         {
185             // Get the XController from the first argument.
186             Reference<frame::XController> xController (aArguments[0], UNO_QUERY_THROW);
187             mxControllerWeak = xController;
188 
189             // Tunnel through the controller to obtain access to the ViewShellBase.
190             try
191             {
192                 Reference<lang::XUnoTunnel> xTunnel (xController, UNO_QUERY_THROW);
193                 DrawController* pController
194                     = reinterpret_cast<DrawController*>(
195                         (sal::static_int_cast<sal_uIntPtr>(
196                             xTunnel->getSomething(DrawController::getUnoTunnelId()))));
197                 mpViewShellBase = pController->GetViewShellBase();
198                 mpUpdateLockManager = mpViewShellBase->GetUpdateLockManager();
199             }
200             catch(RuntimeException&)
201             {}
202 
203             Reference<XControllerManager> xCM (xController, UNO_QUERY_THROW);
204             Reference<XConfigurationController> xCC (xCM->getConfigurationController());
205             mxConfigurationControllerWeak = xCC;
206 
207             // Add pane factories for the two left panes (one for Impress and one for
208             // Draw) and the center pane.
209             if (xController.is() && xCC.is())
210             {
211                 PaneDescriptor aDescriptor;
212                 aDescriptor.msPaneURL = FrameworkHelper::msCenterPaneURL;
213                 aDescriptor.mePaneId = CenterPaneId;
214                 aDescriptor.mbIsReleased = false;
215                 aDescriptor.mbIsChildWindow = false;
216                 mpPaneContainer->push_back(aDescriptor);
217                 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
218 
219                 aDescriptor.msPaneURL = FrameworkHelper::msFullScreenPaneURL;
220                 aDescriptor.mePaneId = FullScreenPaneId;
221                 mpPaneContainer->push_back(aDescriptor);
222                 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
223 
224                 aDescriptor.msPaneURL = FrameworkHelper::msLeftImpressPaneURL;
225                 aDescriptor.mePaneId = LeftImpressPaneId;
226                 aDescriptor.mbIsChildWindow = true;
227                 mpPaneContainer->push_back(aDescriptor);
228                 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
229 
230                 aDescriptor.msPaneURL = FrameworkHelper::msLeftDrawPaneURL;
231                 aDescriptor.mePaneId = LeftDrawPaneId;
232                 mpPaneContainer->push_back(aDescriptor);
233                 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
234             }
235 
236             // Register as configuration change listener.
237             if (xCC.is())
238             {
239                 xCC->addConfigurationChangeListener(
240                     this,
241                     FrameworkHelper::msConfigurationUpdateStartEvent,
242                     makeAny(gnConfigurationUpdateStartEvent));
243                 xCC->addConfigurationChangeListener(
244                     this,
245                     FrameworkHelper::msConfigurationUpdateEndEvent,
246                     makeAny(gnConfigurationUpdateEndEvent));
247             }
248         }
249         catch (RuntimeException&)
250         {
251             Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
252             if (xCC.is())
253                 xCC->removeResourceFactoryForReference(this);
254         }
255     }
256 }
257 
258 
259 
260 
261 //===== XPaneFactory ==========================================================
262 
263 Reference<XResource> SAL_CALL BasicPaneFactory::createResource (
264     const Reference<XResourceId>& rxPaneId)
265     throw (RuntimeException, IllegalArgumentException, WrappedTargetException)
266 {
267     ThrowIfDisposed();
268 
269     Reference<XResource> xPane;
270 
271     // Based on the ResourceURL of the given ResourceId look up the
272     // corresponding factory descriptor.
273     PaneContainer::iterator iDescriptor (
274         ::std::find_if (
275             mpPaneContainer->begin(),
276             mpPaneContainer->end(),
277             ::boost::bind(&PaneDescriptor::CompareURL, _1, rxPaneId->getResourceURL())));
278 
279     if (iDescriptor != mpPaneContainer->end())
280     {
281         if (iDescriptor->mxPane.is())
282         {
283             // The pane has already been created and is still active (has
284             // not yet been released).  This should not happen.
285             xPane = iDescriptor->mxPane;
286         }
287         else
288         {
289             // Create a new pane.
290             switch (iDescriptor->mePaneId)
291             {
292                 case CenterPaneId:
293                     xPane = CreateFrameWindowPane(rxPaneId);
294                     break;
295 
296                 case FullScreenPaneId:
297                     xPane = CreateFullScreenPane(mxComponentContext, rxPaneId);
298                     break;
299 
300                 case LeftImpressPaneId:
301                 case LeftDrawPaneId:
302                     xPane = CreateChildWindowPane(
303                         rxPaneId,
304                         *iDescriptor);
305                     break;
306             }
307             iDescriptor->mxPane = xPane;
308 
309             // Listen for the pane being disposed.
310             Reference<lang::XComponent> xComponent (xPane, UNO_QUERY);
311             if (xComponent.is())
312                 xComponent->addEventListener(this);
313         }
314         iDescriptor->mbIsReleased = false;
315     }
316     else
317     {
318         // The requested pane can not be created by any of the factories
319         // managed by the called BasicPaneFactory object.
320         throw lang::IllegalArgumentException(
321             ::rtl::OUString::createFromAscii(
322                 "BasicPaneFactory::createPane() called for unknown resource id"),
323             NULL,
324             0);
325     }
326 
327     return xPane;
328 }
329 
330 
331 
332 
333 
334 void SAL_CALL BasicPaneFactory::releaseResource (
335     const Reference<XResource>& rxPane)
336     throw (RuntimeException)
337 {
338     ThrowIfDisposed();
339 
340     // Based on the given XPane reference look up the corresponding factory
341     // descriptor.
342     PaneContainer::iterator iDescriptor (
343         ::std::find_if(
344             mpPaneContainer->begin(),
345             mpPaneContainer->end(),
346             ::boost::bind(&PaneDescriptor::ComparePane, _1, rxPane)));
347 
348     if (iDescriptor != mpPaneContainer->end())
349     {
350         // The given pane was created by one of the factories.  Child
351         // windows are just hidden and will be reused when requested later.
352         // Other windows are disposed and their reference is reset so that
353         // on the next createPane() call for the same pane type the pane is
354         // created anew.
355         ChildWindowPane* pChildWindowPane = dynamic_cast<ChildWindowPane*>(rxPane.get());
356         if (pChildWindowPane != NULL)
357         {
358             iDescriptor->mbIsReleased = true;
359             pChildWindowPane->Hide();
360         }
361         else
362         {
363             iDescriptor->mxPane = NULL;
364             Reference<XComponent> xComponent (rxPane, UNO_QUERY);
365             if (xComponent.is())
366             {
367                 // We are disposing the pane and do not have to be informed of
368                 // that.
369                 xComponent->removeEventListener(this);
370                 xComponent->dispose();
371             }
372         }
373     }
374     else
375     {
376         // The given XPane reference is either empty or the pane was not
377         // created by any of the factories managed by the called
378         // BasicPaneFactory object.
379         throw lang::IllegalArgumentException(
380             ::rtl::OUString::createFromAscii(
381                 "BasicPaneFactory::releasePane() called for pane that that was not created by same factory."),
382             NULL,
383             0);
384     }
385 }
386 
387 
388 
389 
390 //===== XConfigurationChangeListener ==========================================
391 
392 void SAL_CALL BasicPaneFactory::notifyConfigurationChange (
393     const ConfigurationChangeEvent& rEvent)
394     throw (RuntimeException)
395 {
396     sal_Int32 nEventType = 0;
397     rEvent.UserData >>= nEventType;
398     switch (nEventType)
399     {
400         case gnConfigurationUpdateStartEvent:
401             // Lock UI updates while we are switching the views except for
402             // the first time after creation.  Outherwise this leads to
403             // problems after reload (missing resizes for the side panes).
404             if (mbFirstUpdateSeen)
405             {
406                 if (mpUpdateLockManager.get()!=NULL)
407                 {
408                     //                    ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex());
409                     //                    mpUpdateLockManager->Lock();
410                 }
411             }
412             else
413                 mbFirstUpdateSeen = true;
414             break;
415 
416         case gnConfigurationUpdateEndEvent:
417             // Unlock the update lock here when only the visibility of
418             // windows but not the view shells displayed in them have
419             // changed.  Otherwise the UpdateLockManager takes care of
420             // unlocking at the right time.
421             if (mpUpdateLockManager.get() != NULL)
422             {
423                 ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex());
424                 //                if (mpUpdateLockManager->IsLocked())
425                 //                    mpUpdateLockManager->Unlock();
426             }
427             break;
428     }
429 }
430 
431 
432 
433 
434 //===== lang::XEventListener ==================================================
435 
436 void SAL_CALL BasicPaneFactory::disposing (
437     const lang::EventObject& rEventObject)
438     throw (RuntimeException)
439 {
440     if (mxConfigurationControllerWeak == rEventObject.Source)
441     {
442         mxConfigurationControllerWeak = Reference<XConfigurationController>();
443     }
444     else
445     {
446         // Has one of the panes been disposed?  If so, then release the
447         // reference to that pane, but not the pane descriptor.
448         Reference<XResource> xPane (rEventObject.Source, UNO_QUERY);
449         PaneContainer::iterator iDescriptor (
450             ::std::find_if (
451                 mpPaneContainer->begin(),
452                 mpPaneContainer->end(),
453                 ::boost::bind(&PaneDescriptor::ComparePane, _1, xPane)));
454         if (iDescriptor != mpPaneContainer->end())
455         {
456             iDescriptor->mxPane = NULL;
457         }
458     }
459 }
460 
461 
462 
463 
464 //-----------------------------------------------------------------------------
465 
466 Reference<XResource> BasicPaneFactory::CreateFrameWindowPane (
467     const Reference<XResourceId>& rxPaneId)
468 {
469     Reference<XResource> xPane;
470 
471     if (mpViewShellBase != NULL)
472     {
473         xPane = new FrameWindowPane(rxPaneId, mpViewShellBase->GetViewWindow());
474     }
475 
476     return xPane;
477 }
478 
479 
480 
481 
482 Reference<XResource> BasicPaneFactory::CreateFullScreenPane (
483     const Reference<XComponentContext>& rxComponentContext,
484     const Reference<XResourceId>& rxPaneId)
485 {
486     Reference<XResource> xPane (
487         new FullScreenPane(
488             rxComponentContext,
489             rxPaneId,
490             mpViewShellBase->GetViewWindow()));
491 
492     return xPane;
493 }
494 
495 
496 
497 
498 Reference<XResource> BasicPaneFactory::CreateChildWindowPane (
499     const Reference<XResourceId>& rxPaneId,
500     const PaneDescriptor& rDescriptor)
501 {
502     Reference<XResource> xPane;
503 
504     if (mpViewShellBase != NULL)
505     {
506         // Create the corresponding shell and determine the id of the child window.
507         sal_uInt16 nChildWindowId = 0;
508         ::std::auto_ptr<SfxShell> pShell;
509         switch (rDescriptor.mePaneId)
510         {
511             case LeftImpressPaneId:
512                 pShell.reset(new LeftImpressPaneShell());
513                 nChildWindowId = ::sd::LeftPaneImpressChildWindow::GetChildWindowId();
514                 break;
515 
516             case LeftDrawPaneId:
517                 pShell.reset(new LeftDrawPaneShell());
518                 nChildWindowId = ::sd::LeftPaneDrawChildWindow::GetChildWindowId();
519                 break;
520 
521             default:
522                 break;
523         }
524 
525         // With shell and child window id create the ChildWindowPane
526         // wrapper.
527         if (pShell.get() != NULL)
528         {
529             xPane = new ChildWindowPane(
530                 rxPaneId,
531                 nChildWindowId,
532                 *mpViewShellBase,
533                 pShell);
534         }
535     }
536 
537     return xPane;
538 }
539 
540 void BasicPaneFactory::ThrowIfDisposed (void) const
541     throw (lang::DisposedException)
542 {
543 	if (rBHelper.bDisposed || rBHelper.bInDispose)
544 	{
545         throw lang::DisposedException (
546             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
547                 "BasicPaneFactory object has already been disposed")),
548             const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
549     }
550 }
551 
552 
553 } } // end of namespace sd::framework
554