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