1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "precompiled_sd.hxx" 29 30 #include "BasicViewFactory.hxx" 31 32 #include "framework/ViewShellWrapper.hxx" 33 #include "framework/FrameworkHelper.hxx" 34 #include <com/sun/star/drawing/framework/XControllerManager.hpp> 35 #include <com/sun/star/lang/IllegalArgumentException.hpp> 36 #include "framework/Pane.hxx" 37 #include "DrawController.hxx" 38 #include "DrawSubController.hxx" 39 #include "ViewShellBase.hxx" 40 #include "ViewShellManager.hxx" 41 #include "DrawDocShell.hxx" 42 #include "DrawViewShell.hxx" 43 #include "GraphicViewShell.hxx" 44 #include "OutlineViewShell.hxx" 45 #include "taskpane/ToolPanelViewShell.hxx" 46 #include "PresentationViewShell.hxx" 47 #include "SlideSorterViewShell.hxx" 48 #include "FrameView.hxx" 49 50 #include <sfx2/viewfrm.hxx> 51 #include <vcl/wrkwin.hxx> 52 #include <toolkit/helper/vclunohelper.hxx> 53 54 #include <boost/bind.hpp> 55 56 using namespace ::com::sun::star; 57 using namespace ::com::sun::star::uno; 58 using namespace ::com::sun::star::lang; 59 using namespace ::com::sun::star::drawing::framework; 60 61 using ::rtl::OUString; 62 using ::sd::framework::FrameworkHelper; 63 64 65 namespace sd { namespace framework { 66 67 68 Reference<XInterface> SAL_CALL BasicViewFactory_createInstance ( 69 const Reference<XComponentContext>& rxContext) 70 { 71 return Reference<XInterface>(static_cast<XWeak*>(new BasicViewFactory(rxContext))); 72 } 73 74 75 76 77 ::rtl::OUString BasicViewFactory_getImplementationName (void) throw(RuntimeException) 78 { 79 return ::rtl::OUString( 80 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.framework.BasicViewFactory")); 81 } 82 83 84 85 86 Sequence<rtl::OUString> SAL_CALL BasicViewFactory_getSupportedServiceNames (void) 87 throw (RuntimeException) 88 { 89 static const ::rtl::OUString sServiceName( 90 ::rtl::OUString::createFromAscii("com.sun.star.drawing.framework.BasicViewFactory")); 91 return Sequence<rtl::OUString>(&sServiceName, 1); 92 } 93 94 95 96 97 //===== ViewDescriptor ======================================================== 98 99 class BasicViewFactory::ViewDescriptor 100 { 101 public: 102 Reference<XResource> mxView; 103 ::boost::shared_ptr<sd::ViewShell> mpViewShell; 104 ViewShellWrapper* mpWrapper; 105 Reference<XResourceId> mxViewId; 106 static bool CompareView (const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor, 107 const Reference<XResource>& rxView) 108 { return rpDescriptor->mxView.get() == rxView.get(); } 109 }; 110 111 112 113 114 115 //===== BasicViewFactory::ViewShellContainer ================================== 116 117 class BasicViewFactory::ViewShellContainer 118 : public ::std::vector<boost::shared_ptr<ViewDescriptor> > 119 { 120 public: 121 ViewShellContainer (void) {}; 122 }; 123 124 125 class BasicViewFactory::ViewCache 126 : public ::std::vector<boost::shared_ptr<ViewDescriptor> > 127 { 128 public: 129 ViewCache (void) {}; 130 }; 131 132 133 134 135 //===== ViewFactory =========================================================== 136 137 BasicViewFactory::BasicViewFactory ( 138 const Reference<XComponentContext>& rxContext) 139 : BasicViewFactoryInterfaceBase(MutexOwner::maMutex), 140 mxConfigurationController(), 141 mpViewShellContainer(new ViewShellContainer()), 142 mpBase(NULL), 143 mpFrameView(NULL), 144 mpWindow(new WorkWindow(NULL,WB_STDWORK)), 145 mpViewCache(new ViewCache()), 146 mxLocalPane(new Pane(Reference<XResourceId>(), mpWindow.get())) 147 { 148 (void)rxContext; 149 } 150 151 152 153 154 BasicViewFactory::~BasicViewFactory (void) 155 { 156 } 157 158 159 160 161 void SAL_CALL BasicViewFactory::disposing (void) 162 { 163 // Disconnect from the frame view. 164 if (mpFrameView != NULL) 165 { 166 mpFrameView->Disconnect(); 167 mpFrameView = NULL; 168 } 169 170 // Relase the view cache. 171 ViewShellContainer::const_iterator iView; 172 for (iView=mpViewCache->begin(); iView!=mpViewCache->end(); ++iView) 173 { 174 ReleaseView(*iView, true); 175 } 176 177 // Release the view shell container. At this point no one other than us 178 // should hold references to the view shells (at the moment this is a 179 // trivial requirement, because no one other then us holds a shared 180 // pointer). 181 // ViewShellContainer::const_iterator iView; 182 for (iView=mpViewShellContainer->begin(); iView!=mpViewShellContainer->end(); ++iView) 183 { 184 OSL_ASSERT((*iView)->mpViewShell.unique()); 185 } 186 mpViewShellContainer.reset(); 187 } 188 189 190 191 192 Reference<XResource> SAL_CALL BasicViewFactory::createResource ( 193 const Reference<XResourceId>& rxViewId) 194 throw(RuntimeException, IllegalArgumentException, WrappedTargetException) 195 { 196 Reference<XResource> xView; 197 const bool bIsCenterPane ( 198 rxViewId->isBoundToURL(FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT)); 199 200 // Get the pane for the anchor URL. 201 Reference<XPane> xPane; 202 if (mxConfigurationController.is()) 203 xPane = Reference<XPane>(mxConfigurationController->getResource(rxViewId->getAnchor()), 204 UNO_QUERY); 205 206 // For main views use the frame view of the last main view. 207 ::sd::FrameView* pFrameView = NULL; 208 if (xPane.is() && bIsCenterPane) 209 { 210 pFrameView = mpFrameView; 211 } 212 213 // Get Window pointer for XWindow of the pane. 214 ::Window* pWindow = NULL; 215 if (xPane.is()) 216 pWindow = VCLUnoHelper::GetWindow(xPane->getWindow()); 217 218 // Get the view frame. 219 SfxViewFrame* pFrame = NULL; 220 if (mpBase != NULL) 221 pFrame = mpBase->GetViewFrame(); 222 223 if (pFrame != NULL && mpBase!=NULL && pWindow!=NULL) 224 { 225 // Try to get the view from the cache. 226 ::boost::shared_ptr<ViewDescriptor> pDescriptor (GetViewFromCache(rxViewId, xPane)); 227 228 // When the requested view is not in the cache then create a new view. 229 if (pDescriptor.get() == NULL) 230 { 231 pDescriptor = CreateView(rxViewId, *pFrame, *pWindow, xPane, pFrameView, bIsCenterPane); 232 } 233 234 if (pDescriptor.get() != NULL) 235 xView = pDescriptor->mxView; 236 237 mpViewShellContainer->push_back(pDescriptor); 238 239 if (bIsCenterPane) 240 ActivateCenterView(pDescriptor); 241 else 242 pWindow->Resize(); 243 } 244 245 return xView; 246 } 247 248 249 250 251 void SAL_CALL BasicViewFactory::releaseResource (const Reference<XResource>& rxView) 252 throw(RuntimeException) 253 { 254 if ( ! rxView.is()) 255 throw lang::IllegalArgumentException(); 256 257 if (rxView.is() && mpBase!=NULL) 258 { 259 ViewShellContainer::iterator iViewShell ( 260 ::std::find_if( 261 mpViewShellContainer->begin(), 262 mpViewShellContainer->end(), 263 ::boost::bind(&ViewDescriptor::CompareView, _1, rxView))); 264 if (iViewShell != mpViewShellContainer->end()) 265 { 266 ::boost::shared_ptr<ViewShell> pViewShell ((*iViewShell)->mpViewShell); 267 268 if ((*iViewShell)->mxViewId->isBoundToURL( 269 FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT)) 270 { 271 // Obtain a pointer to and connect to the frame view of the 272 // view. The next view, that is created, will be 273 // initialized with this frame view. 274 if (mpFrameView == NULL) 275 { 276 mpFrameView = pViewShell->GetFrameView(); 277 if (mpFrameView) 278 mpFrameView->Connect(); 279 } 280 281 // With the view in the center pane the sub controller is 282 // released, too. 283 mpBase->GetDrawController().SetSubController( 284 Reference<drawing::XDrawSubController>()); 285 286 SfxViewShell* pSfxViewShell = pViewShell->GetViewShell(); 287 if (pSfxViewShell != NULL) 288 pSfxViewShell->DisconnectAllClients(); 289 } 290 291 ReleaseView(*iViewShell); 292 293 mpViewShellContainer->erase(iViewShell); 294 } 295 else 296 { 297 throw lang::IllegalArgumentException(); 298 } 299 } 300 } 301 302 303 304 305 void SAL_CALL BasicViewFactory::initialize (const Sequence<Any>& aArguments) 306 throw (Exception, RuntimeException) 307 { 308 if (aArguments.getLength() > 0) 309 { 310 Reference<XConfigurationController> xCC; 311 try 312 { 313 // Get the XController from the first argument. 314 Reference<frame::XController> xController (aArguments[0], UNO_QUERY_THROW); 315 316 // Tunnel through the controller to obtain a ViewShellBase. 317 Reference<lang::XUnoTunnel> xTunnel (xController, UNO_QUERY_THROW); 318 ::sd::DrawController* pController = reinterpret_cast<sd::DrawController*>( 319 xTunnel->getSomething(sd::DrawController::getUnoTunnelId())); 320 if (pController != NULL) 321 mpBase = pController->GetViewShellBase(); 322 323 // Register the factory for its supported views. 324 Reference<XControllerManager> xCM (xController,UNO_QUERY_THROW); 325 mxConfigurationController = xCM->getConfigurationController(); 326 if ( ! mxConfigurationController.is()) 327 throw RuntimeException(); 328 mxConfigurationController->addResourceFactory(FrameworkHelper::msImpressViewURL, this); 329 mxConfigurationController->addResourceFactory(FrameworkHelper::msDrawViewURL, this); 330 mxConfigurationController->addResourceFactory(FrameworkHelper::msOutlineViewURL, this); 331 mxConfigurationController->addResourceFactory(FrameworkHelper::msNotesViewURL, this); 332 mxConfigurationController->addResourceFactory(FrameworkHelper::msHandoutViewURL, this); 333 mxConfigurationController->addResourceFactory(FrameworkHelper::msPresentationViewURL, this); 334 mxConfigurationController->addResourceFactory(FrameworkHelper::msTaskPaneURL, this); 335 mxConfigurationController->addResourceFactory(FrameworkHelper::msSlideSorterURL, this); 336 } 337 catch (RuntimeException&) 338 { 339 mpBase = NULL; 340 if (mxConfigurationController.is()) 341 mxConfigurationController->removeResourceFactoryForReference(this); 342 throw; 343 } 344 } 345 } 346 347 348 349 350 ::boost::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::CreateView ( 351 const Reference<XResourceId>& rxViewId, 352 SfxViewFrame& rFrame, 353 ::Window& rWindow, 354 const Reference<XPane>& rxPane, 355 FrameView* pFrameView, 356 const bool bIsCenterPane) 357 { 358 ::boost::shared_ptr<ViewDescriptor> pDescriptor (new ViewDescriptor()); 359 360 pDescriptor->mpViewShell = CreateViewShell( 361 rxViewId, 362 rFrame, 363 rWindow, 364 pFrameView, 365 bIsCenterPane); 366 pDescriptor->mxViewId = rxViewId; 367 368 if (pDescriptor->mpViewShell.get() != NULL) 369 { 370 pDescriptor->mpViewShell->Init(bIsCenterPane); 371 mpBase->GetViewShellManager()->ActivateViewShell(pDescriptor->mpViewShell.get()); 372 373 pDescriptor->mpWrapper = new ViewShellWrapper( 374 pDescriptor->mpViewShell, 375 rxViewId, 376 rxPane->getWindow()); 377 pDescriptor->mxView.set( pDescriptor->mpWrapper->queryInterface( XResource::static_type() ), UNO_QUERY_THROW ); 378 } 379 380 return pDescriptor; 381 } 382 383 384 385 386 ::boost::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell ( 387 const Reference<XResourceId>& rxViewId, 388 SfxViewFrame& rFrame, 389 ::Window& rWindow, 390 FrameView* pFrameView, 391 const bool bIsCenterPane) 392 { 393 ::boost::shared_ptr<ViewShell> pViewShell; 394 const OUString& rsViewURL (rxViewId->getResourceURL()); 395 if (rsViewURL.equals(FrameworkHelper::msImpressViewURL)) 396 { 397 pViewShell.reset( 398 new DrawViewShell( 399 &rFrame, 400 *mpBase, 401 &rWindow, 402 PK_STANDARD, 403 pFrameView)); 404 } 405 else if (rsViewURL.equals(FrameworkHelper::msDrawViewURL)) 406 { 407 pViewShell.reset( 408 new GraphicViewShell ( 409 &rFrame, 410 *mpBase, 411 &rWindow, 412 pFrameView)); 413 } 414 else if (rsViewURL.equals(FrameworkHelper::msOutlineViewURL)) 415 { 416 pViewShell.reset( 417 new OutlineViewShell ( 418 &rFrame, 419 *mpBase, 420 &rWindow, 421 pFrameView)); 422 } 423 else if (rsViewURL.equals(FrameworkHelper::msNotesViewURL)) 424 { 425 pViewShell.reset( 426 new DrawViewShell( 427 &rFrame, 428 *mpBase, 429 &rWindow, 430 PK_NOTES, 431 pFrameView)); 432 } 433 else if (rsViewURL.equals(FrameworkHelper::msHandoutViewURL)) 434 { 435 pViewShell.reset( 436 new DrawViewShell( 437 &rFrame, 438 *mpBase, 439 &rWindow, 440 PK_HANDOUT, 441 pFrameView)); 442 } 443 else if (rsViewURL.equals(FrameworkHelper::msPresentationViewURL)) 444 { 445 pViewShell.reset( 446 new PresentationViewShell( 447 &rFrame, 448 *mpBase, 449 &rWindow, 450 pFrameView)); 451 } 452 else if (rsViewURL.equals(FrameworkHelper::msTaskPaneURL)) 453 { 454 pViewShell.reset( 455 new ::sd::toolpanel::ToolPanelViewShell( 456 &rFrame, 457 *mpBase, 458 &rWindow, 459 pFrameView)); 460 } 461 else if (rsViewURL.equals(FrameworkHelper::msSlideSorterURL)) 462 { 463 pViewShell = ::sd::slidesorter::SlideSorterViewShell::Create ( 464 &rFrame, 465 *mpBase, 466 &rWindow, 467 pFrameView, 468 bIsCenterPane); 469 } 470 471 return pViewShell; 472 } 473 474 475 476 477 void BasicViewFactory::ReleaseView ( 478 const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor, 479 bool bDoNotCache) 480 { 481 bool bIsCacheable (!bDoNotCache && IsCacheable(rpDescriptor)); 482 483 if (bIsCacheable) 484 { 485 Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY); 486 if (xResource.is()) 487 { 488 Reference<XResource> xNewAnchor (mxLocalPane, UNO_QUERY); 489 if (xNewAnchor.is()) 490 if (xResource->relocateToAnchor(xNewAnchor)) 491 mpViewCache->push_back(rpDescriptor); 492 else 493 bIsCacheable = false; 494 else 495 bIsCacheable = false; 496 } 497 else 498 { 499 bIsCacheable = false; 500 } 501 } 502 503 if ( ! bIsCacheable) 504 { 505 // Shut down the current view shell. 506 rpDescriptor->mpViewShell->Shutdown (); 507 mpBase->GetDocShell()->Disconnect(rpDescriptor->mpViewShell.get()); 508 mpBase->GetViewShellManager()->DeactivateViewShell(rpDescriptor->mpViewShell.get()); 509 510 Reference<XComponent> xComponent (rpDescriptor->mxView, UNO_QUERY); 511 if (xComponent.is()) 512 xComponent->dispose(); 513 } 514 } 515 516 517 518 519 bool BasicViewFactory::IsCacheable (const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor) 520 { 521 bool bIsCacheable (false); 522 523 Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY); 524 if (xResource.is()) 525 { 526 static ::std::vector<Reference<XResourceId> > maCacheableResources; 527 if (maCacheableResources.empty() ) 528 { 529 ::boost::shared_ptr<FrameworkHelper> pHelper (FrameworkHelper::Instance(*mpBase)); 530 531 // The slide sorter and the task panel are cacheable and relocatable. 532 maCacheableResources.push_back(pHelper->CreateResourceId( 533 FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftDrawPaneURL)); 534 maCacheableResources.push_back(pHelper->CreateResourceId( 535 FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftImpressPaneURL)); 536 maCacheableResources.push_back(pHelper->CreateResourceId( 537 FrameworkHelper::msTaskPaneURL, FrameworkHelper::msRightPaneURL)); 538 } 539 540 ::std::vector<Reference<XResourceId> >::const_iterator iId; 541 for (iId=maCacheableResources.begin(); iId!=maCacheableResources.end(); ++iId) 542 { 543 if ((*iId)->compareTo(rpDescriptor->mxViewId) == 0) 544 { 545 bIsCacheable = true; 546 break; 547 } 548 } 549 } 550 551 return bIsCacheable; 552 } 553 554 555 556 557 ::boost::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::GetViewFromCache ( 558 const Reference<XResourceId>& rxViewId, 559 const Reference<XPane>& rxPane) 560 { 561 ::boost::shared_ptr<ViewDescriptor> pDescriptor; 562 563 // Search for the requested view in the cache. 564 ViewCache::iterator iEntry; 565 for (iEntry=mpViewCache->begin(); iEntry!=mpViewCache->end(); ++iEntry) 566 { 567 if ((*iEntry)->mxViewId->compareTo(rxViewId) == 0) 568 { 569 pDescriptor = *iEntry; 570 mpViewCache->erase(iEntry); 571 break; 572 } 573 } 574 575 // When the view has been found then relocate it to the given pane and 576 // remove it from the cache. 577 if (pDescriptor.get() != NULL) 578 { 579 bool bRelocationSuccessfull (false); 580 Reference<XRelocatableResource> xResource (pDescriptor->mxView, UNO_QUERY); 581 Reference<XResource> xNewAnchor (rxPane, UNO_QUERY); 582 if (xResource.is() && xNewAnchor.is()) 583 { 584 if (xResource->relocateToAnchor(xNewAnchor)) 585 bRelocationSuccessfull = true; 586 } 587 588 if ( ! bRelocationSuccessfull) 589 { 590 ReleaseView(pDescriptor, true); 591 pDescriptor.reset(); 592 } 593 } 594 595 return pDescriptor; 596 } 597 598 599 600 601 void BasicViewFactory::ActivateCenterView ( 602 const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor) 603 { 604 mpBase->GetDocShell()->Connect(rpDescriptor->mpViewShell.get()); 605 606 // During the creation of the new sub-shell, resize requests were not 607 // forwarded to it because it was not yet registered. Therefore, we 608 // have to request a resize now. 609 rpDescriptor->mpViewShell->UIFeatureChanged(); 610 if (mpBase->GetDocShell()->IsInPlaceActive()) 611 mpBase->GetViewFrame()->Resize(sal_True); 612 613 mpBase->GetDrawController().SetSubController( 614 rpDescriptor->mpViewShell->CreateSubController()); 615 } 616 617 } } // end of namespace sd::framework 618