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