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