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