bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / framework / factories / BasicViewFactory.cxx
blob065499bac8e5a354e7ea4b865ba2c7dffce06974
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "BasicViewFactory.hxx"
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"
40 #include <sfx2/viewfrm.hxx>
41 #include <vcl/wrkwin.hxx>
42 #include <toolkit/helper/vclunohelper.hxx>
44 #include <boost/bind.hpp>
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;
51 using ::sd::framework::FrameworkHelper;
53 namespace sd { namespace framework {
55 //===== ViewDescriptor ========================================================
57 class BasicViewFactory::ViewDescriptor
59 public:
60 Reference<XResource> mxView;
61 ::boost::shared_ptr<sd::ViewShell> mpViewShell;
62 ViewShellWrapper* mpWrapper;
63 Reference<XResourceId> mxViewId;
64 static bool CompareView (const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor,
65 const Reference<XResource>& rxView)
66 { return rpDescriptor->mxView.get() == rxView.get(); }
69 //===== BasicViewFactory::ViewShellContainer ==================================
71 class BasicViewFactory::ViewShellContainer
72 : public ::std::vector<boost::shared_ptr<ViewDescriptor> >
74 public:
75 ViewShellContainer() {};
78 class BasicViewFactory::ViewCache
79 : public ::std::vector<boost::shared_ptr<ViewDescriptor> >
81 public:
82 ViewCache() {};
85 //===== ViewFactory ===========================================================
87 BasicViewFactory::BasicViewFactory (
88 const Reference<XComponentContext>& rxContext)
89 : BasicViewFactoryInterfaceBase(MutexOwner::maMutex),
90 mxConfigurationController(),
91 mpViewShellContainer(new ViewShellContainer()),
92 mpBase(NULL),
93 mpFrameView(NULL),
94 mpWindow(VclPtr<WorkWindow>::Create(nullptr,WB_STDWORK)),
95 mpViewCache(new ViewCache()),
96 mxLocalPane(new Pane(Reference<XResourceId>(), mpWindow.get()))
98 (void)rxContext;
101 BasicViewFactory::~BasicViewFactory()
105 void SAL_CALL BasicViewFactory::disposing()
107 // Disconnect from the frame view.
108 if (mpFrameView != NULL)
110 mpFrameView->Disconnect();
111 mpFrameView = NULL;
114 // Relase the view cache.
115 ViewShellContainer::const_iterator iView;
116 for (iView=mpViewCache->begin(); iView!=mpViewCache->end(); ++iView)
118 ReleaseView(*iView, true);
121 // Release the view shell container. At this point no one other than us
122 // should hold references to the view shells (at the moment this is a
123 // trivial requirement, because no one other then us holds a shared
124 // pointer).
125 // ViewShellContainer::const_iterator iView;
126 for (iView=mpViewShellContainer->begin(); iView!=mpViewShellContainer->end(); ++iView)
128 OSL_ASSERT((*iView)->mpViewShell.unique());
130 mpViewShellContainer.reset();
133 Reference<XResource> SAL_CALL BasicViewFactory::createResource (
134 const Reference<XResourceId>& rxViewId)
135 throw(RuntimeException, IllegalArgumentException, WrappedTargetException, std::exception)
137 Reference<XResource> xView;
138 const bool bIsCenterPane (
139 rxViewId->isBoundToURL(FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT));
141 // Get the pane for the anchor URL.
142 Reference<XPane> xPane;
143 if (mxConfigurationController.is())
144 xPane = Reference<XPane>(mxConfigurationController->getResource(rxViewId->getAnchor()),
145 UNO_QUERY);
147 // For main views use the frame view of the last main view.
148 ::sd::FrameView* pFrameView = NULL;
149 if (xPane.is() && bIsCenterPane)
151 pFrameView = mpFrameView;
154 // Get Window pointer for XWindow of the pane.
155 vcl::Window* pWindow = NULL;
156 if (xPane.is())
157 pWindow = VCLUnoHelper::GetWindow(xPane->getWindow());
159 // Get the view frame.
160 SfxViewFrame* pFrame = NULL;
161 if (mpBase != NULL)
162 pFrame = mpBase->GetViewFrame();
164 if (pFrame != NULL && mpBase!=NULL && pWindow!=NULL)
166 // Try to get the view from the cache.
167 ::boost::shared_ptr<ViewDescriptor> pDescriptor (GetViewFromCache(rxViewId, xPane));
169 // When the requested view is not in the cache then create a new view.
170 if (pDescriptor.get() == NULL)
172 pDescriptor = CreateView(rxViewId, *pFrame, *pWindow, xPane, pFrameView, bIsCenterPane);
175 if (pDescriptor.get() != NULL)
176 xView = pDescriptor->mxView;
178 mpViewShellContainer->push_back(pDescriptor);
180 if (bIsCenterPane)
181 ActivateCenterView(pDescriptor);
182 else
183 pWindow->Resize();
186 return xView;
189 void SAL_CALL BasicViewFactory::releaseResource (const Reference<XResource>& rxView)
190 throw(RuntimeException, std::exception)
192 if ( ! rxView.is())
193 throw lang::IllegalArgumentException();
195 if (rxView.is() && mpBase!=NULL)
197 ViewShellContainer::iterator iViewShell (
198 ::std::find_if(
199 mpViewShellContainer->begin(),
200 mpViewShellContainer->end(),
201 ::boost::bind(&ViewDescriptor::CompareView, _1, rxView)));
202 if (iViewShell != mpViewShellContainer->end())
204 ::boost::shared_ptr<ViewShell> pViewShell ((*iViewShell)->mpViewShell);
206 if ((*iViewShell)->mxViewId->isBoundToURL(
207 FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT))
209 // Obtain a pointer to and connect to the frame view of the
210 // view. The next view, that is created, will be
211 // initialized with this frame view.
212 if (mpFrameView == NULL)
214 mpFrameView = pViewShell->GetFrameView();
215 if (mpFrameView)
216 mpFrameView->Connect();
219 // With the view in the center pane the sub controller is
220 // released, too.
221 mpBase->GetDrawController().SetSubController(
222 Reference<drawing::XDrawSubController>());
224 SfxViewShell* pSfxViewShell = pViewShell->GetViewShell();
225 if (pSfxViewShell != NULL)
226 pSfxViewShell->DisconnectAllClients();
229 ReleaseView(*iViewShell);
231 mpViewShellContainer->erase(iViewShell);
233 else
235 throw lang::IllegalArgumentException();
240 void SAL_CALL BasicViewFactory::initialize (const Sequence<Any>& aArguments)
241 throw (Exception, RuntimeException, std::exception)
243 if (aArguments.getLength() > 0)
245 Reference<XConfigurationController> xCC;
248 // Get the XController from the first argument.
249 Reference<frame::XController> xController (aArguments[0], UNO_QUERY_THROW);
251 // Tunnel through the controller to obtain a ViewShellBase.
252 Reference<lang::XUnoTunnel> xTunnel (xController, UNO_QUERY_THROW);
253 ::sd::DrawController* pController = reinterpret_cast<sd::DrawController*>(
254 xTunnel->getSomething(sd::DrawController::getUnoTunnelId()));
255 if (pController != NULL)
256 mpBase = pController->GetViewShellBase();
258 // Register the factory for its supported views.
259 Reference<XControllerManager> xCM (xController,UNO_QUERY_THROW);
260 mxConfigurationController = xCM->getConfigurationController();
261 if ( ! mxConfigurationController.is())
262 throw RuntimeException();
263 mxConfigurationController->addResourceFactory(FrameworkHelper::msImpressViewURL, this);
264 mxConfigurationController->addResourceFactory(FrameworkHelper::msDrawViewURL, this);
265 mxConfigurationController->addResourceFactory(FrameworkHelper::msOutlineViewURL, this);
266 mxConfigurationController->addResourceFactory(FrameworkHelper::msNotesViewURL, this);
267 mxConfigurationController->addResourceFactory(FrameworkHelper::msHandoutViewURL, this);
268 mxConfigurationController->addResourceFactory(FrameworkHelper::msPresentationViewURL, this);
269 mxConfigurationController->addResourceFactory(FrameworkHelper::msSlideSorterURL, this);
271 catch (RuntimeException&)
273 mpBase = NULL;
274 if (mxConfigurationController.is())
275 mxConfigurationController->removeResourceFactoryForReference(this);
276 throw;
281 ::boost::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::CreateView (
282 const Reference<XResourceId>& rxViewId,
283 SfxViewFrame& rFrame,
284 vcl::Window& rWindow,
285 const Reference<XPane>& rxPane,
286 FrameView* pFrameView,
287 const bool bIsCenterPane)
289 ::boost::shared_ptr<ViewDescriptor> pDescriptor (new ViewDescriptor());
291 pDescriptor->mpViewShell = CreateViewShell(
292 rxViewId,
293 rFrame,
294 rWindow,
295 pFrameView,
296 bIsCenterPane);
297 pDescriptor->mxViewId = rxViewId;
299 if (pDescriptor->mpViewShell.get() != NULL)
301 pDescriptor->mpViewShell->Init(bIsCenterPane);
302 mpBase->GetViewShellManager()->ActivateViewShell(pDescriptor->mpViewShell.get());
304 Reference<awt::XWindow> xWindow(rxPane->getWindow());
305 pDescriptor->mpWrapper = new ViewShellWrapper(
306 pDescriptor->mpViewShell,
307 rxViewId,
308 xWindow);
310 // register ViewShellWrapper on pane window
311 if (xWindow.is())
313 xWindow->addWindowListener(pDescriptor->mpWrapper);
314 if (pDescriptor->mpViewShell != 0)
316 pDescriptor->mpViewShell->Resize();
320 pDescriptor->mxView.set( pDescriptor->mpWrapper->queryInterface( cppu::UnoType<XResource>::get() ), UNO_QUERY_THROW );
323 return pDescriptor;
326 ::boost::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell (
327 const Reference<XResourceId>& rxViewId,
328 SfxViewFrame& rFrame,
329 vcl::Window& rWindow,
330 FrameView* pFrameView,
331 const bool bIsCenterPane)
333 ::boost::shared_ptr<ViewShell> pViewShell;
334 const OUString& rsViewURL (rxViewId->getResourceURL());
335 if (rsViewURL.equals(FrameworkHelper::msImpressViewURL))
337 pViewShell.reset(
338 new DrawViewShell(
339 &rFrame,
340 *mpBase,
341 &rWindow,
342 PK_STANDARD,
343 pFrameView));
345 else if (rsViewURL.equals(FrameworkHelper::msDrawViewURL))
347 pViewShell.reset(
348 new GraphicViewShell (
349 &rFrame,
350 *mpBase,
351 &rWindow,
352 pFrameView));
354 else if (rsViewURL.equals(FrameworkHelper::msOutlineViewURL))
356 pViewShell.reset(
357 new OutlineViewShell (
358 &rFrame,
359 *mpBase,
360 &rWindow,
361 pFrameView));
363 else if (rsViewURL.equals(FrameworkHelper::msNotesViewURL))
365 pViewShell.reset(
366 new DrawViewShell(
367 &rFrame,
368 *mpBase,
369 &rWindow,
370 PK_NOTES,
371 pFrameView));
373 else if (rsViewURL.equals(FrameworkHelper::msHandoutViewURL))
375 pViewShell.reset(
376 new DrawViewShell(
377 &rFrame,
378 *mpBase,
379 &rWindow,
380 PK_HANDOUT,
381 pFrameView));
383 else if (rsViewURL.equals(FrameworkHelper::msPresentationViewURL))
385 pViewShell.reset(
386 new PresentationViewShell(
387 &rFrame,
388 *mpBase,
389 &rWindow,
390 pFrameView));
392 else if (rsViewURL.equals(FrameworkHelper::msSlideSorterURL))
394 pViewShell = ::sd::slidesorter::SlideSorterViewShell::Create (
395 &rFrame,
396 *mpBase,
397 &rWindow,
398 pFrameView,
399 bIsCenterPane);
402 return pViewShell;
405 void BasicViewFactory::ReleaseView (
406 const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor,
407 bool bDoNotCache)
409 bool bIsCacheable (!bDoNotCache && IsCacheable(rpDescriptor));
411 if (bIsCacheable)
413 Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY);
414 if (xResource.is())
416 Reference<XResource> xNewAnchor (mxLocalPane, UNO_QUERY);
417 if (xNewAnchor.is())
418 if (xResource->relocateToAnchor(xNewAnchor))
419 mpViewCache->push_back(rpDescriptor);
420 else
421 bIsCacheable = false;
422 else
423 bIsCacheable = false;
425 else
427 bIsCacheable = false;
431 if ( ! bIsCacheable)
433 // Shut down the current view shell.
434 rpDescriptor->mpViewShell->Shutdown ();
435 mpBase->GetDocShell()->Disconnect(rpDescriptor->mpViewShell.get());
436 mpBase->GetViewShellManager()->DeactivateViewShell(rpDescriptor->mpViewShell.get());
438 Reference<XComponent> xComponent (rpDescriptor->mxView, UNO_QUERY);
439 if (xComponent.is())
440 xComponent->dispose();
444 bool BasicViewFactory::IsCacheable (const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor)
446 bool bIsCacheable (false);
448 Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY);
449 if (xResource.is())
451 static ::std::vector<Reference<XResourceId> > maCacheableResources;
452 if (maCacheableResources.empty() )
454 ::boost::shared_ptr<FrameworkHelper> pHelper (FrameworkHelper::Instance(*mpBase));
456 // The slide sorter and the task panel are cacheable and relocatable.
457 maCacheableResources.push_back(FrameworkHelper::CreateResourceId(
458 FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftDrawPaneURL));
459 maCacheableResources.push_back(FrameworkHelper::CreateResourceId(
460 FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftImpressPaneURL));
463 ::std::vector<Reference<XResourceId> >::const_iterator iId;
464 for (iId=maCacheableResources.begin(); iId!=maCacheableResources.end(); ++iId)
466 if ((*iId)->compareTo(rpDescriptor->mxViewId) == 0)
468 bIsCacheable = true;
469 break;
474 return bIsCacheable;
477 ::boost::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::GetViewFromCache (
478 const Reference<XResourceId>& rxViewId,
479 const Reference<XPane>& rxPane)
481 ::boost::shared_ptr<ViewDescriptor> pDescriptor;
483 // Search for the requested view in the cache.
484 ViewCache::iterator iEntry;
485 for (iEntry=mpViewCache->begin(); iEntry!=mpViewCache->end(); ++iEntry)
487 if ((*iEntry)->mxViewId->compareTo(rxViewId) == 0)
489 pDescriptor = *iEntry;
490 mpViewCache->erase(iEntry);
491 break;
495 // When the view has been found then relocate it to the given pane and
496 // remove it from the cache.
497 if (pDescriptor.get() != NULL)
499 bool bRelocationSuccessfull (false);
500 Reference<XRelocatableResource> xResource (pDescriptor->mxView, UNO_QUERY);
501 if (xResource.is() && rxPane.is())
503 if (xResource->relocateToAnchor(rxPane))
504 bRelocationSuccessfull = true;
507 if ( ! bRelocationSuccessfull)
509 ReleaseView(pDescriptor, true);
510 pDescriptor.reset();
514 return pDescriptor;
517 void BasicViewFactory::ActivateCenterView (
518 const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor)
520 mpBase->GetDocShell()->Connect(rpDescriptor->mpViewShell.get());
522 // During the creation of the new sub-shell, resize requests were not
523 // forwarded to it because it was not yet registered. Therefore, we
524 // have to request a resize now.
525 rpDescriptor->mpViewShell->UIFeatureChanged();
526 if (mpBase->GetDocShell()->IsInPlaceActive())
527 mpBase->GetViewFrame()->Resize(true);
529 mpBase->GetDrawController().SetSubController(
530 rpDescriptor->mpViewShell->CreateSubController());
533 } } // end of namespace sd::framework
536 extern "C" SAL_DLLPUBLIC_EXPORT ::com::sun::star::uno::XInterface* SAL_CALL
537 com_sun_star_comp_Draw_framework_BasicViewFactory_get_implementation(::com::sun::star::uno::XComponentContext* context,
538 ::com::sun::star::uno::Sequence<css::uno::Any> const &)
540 return cppu::acquire(new sd::framework::BasicViewFactory(context));
545 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */