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