xref: /AOO41X/main/sd/source/ui/framework/factories/BasicViewFactory.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 "BasicViewFactory.hxx"
31 
32 #include "framework/ViewShellWrapper.hxx"
33 #include "framework/FrameworkHelper.hxx"
34 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
35 #include <com/sun/star/lang/IllegalArgumentException.hpp>
36 #include "framework/Pane.hxx"
37 #include "DrawController.hxx"
38 #include "DrawSubController.hxx"
39 #include "ViewShellBase.hxx"
40 #include "ViewShellManager.hxx"
41 #include "DrawDocShell.hxx"
42 #include "DrawViewShell.hxx"
43 #include "GraphicViewShell.hxx"
44 #include "OutlineViewShell.hxx"
45 #include "taskpane/ToolPanelViewShell.hxx"
46 #include "PresentationViewShell.hxx"
47 #include "SlideSorterViewShell.hxx"
48 #include "FrameView.hxx"
49 
50 #include <sfx2/viewfrm.hxx>
51 #include <vcl/wrkwin.hxx>
52 #include <toolkit/helper/vclunohelper.hxx>
53 
54 #include <boost/bind.hpp>
55 
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::uno;
58 using namespace ::com::sun::star::lang;
59 using namespace ::com::sun::star::drawing::framework;
60 
61 using ::rtl::OUString;
62 using ::sd::framework::FrameworkHelper;
63 
64 
65 namespace sd { namespace framework {
66 
67 
68 Reference<XInterface> SAL_CALL BasicViewFactory_createInstance (
69     const Reference<XComponentContext>& rxContext)
70 {
71     return Reference<XInterface>(static_cast<XWeak*>(new BasicViewFactory(rxContext)));
72 }
73 
74 
75 
76 
77 ::rtl::OUString BasicViewFactory_getImplementationName (void) throw(RuntimeException)
78 {
79     return ::rtl::OUString(
80         RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.framework.BasicViewFactory"));
81 }
82 
83 
84 
85 
86 Sequence<rtl::OUString> SAL_CALL BasicViewFactory_getSupportedServiceNames (void)
87     throw (RuntimeException)
88 {
89 	static const ::rtl::OUString sServiceName(
90         ::rtl::OUString::createFromAscii("com.sun.star.drawing.framework.BasicViewFactory"));
91 	return Sequence<rtl::OUString>(&sServiceName, 1);
92 }
93 
94 
95 
96 
97 //===== ViewDescriptor ========================================================
98 
99 class BasicViewFactory::ViewDescriptor
100 {
101 public:
102     Reference<XResource> mxView;
103     ::boost::shared_ptr<sd::ViewShell> mpViewShell;
104     ViewShellWrapper* mpWrapper;
105     Reference<XResourceId> mxViewId;
106     static bool CompareView (const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor,
107         const Reference<XResource>& rxView)
108     { return rpDescriptor->mxView.get() == rxView.get(); }
109 };
110 
111 
112 
113 
114 
115 //===== BasicViewFactory::ViewShellContainer ==================================
116 
117 class BasicViewFactory::ViewShellContainer
118     : public ::std::vector<boost::shared_ptr<ViewDescriptor> >
119 {
120 public:
121     ViewShellContainer (void) {};
122 };
123 
124 
125 class BasicViewFactory::ViewCache
126     : public ::std::vector<boost::shared_ptr<ViewDescriptor> >
127 {
128 public:
129     ViewCache (void) {};
130 };
131 
132 
133 
134 
135 //===== ViewFactory ===========================================================
136 
137 BasicViewFactory::BasicViewFactory (
138     const Reference<XComponentContext>& rxContext)
139     : BasicViewFactoryInterfaceBase(MutexOwner::maMutex),
140       mxConfigurationController(),
141       mpViewShellContainer(new ViewShellContainer()),
142       mpBase(NULL),
143       mpFrameView(NULL),
144       mpWindow(new WorkWindow(NULL,WB_STDWORK)),
145       mpViewCache(new ViewCache()),
146       mxLocalPane(new Pane(Reference<XResourceId>(), mpWindow.get()))
147 {
148     (void)rxContext;
149 }
150 
151 
152 
153 
154 BasicViewFactory::~BasicViewFactory (void)
155 {
156 }
157 
158 
159 
160 
161 void SAL_CALL BasicViewFactory::disposing (void)
162 {
163     // Disconnect from the frame view.
164     if (mpFrameView != NULL)
165     {
166         mpFrameView->Disconnect();
167         mpFrameView = NULL;
168     }
169 
170     // Relase the view cache.
171     ViewShellContainer::const_iterator iView;
172     for (iView=mpViewCache->begin(); iView!=mpViewCache->end(); ++iView)
173     {
174         ReleaseView(*iView, true);
175     }
176 
177     // Release the view shell container.  At this point no one other than us
178     // should hold references to the view shells (at the moment this is a
179     // trivial requirement, because no one other then us holds a shared
180     // pointer).
181     //    ViewShellContainer::const_iterator iView;
182     for (iView=mpViewShellContainer->begin(); iView!=mpViewShellContainer->end(); ++iView)
183     {
184         OSL_ASSERT((*iView)->mpViewShell.unique());
185     }
186     mpViewShellContainer.reset();
187 }
188 
189 
190 
191 
192 Reference<XResource> SAL_CALL BasicViewFactory::createResource (
193     const Reference<XResourceId>& rxViewId)
194     throw(RuntimeException, IllegalArgumentException, WrappedTargetException)
195 {
196     Reference<XResource> xView;
197     const bool bIsCenterPane (
198         rxViewId->isBoundToURL(FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT));
199 
200     // Get the pane for the anchor URL.
201     Reference<XPane> xPane;
202     if (mxConfigurationController.is())
203         xPane = Reference<XPane>(mxConfigurationController->getResource(rxViewId->getAnchor()),
204             UNO_QUERY);
205 
206     // For main views use the frame view of the last main view.
207     ::sd::FrameView* pFrameView = NULL;
208     if (xPane.is() && bIsCenterPane)
209     {
210         pFrameView = mpFrameView;
211     }
212 
213     // Get Window pointer for XWindow of the pane.
214     ::Window* pWindow = NULL;
215     if (xPane.is())
216         pWindow = VCLUnoHelper::GetWindow(xPane->getWindow());
217 
218     // Get the view frame.
219     SfxViewFrame* pFrame = NULL;
220     if (mpBase != NULL)
221         pFrame = mpBase->GetViewFrame();
222 
223     if (pFrame != NULL && mpBase!=NULL && pWindow!=NULL)
224     {
225         // Try to get the view from the cache.
226         ::boost::shared_ptr<ViewDescriptor> pDescriptor (GetViewFromCache(rxViewId, xPane));
227 
228         // When the requested view is not in the cache then create a new view.
229         if (pDescriptor.get() == NULL)
230         {
231             pDescriptor = CreateView(rxViewId, *pFrame, *pWindow, xPane, pFrameView, bIsCenterPane);
232         }
233 
234         if (pDescriptor.get() != NULL)
235             xView = pDescriptor->mxView;
236 
237         mpViewShellContainer->push_back(pDescriptor);
238 
239         if (bIsCenterPane)
240             ActivateCenterView(pDescriptor);
241         else
242             pWindow->Resize();
243     }
244 
245     return xView;
246 }
247 
248 
249 
250 
251 void SAL_CALL BasicViewFactory::releaseResource (const Reference<XResource>& rxView)
252     throw(RuntimeException)
253 {
254     if ( ! rxView.is())
255         throw lang::IllegalArgumentException();
256 
257     if (rxView.is() && mpBase!=NULL)
258     {
259         ViewShellContainer::iterator iViewShell (
260             ::std::find_if(
261                 mpViewShellContainer->begin(),
262                 mpViewShellContainer->end(),
263                 ::boost::bind(&ViewDescriptor::CompareView, _1, rxView)));
264         if (iViewShell != mpViewShellContainer->end())
265         {
266             ::boost::shared_ptr<ViewShell> pViewShell ((*iViewShell)->mpViewShell);
267 
268             if ((*iViewShell)->mxViewId->isBoundToURL(
269                 FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT))
270             {
271                 // Obtain a pointer to and connect to the frame view of the
272                 // view.  The next view, that is created, will be
273                 // initialized with this frame view.
274                 if (mpFrameView == NULL)
275                 {
276                     mpFrameView = pViewShell->GetFrameView();
277                     if (mpFrameView)
278                         mpFrameView->Connect();
279                 }
280 
281                 // With the view in the center pane the sub controller is
282                 // released, too.
283                 mpBase->GetDrawController().SetSubController(
284                     Reference<drawing::XDrawSubController>());
285 
286                 SfxViewShell* pSfxViewShell = pViewShell->GetViewShell();
287                 if (pSfxViewShell != NULL)
288                     pSfxViewShell->DisconnectAllClients();
289             }
290 
291             ReleaseView(*iViewShell);
292 
293             mpViewShellContainer->erase(iViewShell);
294         }
295         else
296         {
297             throw lang::IllegalArgumentException();
298         }
299     }
300 }
301 
302 
303 
304 
305 void SAL_CALL BasicViewFactory::initialize (const Sequence<Any>& aArguments)
306     throw (Exception, RuntimeException)
307 {
308     if (aArguments.getLength() > 0)
309     {
310         Reference<XConfigurationController> xCC;
311         try
312         {
313             // Get the XController from the first argument.
314             Reference<frame::XController> xController (aArguments[0], UNO_QUERY_THROW);
315 
316             // Tunnel through the controller to obtain a ViewShellBase.
317             Reference<lang::XUnoTunnel> xTunnel (xController, UNO_QUERY_THROW);
318             ::sd::DrawController* pController = reinterpret_cast<sd::DrawController*>(
319                 xTunnel->getSomething(sd::DrawController::getUnoTunnelId()));
320             if (pController != NULL)
321                 mpBase = pController->GetViewShellBase();
322 
323             // Register the factory for its supported views.
324             Reference<XControllerManager> xCM (xController,UNO_QUERY_THROW);
325             mxConfigurationController = xCM->getConfigurationController();
326             if ( ! mxConfigurationController.is())
327                 throw RuntimeException();
328             mxConfigurationController->addResourceFactory(FrameworkHelper::msImpressViewURL, this);
329             mxConfigurationController->addResourceFactory(FrameworkHelper::msDrawViewURL, this);
330             mxConfigurationController->addResourceFactory(FrameworkHelper::msOutlineViewURL, this);
331             mxConfigurationController->addResourceFactory(FrameworkHelper::msNotesViewURL, this);
332             mxConfigurationController->addResourceFactory(FrameworkHelper::msHandoutViewURL, this);
333             mxConfigurationController->addResourceFactory(FrameworkHelper::msPresentationViewURL, this);
334             mxConfigurationController->addResourceFactory(FrameworkHelper::msTaskPaneURL, this);
335             mxConfigurationController->addResourceFactory(FrameworkHelper::msSlideSorterURL, this);
336         }
337         catch (RuntimeException&)
338         {
339             mpBase = NULL;
340             if (mxConfigurationController.is())
341                 mxConfigurationController->removeResourceFactoryForReference(this);
342             throw;
343         }
344     }
345 }
346 
347 
348 
349 
350 ::boost::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::CreateView (
351     const Reference<XResourceId>& rxViewId,
352     SfxViewFrame& rFrame,
353     ::Window& rWindow,
354     const Reference<XPane>& rxPane,
355     FrameView* pFrameView,
356     const bool bIsCenterPane)
357 {
358     ::boost::shared_ptr<ViewDescriptor> pDescriptor (new ViewDescriptor());
359 
360     pDescriptor->mpViewShell = CreateViewShell(
361         rxViewId,
362         rFrame,
363         rWindow,
364         pFrameView,
365         bIsCenterPane);
366     pDescriptor->mxViewId = rxViewId;
367 
368     if (pDescriptor->mpViewShell.get() != NULL)
369     {
370         pDescriptor->mpViewShell->Init(bIsCenterPane);
371         mpBase->GetViewShellManager()->ActivateViewShell(pDescriptor->mpViewShell.get());
372 
373         pDescriptor->mpWrapper = new ViewShellWrapper(
374             pDescriptor->mpViewShell,
375             rxViewId,
376             rxPane->getWindow());
377         pDescriptor->mxView.set( pDescriptor->mpWrapper->queryInterface( XResource::static_type() ), UNO_QUERY_THROW );
378     }
379 
380     return pDescriptor;
381 }
382 
383 
384 
385 
386 ::boost::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell (
387     const Reference<XResourceId>& rxViewId,
388     SfxViewFrame& rFrame,
389     ::Window& rWindow,
390     FrameView* pFrameView,
391     const bool bIsCenterPane)
392 {
393     ::boost::shared_ptr<ViewShell> pViewShell;
394     const OUString& rsViewURL (rxViewId->getResourceURL());
395     if (rsViewURL.equals(FrameworkHelper::msImpressViewURL))
396     {
397         pViewShell.reset(
398             new DrawViewShell(
399                 &rFrame,
400                 *mpBase,
401                 &rWindow,
402                 PK_STANDARD,
403                 pFrameView));
404     }
405     else if (rsViewURL.equals(FrameworkHelper::msDrawViewURL))
406     {
407         pViewShell.reset(
408             new GraphicViewShell (
409                 &rFrame,
410                 *mpBase,
411                 &rWindow,
412                 pFrameView));
413     }
414     else if (rsViewURL.equals(FrameworkHelper::msOutlineViewURL))
415     {
416         pViewShell.reset(
417             new OutlineViewShell (
418                 &rFrame,
419                 *mpBase,
420                 &rWindow,
421                 pFrameView));
422     }
423     else if (rsViewURL.equals(FrameworkHelper::msNotesViewURL))
424     {
425         pViewShell.reset(
426             new DrawViewShell(
427                 &rFrame,
428                 *mpBase,
429                 &rWindow,
430                 PK_NOTES,
431                 pFrameView));
432     }
433     else if (rsViewURL.equals(FrameworkHelper::msHandoutViewURL))
434     {
435         pViewShell.reset(
436             new DrawViewShell(
437                 &rFrame,
438                 *mpBase,
439                 &rWindow,
440                 PK_HANDOUT,
441                 pFrameView));
442     }
443     else if (rsViewURL.equals(FrameworkHelper::msPresentationViewURL))
444     {
445         pViewShell.reset(
446             new PresentationViewShell(
447                 &rFrame,
448                 *mpBase,
449                 &rWindow,
450                 pFrameView));
451     }
452     else if (rsViewURL.equals(FrameworkHelper::msTaskPaneURL))
453     {
454         pViewShell.reset(
455             new ::sd::toolpanel::ToolPanelViewShell(
456                 &rFrame,
457                 *mpBase,
458                 &rWindow,
459                 pFrameView));
460     }
461     else if (rsViewURL.equals(FrameworkHelper::msSlideSorterURL))
462     {
463         pViewShell = ::sd::slidesorter::SlideSorterViewShell::Create (
464             &rFrame,
465             *mpBase,
466             &rWindow,
467             pFrameView,
468             bIsCenterPane);
469     }
470 
471     return pViewShell;
472 }
473 
474 
475 
476 
477 void BasicViewFactory::ReleaseView (
478     const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor,
479     bool bDoNotCache)
480 {
481     bool bIsCacheable (!bDoNotCache && IsCacheable(rpDescriptor));
482 
483     if (bIsCacheable)
484     {
485         Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY);
486         if (xResource.is())
487         {
488             Reference<XResource> xNewAnchor (mxLocalPane, UNO_QUERY);
489             if (xNewAnchor.is())
490                 if (xResource->relocateToAnchor(xNewAnchor))
491                     mpViewCache->push_back(rpDescriptor);
492                 else
493                     bIsCacheable = false;
494             else
495                 bIsCacheable = false;
496         }
497         else
498         {
499             bIsCacheable = false;
500         }
501     }
502 
503     if ( ! bIsCacheable)
504     {
505         // Shut down the current view shell.
506         rpDescriptor->mpViewShell->Shutdown ();
507         mpBase->GetDocShell()->Disconnect(rpDescriptor->mpViewShell.get());
508         mpBase->GetViewShellManager()->DeactivateViewShell(rpDescriptor->mpViewShell.get());
509 
510         Reference<XComponent> xComponent (rpDescriptor->mxView, UNO_QUERY);
511         if (xComponent.is())
512             xComponent->dispose();
513     }
514 }
515 
516 
517 
518 
519 bool BasicViewFactory::IsCacheable (const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor)
520 {
521     bool bIsCacheable (false);
522 
523     Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY);
524     if (xResource.is())
525     {
526         static ::std::vector<Reference<XResourceId> > maCacheableResources;
527         if (maCacheableResources.empty() )
528         {
529             ::boost::shared_ptr<FrameworkHelper> pHelper (FrameworkHelper::Instance(*mpBase));
530 
531             // The slide sorter and the task panel are cacheable and relocatable.
532             maCacheableResources.push_back(pHelper->CreateResourceId(
533                 FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftDrawPaneURL));
534             maCacheableResources.push_back(pHelper->CreateResourceId(
535                 FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftImpressPaneURL));
536             maCacheableResources.push_back(pHelper->CreateResourceId(
537                 FrameworkHelper::msTaskPaneURL, FrameworkHelper::msRightPaneURL));
538         }
539 
540         ::std::vector<Reference<XResourceId> >::const_iterator iId;
541         for (iId=maCacheableResources.begin(); iId!=maCacheableResources.end(); ++iId)
542         {
543             if ((*iId)->compareTo(rpDescriptor->mxViewId) == 0)
544             {
545                 bIsCacheable = true;
546                 break;
547             }
548         }
549     }
550 
551     return bIsCacheable;
552 }
553 
554 
555 
556 
557 ::boost::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::GetViewFromCache (
558     const Reference<XResourceId>& rxViewId,
559     const Reference<XPane>& rxPane)
560 {
561     ::boost::shared_ptr<ViewDescriptor> pDescriptor;
562 
563     // Search for the requested view in the cache.
564     ViewCache::iterator iEntry;
565     for (iEntry=mpViewCache->begin(); iEntry!=mpViewCache->end(); ++iEntry)
566     {
567         if ((*iEntry)->mxViewId->compareTo(rxViewId) == 0)
568         {
569             pDescriptor = *iEntry;
570             mpViewCache->erase(iEntry);
571             break;
572         }
573     }
574 
575     // When the view has been found then relocate it to the given pane and
576     // remove it from the cache.
577     if (pDescriptor.get() != NULL)
578     {
579         bool bRelocationSuccessfull (false);
580         Reference<XRelocatableResource> xResource (pDescriptor->mxView, UNO_QUERY);
581         Reference<XResource> xNewAnchor (rxPane, UNO_QUERY);
582         if (xResource.is() && xNewAnchor.is())
583         {
584             if (xResource->relocateToAnchor(xNewAnchor))
585                 bRelocationSuccessfull = true;
586         }
587 
588         if ( ! bRelocationSuccessfull)
589         {
590             ReleaseView(pDescriptor, true);
591             pDescriptor.reset();
592         }
593     }
594 
595     return pDescriptor;
596 }
597 
598 
599 
600 
601 void BasicViewFactory::ActivateCenterView (
602     const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor)
603 {
604     mpBase->GetDocShell()->Connect(rpDescriptor->mpViewShell.get());
605 
606     // During the creation of the new sub-shell, resize requests were not
607     // forwarded to it because it was not yet registered.  Therefore, we
608     // have to request a resize now.
609     rpDescriptor->mpViewShell->UIFeatureChanged();
610     if (mpBase->GetDocShell()->IsInPlaceActive())
611         mpBase->GetViewFrame()->Resize(sal_True);
612 
613     mpBase->GetDrawController().SetSubController(
614         rpDescriptor->mpViewShell->CreateSubController());
615 }
616 
617 } } // end of namespace sd::framework
618