1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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
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
> >
75 ViewShellContainer() {};
78 class BasicViewFactory::ViewCache
79 : public ::std::vector
<boost::shared_ptr
<ViewDescriptor
> >
85 //===== ViewFactory ===========================================================
87 BasicViewFactory::BasicViewFactory (
88 const Reference
<XComponentContext
>& rxContext
)
89 : BasicViewFactoryInterfaceBase(MutexOwner::maMutex
),
90 mxConfigurationController(),
91 mpViewShellContainer(new ViewShellContainer()),
94 mpWindow(VclPtr
<WorkWindow
>::Create(nullptr,WB_STDWORK
)),
95 mpViewCache(new ViewCache()),
96 mxLocalPane(new Pane(Reference
<XResourceId
>(), mpWindow
.get()))
101 BasicViewFactory::~BasicViewFactory()
105 void SAL_CALL
BasicViewFactory::disposing()
107 // Disconnect from the frame view.
108 if (mpFrameView
!= NULL
)
110 mpFrameView
->Disconnect();
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
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()),
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
;
157 pWindow
= VCLUnoHelper::GetWindow(xPane
->getWindow());
159 // Get the view frame.
160 SfxViewFrame
* pFrame
= 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
);
181 ActivateCenterView(pDescriptor
);
189 void SAL_CALL
BasicViewFactory::releaseResource (const Reference
<XResource
>& rxView
)
190 throw(RuntimeException
, std::exception
)
193 throw lang::IllegalArgumentException();
195 if (rxView
.is() && mpBase
!=NULL
)
197 ViewShellContainer::iterator
iViewShell (
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();
216 mpFrameView
->Connect();
219 // With the view in the center pane the sub controller is
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
);
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
&)
274 if (mxConfigurationController
.is())
275 mxConfigurationController
->removeResourceFactoryForReference(this);
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(
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
,
310 // register ViewShellWrapper on pane window
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
);
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
))
345 else if (rsViewURL
.equals(FrameworkHelper::msDrawViewURL
))
348 new GraphicViewShell (
354 else if (rsViewURL
.equals(FrameworkHelper::msOutlineViewURL
))
357 new OutlineViewShell (
363 else if (rsViewURL
.equals(FrameworkHelper::msNotesViewURL
))
373 else if (rsViewURL
.equals(FrameworkHelper::msHandoutViewURL
))
383 else if (rsViewURL
.equals(FrameworkHelper::msPresentationViewURL
))
386 new PresentationViewShell(
392 else if (rsViewURL
.equals(FrameworkHelper::msSlideSorterURL
))
394 pViewShell
= ::sd::slidesorter::SlideSorterViewShell::Create (
405 void BasicViewFactory::ReleaseView (
406 const ::boost::shared_ptr
<ViewDescriptor
>& rpDescriptor
,
409 bool bIsCacheable (!bDoNotCache
&& IsCacheable(rpDescriptor
));
413 Reference
<XRelocatableResource
> xResource (rpDescriptor
->mxView
, UNO_QUERY
);
416 Reference
<XResource
> xNewAnchor (mxLocalPane
, UNO_QUERY
);
418 if (xResource
->relocateToAnchor(xNewAnchor
))
419 mpViewCache
->push_back(rpDescriptor
);
421 bIsCacheable
= false;
423 bIsCacheable
= false;
427 bIsCacheable
= false;
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
);
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
);
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)
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
);
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);
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: */