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