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