Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sd / source / ui / framework / factories / BasicViewFactory.cxx
blob3ea7e37f1f936730286a7bc99610903ca95ddfc5
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 <framework/factories/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 <ViewShellBase.hxx>
29 #include <ViewShellManager.hxx>
30 #include <DrawDocShell.hxx>
31 #include <DrawViewShell.hxx>
32 #include <GraphicViewShell.hxx>
33 #include <OutlineViewShell.hxx>
34 #include <PresentationViewShell.hxx>
35 #include <SlideSorterViewShell.hxx>
36 #include <FrameView.hxx>
37 #include <Window.hxx>
39 #include <comphelper/servicehelper.hxx>
40 #include <sfx2/viewfrm.hxx>
41 #include <vcl/wrkwin.hxx>
42 #include <toolkit/helper/vclunohelper.hxx>
45 using namespace ::com::sun::star;
46 using namespace ::com::sun::star::uno;
47 using namespace ::com::sun::star::lang;
48 using namespace ::com::sun::star::drawing::framework;
50 using ::sd::framework::FrameworkHelper;
52 namespace sd::framework {
54 //===== ViewDescriptor ========================================================
56 class BasicViewFactory::ViewDescriptor
58 public:
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(); }
67 //===== BasicViewFactory::ViewShellContainer ==================================
69 class BasicViewFactory::ViewShellContainer
70 : public ::std::vector<std::shared_ptr<ViewDescriptor> >
72 public:
73 ViewShellContainer() {};
76 class BasicViewFactory::ViewCache
77 : public ::std::vector<std::shared_ptr<ViewDescriptor> >
79 public:
80 ViewCache() {};
83 //===== ViewFactory ===========================================================
85 BasicViewFactory::BasicViewFactory (const rtl::Reference<::sd::DrawController>& rxController)
86 : mpViewShellContainer(new ViewShellContainer()),
87 mpBase(nullptr),
88 mpFrameView(nullptr),
89 mpWindow(VclPtr<WorkWindow>::Create(nullptr,WB_STDWORK)),
90 mpViewCache(std::make_shared<ViewCache>()),
91 mxLocalPane(new Pane(Reference<XResourceId>(), mpWindow.get()))
93 try
95 // Tunnel through the controller to obtain a ViewShellBase.
96 mpBase = rxController->GetViewShellBase();
98 // Register the factory for its supported views.
99 mxConfigurationController = rxController->getConfigurationController();
100 if ( ! mxConfigurationController.is())
101 throw RuntimeException();
102 mxConfigurationController->addResourceFactory(FrameworkHelper::msImpressViewURL, this);
103 mxConfigurationController->addResourceFactory(FrameworkHelper::msDrawViewURL, this);
104 mxConfigurationController->addResourceFactory(FrameworkHelper::msOutlineViewURL, this);
105 mxConfigurationController->addResourceFactory(FrameworkHelper::msNotesViewURL, this);
106 mxConfigurationController->addResourceFactory(FrameworkHelper::msHandoutViewURL, this);
107 mxConfigurationController->addResourceFactory(FrameworkHelper::msPresentationViewURL, this);
108 mxConfigurationController->addResourceFactory(FrameworkHelper::msSlideSorterURL, this);
110 catch (RuntimeException&)
112 mpBase = nullptr;
113 if (mxConfigurationController.is())
114 mxConfigurationController->removeResourceFactoryForReference(this);
115 throw;
119 BasicViewFactory::~BasicViewFactory()
123 void BasicViewFactory::disposing(std::unique_lock<std::mutex>&)
125 // Disconnect from the frame view.
126 if (mpFrameView != nullptr)
128 mpFrameView->Disconnect();
129 mpFrameView = nullptr;
132 // Release the view cache.
133 for (const auto& rxView : *mpViewCache)
135 ReleaseView(rxView, true);
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)
145 OSL_ASSERT(rxView->mpViewShell.use_count() == 1);
147 mpViewShellContainer.reset();
150 Reference<XResource> SAL_CALL BasicViewFactory::createResource (
151 const Reference<XResourceId>& rxViewId)
153 Reference<XResource> xView;
154 const bool bIsCenterPane (
155 rxViewId->isBoundToURL(FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT));
157 // Get the pane for the anchor URL.
158 Reference<XPane> xPane;
159 if (mxConfigurationController.is())
160 xPane.set(mxConfigurationController->getResource(rxViewId->getAnchor()), UNO_QUERY);
162 // For main views use the frame view of the last main view.
163 ::sd::FrameView* pFrameView = nullptr;
164 if (xPane.is() && bIsCenterPane)
166 pFrameView = mpFrameView;
169 // Get Window pointer for XWindow of the pane.
170 vcl::Window* pWindow = nullptr;
171 if (xPane.is())
172 pWindow = VCLUnoHelper::GetWindow(xPane->getWindow());
174 // Get the view frame.
175 SfxViewFrame* pFrame = nullptr;
176 if (mpBase != nullptr)
177 pFrame = &mpBase->GetViewFrame();
179 if (pFrame != nullptr && mpBase!=nullptr && pWindow!=nullptr)
181 // Try to get the view from the cache.
182 std::shared_ptr<ViewDescriptor> pDescriptor (GetViewFromCache(rxViewId, xPane));
184 // When the requested view is not in the cache then create a new view.
185 if (pDescriptor == nullptr)
187 pDescriptor = CreateView(rxViewId, *pFrame, *pWindow, xPane, pFrameView, bIsCenterPane);
190 xView = pDescriptor->mxView;
192 mpViewShellContainer->push_back(pDescriptor);
194 if (bIsCenterPane)
195 ActivateCenterView(pDescriptor);
196 else
197 pWindow->Resize();
200 return xView;
203 void SAL_CALL BasicViewFactory::releaseResource (const Reference<XResource>& rxView)
205 if ( ! rxView.is())
206 throw lang::IllegalArgumentException();
208 if (!rxView.is() || !mpBase)
209 return;
211 ViewShellContainer::iterator iViewShell (
212 ::std::find_if(
213 mpViewShellContainer->begin(),
214 mpViewShellContainer->end(),
215 [&] (std::shared_ptr<ViewDescriptor> const& pVD) {
216 return ViewDescriptor::CompareView(pVD, rxView);
217 } ));
218 if (iViewShell == mpViewShellContainer->end())
220 throw lang::IllegalArgumentException();
223 std::shared_ptr<ViewShell> pViewShell ((*iViewShell)->mpViewShell);
225 if ((*iViewShell)->mxViewId->isBoundToURL(
226 FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT))
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)
233 mpFrameView = pViewShell->GetFrameView();
234 if (mpFrameView)
235 mpFrameView->Connect();
238 // With the view in the center pane the sub controller is
239 // released, too.
240 mpBase->GetDrawController()->SetSubController(
241 Reference<drawing::XDrawSubController>());
243 SfxViewShell* pSfxViewShell = pViewShell->GetViewShell();
244 if (pSfxViewShell != nullptr)
245 pSfxViewShell->DisconnectAllClients();
248 ReleaseView(*iViewShell, false);
250 mpViewShellContainer->erase(iViewShell);
253 std::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)
261 auto pDescriptor = std::make_shared<ViewDescriptor>();
263 pDescriptor->mpViewShell = CreateViewShell(
264 rxViewId,
265 rFrame,
266 rWindow,
267 pFrameView);
268 pDescriptor->mxViewId = rxViewId;
270 if (pDescriptor->mpViewShell != nullptr)
272 pDescriptor->mpViewShell->Init(bIsCenterPane);
273 mpBase->GetViewShellManager()->ActivateViewShell(pDescriptor->mpViewShell.get());
275 Reference<awt::XWindow> xWindow(rxPane->getWindow());
276 rtl::Reference<ViewShellWrapper> wrapper(new ViewShellWrapper(
277 pDescriptor->mpViewShell,
278 rxViewId,
279 xWindow));
281 // register ViewShellWrapper on pane window
282 if (xWindow.is())
284 xWindow->addWindowListener(wrapper);
285 if (pDescriptor->mpViewShell != nullptr)
287 pDescriptor->mpViewShell->Resize();
291 pDescriptor->mxView = wrapper.get();
294 return pDescriptor;
297 std::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell (
298 const Reference<XResourceId>& rxViewId,
299 SfxViewFrame& rFrame,
300 vcl::Window& rWindow,
301 FrameView* pFrameView)
303 std::shared_ptr<ViewShell> pViewShell;
304 const OUString& rsViewURL (rxViewId->getResourceURL());
305 if (rsViewURL == FrameworkHelper::msImpressViewURL)
307 pViewShell =
308 std::make_shared<DrawViewShell>(
309 *mpBase,
310 &rWindow,
311 PageKind::Standard,
312 pFrameView);
313 pViewShell->GetContentWindow()->set_id("impress_win");
315 else if (rsViewURL == FrameworkHelper::msDrawViewURL)
317 pViewShell = std::shared_ptr<GraphicViewShell>(
318 new GraphicViewShell(*mpBase, &rWindow, pFrameView),
319 o3tl::default_delete<GraphicViewShell>());
320 pViewShell->GetContentWindow()->set_id("draw_win");
322 else if (rsViewURL == FrameworkHelper::msOutlineViewURL)
324 pViewShell =
325 std::make_shared<OutlineViewShell>(
326 &rFrame,
327 *mpBase,
328 &rWindow,
329 pFrameView);
330 pViewShell->GetContentWindow()->set_id("outline_win");
332 else if (rsViewURL == FrameworkHelper::msNotesViewURL)
334 pViewShell =
335 std::make_shared<DrawViewShell>(
336 *mpBase,
337 &rWindow,
338 PageKind::Notes,
339 pFrameView);
340 pViewShell->GetContentWindow()->set_id("notes_win");
342 else if (rsViewURL == FrameworkHelper::msHandoutViewURL)
344 pViewShell =
345 std::make_shared<DrawViewShell>(
346 *mpBase,
347 &rWindow,
348 PageKind::Handout,
349 pFrameView);
350 pViewShell->GetContentWindow()->set_id("handout_win");
352 else if (rsViewURL == FrameworkHelper::msPresentationViewURL)
354 pViewShell =
355 std::make_shared<PresentationViewShell>(
356 *mpBase,
357 &rWindow,
358 pFrameView);
359 pViewShell->GetContentWindow()->set_id("presentation_win");
361 else if (rsViewURL == FrameworkHelper::msSlideSorterURL)
363 pViewShell = ::sd::slidesorter::SlideSorterViewShell::Create (
364 &rFrame,
365 *mpBase,
366 &rWindow,
367 pFrameView);
368 pViewShell->GetContentWindow()->set_id("slidesorter");
371 return pViewShell;
374 void BasicViewFactory::ReleaseView (
375 const std::shared_ptr<ViewDescriptor>& rpDescriptor,
376 bool bDoNotCache)
378 bool bIsCacheable (!bDoNotCache && IsCacheable(rpDescriptor));
380 if (bIsCacheable)
382 Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY);
383 if (xResource.is())
385 if (mxLocalPane.is())
386 if (xResource->relocateToAnchor(mxLocalPane))
387 mpViewCache->push_back(rpDescriptor);
388 else
389 bIsCacheable = false;
390 else
391 bIsCacheable = false;
393 else
395 bIsCacheable = false;
399 if ( ! bIsCacheable)
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());
406 Reference<XComponent> xComponent (rpDescriptor->mxView, UNO_QUERY);
407 if (xComponent.is())
408 xComponent->dispose();
412 bool BasicViewFactory::IsCacheable (const std::shared_ptr<ViewDescriptor>& rpDescriptor)
414 bool bIsCacheable (false);
416 Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY);
417 if (xResource.is())
419 static ::std::vector<Reference<XResourceId> > s_aCacheableResources = [&]()
421 ::std::vector<Reference<XResourceId> > tmp;
422 FrameworkHelper::Instance(*mpBase);
424 // The slide sorter and the task panel are cacheable and relocatable.
425 tmp.push_back(FrameworkHelper::CreateResourceId(
426 FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftDrawPaneURL));
427 tmp.push_back(FrameworkHelper::CreateResourceId(
428 FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftImpressPaneURL));
429 return tmp;
430 }();
432 bIsCacheable = std::any_of(s_aCacheableResources.begin(), s_aCacheableResources.end(),
433 [&rpDescriptor](const Reference<XResourceId>& rxId) { return rxId->compareTo(rpDescriptor->mxViewId) == 0; });
436 return bIsCacheable;
439 std::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::GetViewFromCache (
440 const Reference<XResourceId>& rxViewId,
441 const Reference<XPane>& rxPane)
443 std::shared_ptr<ViewDescriptor> pDescriptor;
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())
450 pDescriptor = *iEntry;
451 mpViewCache->erase(iEntry);
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)
458 bool bRelocationSuccessful (false);
459 Reference<XRelocatableResource> xResource (pDescriptor->mxView, UNO_QUERY);
460 if (xResource.is() && rxPane.is())
462 if (xResource->relocateToAnchor(rxPane))
463 bRelocationSuccessful = true;
466 if ( ! bRelocationSuccessful)
468 ReleaseView(pDescriptor, true);
469 pDescriptor.reset();
473 return pDescriptor;
476 void BasicViewFactory::ActivateCenterView (
477 const std::shared_ptr<ViewDescriptor>& rpDescriptor)
479 mpBase->GetDocShell()->Connect(rpDescriptor->mpViewShell.get());
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();
485 if (mpBase->GetDocShell()->IsInPlaceActive())
486 mpBase->GetViewFrame().Resize(true);
488 mpBase->GetDrawController()->SetSubController(
489 rpDescriptor->mpViewShell->CreateSubController());
492 } // end of namespace sd::framework
495 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */