xref: /AOO41X/main/sd/source/ui/framework/factories/BasicPaneFactory.cxx (revision 59ddfc10bd384e83978dcd8c83c4a7ba8f8fdec1)
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         RightPaneId
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), the center pane, and the right 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                 aDescriptor.msPaneURL = FrameworkHelper::msRightPaneURL;
236                 aDescriptor.mePaneId = RightPaneId;
237                 mpPaneContainer->push_back(aDescriptor);
238                 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
239             }
240 
241             // Register as configuration change listener.
242             if (xCC.is())
243             {
244                 xCC->addConfigurationChangeListener(
245                     this,
246                     FrameworkHelper::msConfigurationUpdateStartEvent,
247                     makeAny(gnConfigurationUpdateStartEvent));
248                 xCC->addConfigurationChangeListener(
249                     this,
250                     FrameworkHelper::msConfigurationUpdateEndEvent,
251                     makeAny(gnConfigurationUpdateEndEvent));
252             }
253         }
254         catch (RuntimeException&)
255         {
256             Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
257             if (xCC.is())
258                 xCC->removeResourceFactoryForReference(this);
259         }
260     }
261 }
262 
263 
264 
265 
266 //===== XPaneFactory ==========================================================
267 
268 Reference<XResource> SAL_CALL BasicPaneFactory::createResource (
269     const Reference<XResourceId>& rxPaneId)
270     throw (RuntimeException, IllegalArgumentException, WrappedTargetException)
271 {
272     ThrowIfDisposed();
273 
274     Reference<XResource> xPane;
275 
276     // Based on the ResourceURL of the given ResourceId look up the
277     // corresponding factory descriptor.
278     PaneContainer::iterator iDescriptor (
279         ::std::find_if (
280             mpPaneContainer->begin(),
281             mpPaneContainer->end(),
282             ::boost::bind(&PaneDescriptor::CompareURL, _1, rxPaneId->getResourceURL())));
283 
284     if (iDescriptor != mpPaneContainer->end())
285     {
286         if (iDescriptor->mxPane.is())
287         {
288             // The pane has already been created and is still active (has
289             // not yet been released).  This should not happen.
290             xPane = iDescriptor->mxPane;
291         }
292         else
293         {
294             // Create a new pane.
295             switch (iDescriptor->mePaneId)
296             {
297                 case CenterPaneId:
298                     xPane = CreateFrameWindowPane(rxPaneId);
299                     break;
300 
301                 case FullScreenPaneId:
302                     xPane = CreateFullScreenPane(mxComponentContext, rxPaneId);
303                     break;
304 
305                 case LeftImpressPaneId:
306                 case LeftDrawPaneId:
307                 case RightPaneId:
308                     xPane = CreateChildWindowPane(
309                         rxPaneId,
310                         *iDescriptor);
311                     break;
312             }
313             iDescriptor->mxPane = xPane;
314 
315             // Listen for the pane being disposed.
316             Reference<lang::XComponent> xComponent (xPane, UNO_QUERY);
317             if (xComponent.is())
318                 xComponent->addEventListener(this);
319         }
320         iDescriptor->mbIsReleased = false;
321     }
322     else
323     {
324         // The requested pane can not be created by any of the factories
325         // managed by the called BasicPaneFactory object.
326         throw lang::IllegalArgumentException(
327             ::rtl::OUString::createFromAscii(
328                 "BasicPaneFactory::createPane() called for unknown resource id"),
329             NULL,
330             0);
331     }
332 
333     return xPane;
334 }
335 
336 
337 
338 
339 
340 void SAL_CALL BasicPaneFactory::releaseResource (
341     const Reference<XResource>& rxPane)
342     throw (RuntimeException)
343 {
344     ThrowIfDisposed();
345 
346     // Based on the given XPane reference look up the corresponding factory
347     // descriptor.
348     PaneContainer::iterator iDescriptor (
349         ::std::find_if(
350             mpPaneContainer->begin(),
351             mpPaneContainer->end(),
352             ::boost::bind(&PaneDescriptor::ComparePane, _1, rxPane)));
353 
354     if (iDescriptor != mpPaneContainer->end())
355     {
356         // The given pane was created by one of the factories.  Child
357         // windows are just hidden and will be reused when requested later.
358         // Other windows are disposed and their reference is reset so that
359         // on the next createPane() call for the same pane type the pane is
360         // created anew.
361         ChildWindowPane* pChildWindowPane = dynamic_cast<ChildWindowPane*>(rxPane.get());
362         if (pChildWindowPane != NULL)
363         {
364             iDescriptor->mbIsReleased = true;
365             pChildWindowPane->Hide();
366         }
367         else
368         {
369             iDescriptor->mxPane = NULL;
370             Reference<XComponent> xComponent (rxPane, UNO_QUERY);
371             if (xComponent.is())
372             {
373                 // We are disposing the pane and do not have to be informed of
374                 // that.
375                 xComponent->removeEventListener(this);
376                 xComponent->dispose();
377             }
378         }
379     }
380     else
381     {
382         // The given XPane reference is either empty or the pane was not
383         // created by any of the factories managed by the called
384         // BasicPaneFactory object.
385         throw lang::IllegalArgumentException(
386             ::rtl::OUString::createFromAscii(
387                 "BasicPaneFactory::releasePane() called for pane that that was not created by same factory."),
388             NULL,
389             0);
390     }
391 }
392 
393 
394 
395 
396 //===== XConfigurationChangeListener ==========================================
397 
398 void SAL_CALL BasicPaneFactory::notifyConfigurationChange (
399     const ConfigurationChangeEvent& rEvent)
400     throw (RuntimeException)
401 {
402     sal_Int32 nEventType = 0;
403     rEvent.UserData >>= nEventType;
404     switch (nEventType)
405     {
406         case gnConfigurationUpdateStartEvent:
407             // Lock UI updates while we are switching the views except for
408             // the first time after creation.  Outherwise this leads to
409             // problems after reload (missing resizes for the side panes).
410             if (mbFirstUpdateSeen)
411             {
412                 if (mpUpdateLockManager.get()!=NULL)
413                 {
414                     //                    ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex());
415                     //                    mpUpdateLockManager->Lock();
416                 }
417             }
418             else
419                 mbFirstUpdateSeen = true;
420             break;
421 
422         case gnConfigurationUpdateEndEvent:
423             // Unlock the update lock here when only the visibility of
424             // windows but not the view shells displayed in them have
425             // changed.  Otherwise the UpdateLockManager takes care of
426             // unlocking at the right time.
427             if (mpUpdateLockManager.get() != NULL)
428             {
429                 ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex());
430                 //                if (mpUpdateLockManager->IsLocked())
431                 //                    mpUpdateLockManager->Unlock();
432             }
433             break;
434     }
435 }
436 
437 
438 
439 
440 //===== lang::XEventListener ==================================================
441 
442 void SAL_CALL BasicPaneFactory::disposing (
443     const lang::EventObject& rEventObject)
444     throw (RuntimeException)
445 {
446     if (mxConfigurationControllerWeak == rEventObject.Source)
447     {
448         mxConfigurationControllerWeak = Reference<XConfigurationController>();
449     }
450     else
451     {
452         // Has one of the panes been disposed?  If so, then release the
453         // reference to that pane, but not the pane descriptor.
454         Reference<XResource> xPane (rEventObject.Source, UNO_QUERY);
455         PaneContainer::iterator iDescriptor (
456             ::std::find_if (
457                 mpPaneContainer->begin(),
458                 mpPaneContainer->end(),
459                 ::boost::bind(&PaneDescriptor::ComparePane, _1, xPane)));
460         if (iDescriptor != mpPaneContainer->end())
461         {
462             iDescriptor->mxPane = NULL;
463         }
464     }
465 }
466 
467 
468 
469 
470 //-----------------------------------------------------------------------------
471 
472 Reference<XResource> BasicPaneFactory::CreateFrameWindowPane (
473     const Reference<XResourceId>& rxPaneId)
474 {
475     Reference<XResource> xPane;
476 
477     if (mpViewShellBase != NULL)
478     {
479         xPane = new FrameWindowPane(rxPaneId, mpViewShellBase->GetViewWindow());
480     }
481 
482     return xPane;
483 }
484 
485 
486 
487 
488 Reference<XResource> BasicPaneFactory::CreateFullScreenPane (
489     const Reference<XComponentContext>& rxComponentContext,
490     const Reference<XResourceId>& rxPaneId)
491 {
492     Reference<XResource> xPane (
493         new FullScreenPane(
494             rxComponentContext,
495             rxPaneId,
496             mpViewShellBase->GetViewWindow()));
497 
498     return xPane;
499 }
500 
501 
502 
503 
504 Reference<XResource> BasicPaneFactory::CreateChildWindowPane (
505     const Reference<XResourceId>& rxPaneId,
506     const PaneDescriptor& rDescriptor)
507 {
508     Reference<XResource> xPane;
509 
510     if (mpViewShellBase != NULL)
511     {
512         // Create the corresponding shell and determine the id of the child window.
513         sal_uInt16 nChildWindowId = 0;
514         ::std::auto_ptr<SfxShell> pShell;
515         switch (rDescriptor.mePaneId)
516         {
517             case LeftImpressPaneId:
518                 pShell.reset(new LeftImpressPaneShell());
519                 nChildWindowId = ::sd::LeftPaneImpressChildWindow::GetChildWindowId();
520                 break;
521 
522             case LeftDrawPaneId:
523                 pShell.reset(new LeftDrawPaneShell());
524                 nChildWindowId = ::sd::LeftPaneDrawChildWindow::GetChildWindowId();
525                 break;
526 
527             case RightPaneId:
528                 pShell.reset(new ToolPanelPaneShell());
529                 nChildWindowId = ::sd::ToolPanelChildWindow::GetChildWindowId();
530                 break;
531 
532             default:
533                 break;
534         }
535 
536         // With shell and child window id create the ChildWindowPane
537         // wrapper.
538         if (pShell.get() != NULL)
539         {
540             xPane = new ChildWindowPane(
541                 rxPaneId,
542                 nChildWindowId,
543                 *mpViewShellBase,
544                 pShell);
545         }
546     }
547 
548     return xPane;
549 }
550 
551 void BasicPaneFactory::ThrowIfDisposed (void) const
552     throw (lang::DisposedException)
553 {
554 	if (rBHelper.bDisposed || rBHelper.bInDispose)
555 	{
556         throw lang::DisposedException (
557             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
558                 "BasicPaneFactory object has already been disposed")),
559             const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
560     }
561 }
562 
563 
564 } } // end of namespace sd::framework
565