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