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