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