LibreOffice Module sd (master) 1
BasicViewFactory.cxx
Go to the documentation of this file.
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
21
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 <ViewShellBase.hxx>
29#include <ViewShellManager.hxx>
30#include <DrawDocShell.hxx>
31#include <DrawViewShell.hxx>
32#include <GraphicViewShell.hxx>
33#include <OutlineViewShell.hxx>
36#include <FrameView.hxx>
37#include <Window.hxx>
38
40#include <sfx2/viewfrm.hxx>
41#include <vcl/wrkwin.hxx>
43
44
45using namespace ::com::sun::star;
46using namespace ::com::sun::star::uno;
47using namespace ::com::sun::star::lang;
49
50using ::sd::framework::FrameworkHelper;
51
52namespace sd::framework {
53
54//===== ViewDescriptor ========================================================
55
57{
58public:
59 Reference<XResource> mxView;
60 std::shared_ptr<sd::ViewShell> mpViewShell;
61 Reference<XResourceId> mxViewId;
62 static bool CompareView (const std::shared_ptr<ViewDescriptor>& rpDescriptor,
63 const Reference<XResource>& rxView)
64 { return rpDescriptor->mxView.get() == rxView.get(); }
65};
66
67//===== BasicViewFactory::ViewShellContainer ==================================
68
70 : public ::std::vector<std::shared_ptr<ViewDescriptor> >
71{
72public:
74};
75
77 : public ::std::vector<std::shared_ptr<ViewDescriptor> >
78{
79public:
81};
82
83//===== ViewFactory ===========================================================
84
86 : mpViewShellContainer(new ViewShellContainer()),
87 mpBase(nullptr),
88 mpFrameView(nullptr),
90 mpViewCache(std::make_shared<ViewCache>()),
91 mxLocalPane(new Pane(Reference<XResourceId>(), mpWindow.get()))
92{
93 try
94 {
95 // Tunnel through the controller to obtain a ViewShellBase.
96 mpBase = rxController->GetViewShellBase();
97
98 // Register the factory for its supported views.
99 mxConfigurationController = rxController->getConfigurationController();
100 if ( ! mxConfigurationController.is())
101 throw RuntimeException();
109 }
110 catch (RuntimeException&)
111 {
112 mpBase = nullptr;
114 mxConfigurationController->removeResourceFactoryForReference(this);
115 throw;
116 }
117}
118
120{
121}
122
123void BasicViewFactory::disposing(std::unique_lock<std::mutex>&)
124{
125 // Disconnect from the frame view.
126 if (mpFrameView != nullptr)
127 {
129 mpFrameView = nullptr;
130 }
131
132 // Release the view cache.
133 for (const auto& rxView : *mpViewCache)
134 {
135 ReleaseView(rxView, true);
136 }
137
138 // Release the view shell container. At this point no one other than us
139 // should hold references to the view shells (at the moment this is a
140 // trivial requirement, because no one other than us holds a shared
141 // pointer).
142 // ViewShellContainer::const_iterator iView;
143 for (const auto& rxView : *mpViewShellContainer)
144 {
145 OSL_ASSERT(rxView->mpViewShell.use_count() == 1);
146 }
147 mpViewShellContainer.reset();
148}
149
150Reference<XResource> SAL_CALL BasicViewFactory::createResource (
151 const Reference<XResourceId>& rxViewId)
152{
153 Reference<XResource> xView;
154 const bool bIsCenterPane (
155 rxViewId->isBoundToURL(FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT));
156
157 // Get the pane for the anchor URL.
158 Reference<XPane> xPane;
160 xPane.set(mxConfigurationController->getResource(rxViewId->getAnchor()), UNO_QUERY);
161
162 // For main views use the frame view of the last main view.
163 ::sd::FrameView* pFrameView = nullptr;
164 if (xPane.is() && bIsCenterPane)
165 {
166 pFrameView = mpFrameView;
167 }
168
169 // Get Window pointer for XWindow of the pane.
170 vcl::Window* pWindow = nullptr;
171 if (xPane.is())
172 pWindow = VCLUnoHelper::GetWindow(xPane->getWindow());
173
174 // Get the view frame.
175 SfxViewFrame* pFrame = nullptr;
176 if (mpBase != nullptr)
177 pFrame = &mpBase->GetViewFrame();
178
179 if (pFrame != nullptr && mpBase!=nullptr && pWindow!=nullptr)
180 {
181 // Try to get the view from the cache.
182 std::shared_ptr<ViewDescriptor> pDescriptor (GetViewFromCache(rxViewId, xPane));
183
184 // When the requested view is not in the cache then create a new view.
185 if (pDescriptor == nullptr)
186 {
187 pDescriptor = CreateView(rxViewId, *pFrame, *pWindow, xPane, pFrameView, bIsCenterPane);
188 }
189
190 xView = pDescriptor->mxView;
191
192 mpViewShellContainer->push_back(pDescriptor);
193
194 if (bIsCenterPane)
195 ActivateCenterView(pDescriptor);
196 else
197 pWindow->Resize();
198 }
199
200 return xView;
201}
202
203void SAL_CALL BasicViewFactory::releaseResource (const Reference<XResource>& rxView)
204{
205 if ( ! rxView.is())
206 throw lang::IllegalArgumentException();
207
208 if (!rxView.is() || !mpBase)
209 return;
210
211 ViewShellContainer::iterator iViewShell (
212 ::std::find_if(
213 mpViewShellContainer->begin(),
215 [&] (std::shared_ptr<ViewDescriptor> const& pVD) {
216 return ViewDescriptor::CompareView(pVD, rxView);
217 } ));
218 if (iViewShell == mpViewShellContainer->end())
219 {
220 throw lang::IllegalArgumentException();
221 }
222
223 std::shared_ptr<ViewShell> pViewShell ((*iViewShell)->mpViewShell);
224
225 if ((*iViewShell)->mxViewId->isBoundToURL(
226 FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT))
227 {
228 // Obtain a pointer to and connect to the frame view of the
229 // view. The next view, that is created, will be
230 // initialized with this frame view.
231 if (mpFrameView == nullptr)
232 {
233 mpFrameView = pViewShell->GetFrameView();
234 if (mpFrameView)
236 }
237
238 // With the view in the center pane the sub controller is
239 // released, too.
241 Reference<drawing::XDrawSubController>());
242
243 SfxViewShell* pSfxViewShell = pViewShell->GetViewShell();
244 if (pSfxViewShell != nullptr)
245 pSfxViewShell->DisconnectAllClients();
246 }
247
248 ReleaseView(*iViewShell, false);
249
250 mpViewShellContainer->erase(iViewShell);
251}
252
253std::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::CreateView (
254 const Reference<XResourceId>& rxViewId,
255 SfxViewFrame& rFrame,
256 vcl::Window& rWindow,
257 const Reference<XPane>& rxPane,
258 FrameView* pFrameView,
259 const bool bIsCenterPane)
260{
261 auto pDescriptor = std::make_shared<ViewDescriptor>();
262
263 pDescriptor->mpViewShell = CreateViewShell(
264 rxViewId,
265 rFrame,
266 rWindow,
267 pFrameView);
268 pDescriptor->mxViewId = rxViewId;
269
270 if (pDescriptor->mpViewShell != nullptr)
271 {
272 pDescriptor->mpViewShell->Init(bIsCenterPane);
273 mpBase->GetViewShellManager()->ActivateViewShell(pDescriptor->mpViewShell.get());
274
275 Reference<awt::XWindow> xWindow(rxPane->getWindow());
277 pDescriptor->mpViewShell,
278 rxViewId,
279 xWindow));
280
281 // register ViewShellWrapper on pane window
282 if (xWindow.is())
283 {
284 xWindow->addWindowListener(wrapper);
285 if (pDescriptor->mpViewShell != nullptr)
286 {
287 pDescriptor->mpViewShell->Resize();
288 }
289 }
290
291 pDescriptor->mxView = wrapper.get();
292 }
293
294 return pDescriptor;
295}
296
297std::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell (
298 const Reference<XResourceId>& rxViewId,
299 SfxViewFrame& rFrame,
300 vcl::Window& rWindow,
301 FrameView* pFrameView)
302{
303 std::shared_ptr<ViewShell> pViewShell;
304 const OUString& rsViewURL (rxViewId->getResourceURL());
305 if (rsViewURL == FrameworkHelper::msImpressViewURL)
306 {
307 pViewShell =
308 std::make_shared<DrawViewShell>(
309 *mpBase,
310 &rWindow,
312 pFrameView);
313 pViewShell->GetContentWindow()->set_id("impress_win");
314 }
315 else if (rsViewURL == FrameworkHelper::msDrawViewURL)
316 {
317 pViewShell = std::shared_ptr<GraphicViewShell>(
318 new GraphicViewShell(*mpBase, &rWindow, pFrameView),
320 pViewShell->GetContentWindow()->set_id("draw_win");
321 }
322 else if (rsViewURL == FrameworkHelper::msOutlineViewURL)
323 {
324 pViewShell =
325 std::make_shared<OutlineViewShell>(
326 &rFrame,
327 *mpBase,
328 &rWindow,
329 pFrameView);
330 pViewShell->GetContentWindow()->set_id("outline_win");
331 }
332 else if (rsViewURL == FrameworkHelper::msNotesViewURL)
333 {
334 pViewShell =
335 std::make_shared<DrawViewShell>(
336 *mpBase,
337 &rWindow,
339 pFrameView);
340 pViewShell->GetContentWindow()->set_id("notes_win");
341 }
342 else if (rsViewURL == FrameworkHelper::msHandoutViewURL)
343 {
344 pViewShell =
345 std::make_shared<DrawViewShell>(
346 *mpBase,
347 &rWindow,
349 pFrameView);
350 pViewShell->GetContentWindow()->set_id("handout_win");
351 }
352 else if (rsViewURL == FrameworkHelper::msPresentationViewURL)
353 {
354 pViewShell =
355 std::make_shared<PresentationViewShell>(
356 *mpBase,
357 &rWindow,
358 pFrameView);
359 pViewShell->GetContentWindow()->set_id("presentation_win");
360 }
361 else if (rsViewURL == FrameworkHelper::msSlideSorterURL)
362 {
364 &rFrame,
365 *mpBase,
366 &rWindow,
367 pFrameView);
368 pViewShell->GetContentWindow()->set_id("slidesorter");
369 }
370
371 return pViewShell;
372}
373
375 const std::shared_ptr<ViewDescriptor>& rpDescriptor,
376 bool bDoNotCache)
377{
378 bool bIsCacheable (!bDoNotCache && IsCacheable(rpDescriptor));
379
380 if (bIsCacheable)
381 {
382 Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY);
383 if (xResource.is())
384 {
385 if (mxLocalPane.is())
386 if (xResource->relocateToAnchor(mxLocalPane))
387 mpViewCache->push_back(rpDescriptor);
388 else
389 bIsCacheable = false;
390 else
391 bIsCacheable = false;
392 }
393 else
394 {
395 bIsCacheable = false;
396 }
397 }
398
399 if ( ! bIsCacheable)
400 {
401 // Shut down the current view shell.
402 rpDescriptor->mpViewShell->Shutdown ();
403 mpBase->GetDocShell()->Disconnect(rpDescriptor->mpViewShell.get());
404 mpBase->GetViewShellManager()->DeactivateViewShell(rpDescriptor->mpViewShell.get());
405
406 Reference<XComponent> xComponent (rpDescriptor->mxView, UNO_QUERY);
407 if (xComponent.is())
408 xComponent->dispose();
409 }
410}
411
412bool BasicViewFactory::IsCacheable (const std::shared_ptr<ViewDescriptor>& rpDescriptor)
413{
414 bool bIsCacheable (false);
415
416 Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY);
417 if (xResource.is())
418 {
419 static ::std::vector<Reference<XResourceId> > s_aCacheableResources = [&]()
420 {
421 ::std::vector<Reference<XResourceId> > tmp;
423
424 // The slide sorter and the task panel are cacheable and relocatable.
429 return tmp;
430 }();
431
432 bIsCacheable = std::any_of(s_aCacheableResources.begin(), s_aCacheableResources.end(),
433 [&rpDescriptor](const Reference<XResourceId>& rxId) { return rxId->compareTo(rpDescriptor->mxViewId) == 0; });
434 }
435
436 return bIsCacheable;
437}
438
439std::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::GetViewFromCache (
440 const Reference<XResourceId>& rxViewId,
441 const Reference<XPane>& rxPane)
442{
443 std::shared_ptr<ViewDescriptor> pDescriptor;
444
445 // Search for the requested view in the cache.
446 ViewCache::iterator iEntry = std::find_if(mpViewCache->begin(), mpViewCache->end(),
447 [&rxViewId](const ViewCache::value_type& rxEntry) { return rxEntry->mxViewId->compareTo(rxViewId) == 0; });
448 if (iEntry != mpViewCache->end())
449 {
450 pDescriptor = *iEntry;
451 mpViewCache->erase(iEntry);
452 }
453
454 // When the view has been found then relocate it to the given pane and
455 // remove it from the cache.
456 if (pDescriptor != nullptr)
457 {
458 bool bRelocationSuccessful (false);
459 Reference<XRelocatableResource> xResource (pDescriptor->mxView, UNO_QUERY);
460 if (xResource.is() && rxPane.is())
461 {
462 if (xResource->relocateToAnchor(rxPane))
463 bRelocationSuccessful = true;
464 }
465
466 if ( ! bRelocationSuccessful)
467 {
468 ReleaseView(pDescriptor, true);
469 pDescriptor.reset();
470 }
471 }
472
473 return pDescriptor;
474}
475
477 const std::shared_ptr<ViewDescriptor>& rpDescriptor)
478{
479 mpBase->GetDocShell()->Connect(rpDescriptor->mpViewShell.get());
480
481 // During the creation of the new sub-shell, resize requests were not
482 // forwarded to it because it was not yet registered. Therefore, we
483 // have to request a resize now.
484 rpDescriptor->mpViewShell->UIFeatureChanged();
486 mpBase->GetViewFrame().Resize(true);
487
489 rpDescriptor->mpViewShell->CreateSubController());
490}
491
492} // end of namespace sd::framework
493
494
495/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsInPlaceActive() const
SfxViewShell * GetViewShell() const
void Resize(bool bForce=false)
void DisconnectAllClients()
SfxViewFrame & GetViewFrame() const
static vcl::Window * GetWindow(const css::uno::Reference< css::awt::XWindow > &rxWindow)
void SetSubController(const css::uno::Reference< css::drawing::XDrawSubController > &rxSubController)
Replace the currently used sub controller with the given one.
void Connect(sd::ViewShell *pViewSh)
Definition: docshel2.cxx:147
void Disconnect(sd::ViewShell const *pViewSh)
Definition: docshel2.cxx:152
View for MDIFrame.
Definition: FrameView.hxx:36
void Connect()
Definition: frmview.cxx:256
void Disconnect()
Definition: frmview.cxx:261
View shell of the Draw application.
DrawController * GetDrawController() const
std::shared_ptr< ViewShellManager > const & GetViewShellManager() const
DrawDocShell * GetDocShell() const
static bool CompareView(const std::shared_ptr< ViewDescriptor > &rpDescriptor, const Reference< XResource > &rxView)
std::shared_ptr< sd::ViewShell > mpViewShell
virtual void disposing(std::unique_lock< std::mutex > &) override
std::unique_ptr< ViewShellContainer > mpViewShellContainer
std::shared_ptr< ViewCache > mpViewCache
std::shared_ptr< ViewDescriptor > CreateView(const css::uno::Reference< css::drawing::framework::XResourceId > &rxViewId, SfxViewFrame &rFrame, vcl::Window &rWindow, const css::uno::Reference< css::drawing::framework::XPane > &rxPane, FrameView *pFrameView, const bool bIsCenterView)
css::uno::Reference< css::drawing::framework::XConfigurationController > mxConfigurationController
BasicViewFactory(const rtl::Reference<::sd::DrawController > &rxController)
void ReleaseView(const std::shared_ptr< ViewDescriptor > &rpDescriptor, bool bDoNotCache)
virtual css::uno::Reference< css::drawing::framework::XResource > SAL_CALL createResource(const css::uno::Reference< css::drawing::framework::XResourceId > &rxViewId) override
std::shared_ptr< ViewShell > CreateViewShell(const css::uno::Reference< css::drawing::framework::XResourceId > &rxViewId, SfxViewFrame &rFrame, vcl::Window &rWindow, FrameView *pFrameView)
void ActivateCenterView(const std::shared_ptr< ViewDescriptor > &rpDescriptor)
bool IsCacheable(const std::shared_ptr< ViewDescriptor > &rpDescriptor)
virtual void SAL_CALL releaseResource(const css::uno::Reference< css::drawing::framework::XResource > &xView) override
std::shared_ptr< ViewDescriptor > GetViewFromCache(const css::uno::Reference< css::drawing::framework::XResourceId > &rxViewId, const css::uno::Reference< css::drawing::framework::XPane > &rxPane)
css::uno::Reference< css::drawing::framework::XPane > mxLocalPane
static css::uno::Reference< css::drawing::framework::XResourceId > CreateResourceId(const OUString &rsResourceURL)
Create a new XResourceId object for the given resource URL.
static const OUString msHandoutViewURL
static const OUString msCenterPaneURL
static const OUString msLeftDrawPaneURL
static const OUString msNotesViewURL
static const OUString msOutlineViewURL
static const OUString msPresentationViewURL
static const OUString msSlideSorterURL
static ::std::shared_ptr< FrameworkHelper > Instance(ViewShellBase &rBase)
Return the FrameworkHelper object that is associated with the given ViewShellBase.
static const OUString msLeftImpressPaneURL
static const OUString msDrawViewURL
static const OUString msImpressViewURL
A pane is a wrapper for a window and possibly for a tab bar (for view switching).
Definition: Pane.hxx:51
This class wraps ViewShell objects and makes them look like an XView.
static std::shared_ptr< SlideSorterViewShell > Create(SfxViewFrame *pFrame, ViewShellBase &rViewShellBase, vcl::Window *pParentWindow, FrameView *pFrameView)
virtual void Resize()
Reference
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
std::shared_ptr< T > make_shared(Args &&... args)
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
WinBits const WB_STDWORK
VclPtr< vcl::Window > mpWindow