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