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