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