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 <osl/time.h> 31 32 #include "framework/FrameworkHelper.hxx" 33 34 #include "framework/ConfigurationController.hxx" 35 #include "framework/ResourceId.hxx" 36 #include "framework/ViewShellWrapper.hxx" 37 #include "ViewShellBase.hxx" 38 #include "FrameView.hxx" 39 #include "DrawViewShell.hxx" 40 #include "ViewShellHint.hxx" 41 #include "DrawController.hxx" 42 #include "app.hrc" 43 #include <com/sun/star/drawing/framework/XControllerManager.hpp> 44 #include <cppuhelper/compbase1.hxx> 45 #include <svl/lstner.hxx> 46 47 #include <comphelper/stl_types.hxx> 48 #include <sfx2/request.hxx> 49 #include <sfx2/dispatch.hxx> 50 51 #include "MutexOwner.hxx" 52 #include "vcl/svapp.hxx" 53 #include <osl/doublecheckedlocking.h> 54 #include <osl/getglobalmutex.hxx> 55 #include <tools/diagnose_ex.h> 56 57 using namespace ::com::sun::star; 58 using namespace ::com::sun::star::uno; 59 using namespace ::com::sun::star::drawing::framework; 60 61 using ::rtl::OUString; 62 63 namespace { 64 65 66 //----- CallbackCaller -------------------------------------------------------- 67 68 typedef ::cppu::WeakComponentImplHelper1 < 69 ::com::sun::star::drawing::framework::XConfigurationChangeListener 70 > CallbackCallerInterfaceBase; 71 72 /** A CallbackCaller registers as listener at an XConfigurationController 73 object and waits for the notification of one type of event. When that 74 event is received, or when the CallbackCaller detects at its 75 construction that the event will not be sent in the near future, the 76 actual callback object is called and the CallbackCaller destroys itself. 77 */ 78 class CallbackCaller 79 : public ::sd::MutexOwner, 80 public CallbackCallerInterfaceBase 81 { 82 public: 83 /** Create a new CallbackCaller object. This object controls its own 84 lifetime by acquiring a reference to itself in the constructor. 85 When it detects that the event will not be notified in the near 86 future (because the queue of pending configuration change operations 87 is empty and therefore no event will be sent int the near future, it 88 does not acquires a reference and thus initiates its destruction in 89 the constructor.) 90 @param rBase 91 This ViewShellBase object is used to determine the 92 XConfigurationController at which to register. 93 @param rsEventType 94 The event type which the callback is waiting for. 95 @param pCallback 96 The callback object which is to be notified. The caller will 97 typically release his reference to the caller so that when the 98 CallbackCaller dies (after having called the callback) the 99 callback is destroyed. 100 */ 101 CallbackCaller ( 102 ::sd::ViewShellBase& rBase, 103 const OUString& rsEventType, 104 const ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter& rFilter, 105 const ::sd::framework::FrameworkHelper::Callback& rCallback); 106 virtual ~CallbackCaller (void); 107 108 virtual void SAL_CALL disposing (void); 109 virtual void SAL_CALL disposing (const lang::EventObject& rEvent) 110 throw (RuntimeException); 111 virtual void SAL_CALL notifyConfigurationChange (const ConfigurationChangeEvent& rEvent) 112 throw (RuntimeException); 113 114 private: 115 OUString msEventType; 116 Reference<XConfigurationController> mxConfigurationController; 117 ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter maFilter; 118 ::sd::framework::FrameworkHelper::Callback maCallback; 119 }; 120 121 122 123 124 //----- LifetimeController ---------------------------------------------------- 125 126 typedef ::cppu::WeakComponentImplHelper1 < 127 ::com::sun::star::lang::XEventListener 128 > LifetimeControllerInterfaceBase; 129 130 /** This class helps controling the lifetime of the 131 FrameworkHelper. Register at a ViewShellBase object and an XController 132 object and call Dispose() at the associated FrameworkHelper object when 133 one of them and Release() when both of them are destroyed. 134 */ 135 class LifetimeController 136 : public ::sd::MutexOwner, 137 public LifetimeControllerInterfaceBase, 138 public SfxListener 139 { 140 public: 141 explicit LifetimeController (::sd::ViewShellBase& rBase); 142 virtual ~LifetimeController (void); 143 144 virtual void SAL_CALL disposing (void); 145 146 /** XEventListener. This method is called when the frame::XController 147 is being destroyed. 148 */ 149 virtual void SAL_CALL disposing (const lang::EventObject& rEvent) 150 throw (RuntimeException); 151 152 /** This method is called when the ViewShellBase is being destroyed. 153 */ 154 virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint); 155 156 private: 157 ::sd::ViewShellBase& mrBase; 158 bool mbListeningToViewShellBase; 159 bool mbListeningToController; 160 161 /** When one or both of the mbListeningToViewShellBase and 162 mbListeningToController members were modified then call this method 163 to either dispose or release the associated FrameworkHelper. 164 */ 165 void Update (void); 166 }; 167 168 169 170 } // end of anonymous namespace 171 172 namespace sd { namespace framework { 173 174 // Pane URLS. 175 176 const OUString FrameworkHelper::msPaneURLPrefix( 177 OUString::createFromAscii("private:resource/pane/")); 178 const OUString FrameworkHelper::msCenterPaneURL( 179 msPaneURLPrefix + OUString::createFromAscii("CenterPane")); 180 const OUString FrameworkHelper::msFullScreenPaneURL( 181 msPaneURLPrefix + OUString::createFromAscii("FullScreenPane")); 182 const OUString FrameworkHelper::msLeftImpressPaneURL( 183 msPaneURLPrefix + OUString::createFromAscii("LeftImpressPane")); 184 const OUString FrameworkHelper::msLeftDrawPaneURL( 185 msPaneURLPrefix + OUString::createFromAscii("LeftDrawPane")); 186 const OUString FrameworkHelper::msRightPaneURL( 187 msPaneURLPrefix + OUString::createFromAscii("RightPane")); 188 189 190 // View URLs. 191 192 const OUString FrameworkHelper::msViewURLPrefix( 193 OUString::createFromAscii("private:resource/view/")); 194 const OUString FrameworkHelper::msImpressViewURL( 195 msViewURLPrefix + OUString::createFromAscii("ImpressView")); 196 const OUString FrameworkHelper::msDrawViewURL( 197 msViewURLPrefix + OUString::createFromAscii("GraphicView")); 198 const OUString FrameworkHelper::msOutlineViewURL( 199 msViewURLPrefix + OUString::createFromAscii("OutlineView")); 200 const OUString FrameworkHelper::msNotesViewURL( 201 msViewURLPrefix + OUString::createFromAscii("NotesView")); 202 const OUString FrameworkHelper::msHandoutViewURL( 203 msViewURLPrefix + OUString::createFromAscii("HandoutView")); 204 const OUString FrameworkHelper::msSlideSorterURL( 205 msViewURLPrefix + OUString::createFromAscii("SlideSorter")); 206 const OUString FrameworkHelper::msPresentationViewURL( 207 msViewURLPrefix + OUString::createFromAscii("PresentationView")); 208 const OUString FrameworkHelper::msTaskPaneURL( 209 msViewURLPrefix + OUString::createFromAscii("TaskPane")); 210 211 212 // Tool bar URLs. 213 214 const OUString FrameworkHelper::msToolBarURLPrefix( 215 OUString::createFromAscii("private:resource/toolbar/")); 216 const OUString FrameworkHelper::msViewTabBarURL( 217 msToolBarURLPrefix + OUString::createFromAscii("ViewTabBar")); 218 219 220 // Task panel URLs. 221 const ::rtl::OUString FrameworkHelper::msTaskPanelURLPrefix( 222 OUString::createFromAscii("private:resource/toolpanel/DrawingFramework/")); 223 const ::rtl::OUString FrameworkHelper::msMasterPagesTaskPanelURL( 224 msTaskPanelURLPrefix + OUString::createFromAscii("MasterPages")); 225 const ::rtl::OUString FrameworkHelper::msLayoutTaskPanelURL( 226 msTaskPanelURLPrefix + OUString::createFromAscii("Layouts")); 227 const ::rtl::OUString FrameworkHelper::msTableDesignPanelURL( 228 msTaskPanelURLPrefix + OUString::createFromAscii("TableDesign")); 229 const ::rtl::OUString FrameworkHelper::msCustomAnimationTaskPanelURL( 230 msTaskPanelURLPrefix + OUString::createFromAscii("CustomAnimations")); 231 const ::rtl::OUString FrameworkHelper::msSlideTransitionTaskPanelURL( 232 msTaskPanelURLPrefix + OUString::createFromAscii("SlideTransitions")); 233 234 235 // Event URLs. 236 const OUString FrameworkHelper::msResourceActivationRequestEvent( 237 OUString::createFromAscii("ResourceActivationRequested")); 238 const OUString FrameworkHelper::msResourceDeactivationRequestEvent( 239 OUString::createFromAscii("ResourceDeactivationRequest")); 240 const OUString FrameworkHelper::msResourceActivationEvent( 241 OUString::createFromAscii("ResourceActivation")); 242 const OUString FrameworkHelper::msResourceDeactivationEvent( 243 OUString::createFromAscii("ResourceDeactivation")); 244 const OUString FrameworkHelper::msConfigurationUpdateStartEvent( 245 OUString::createFromAscii("ConfigurationUpdateStart")); 246 const OUString FrameworkHelper::msConfigurationUpdateEndEvent( 247 OUString::createFromAscii("ConfigurationUpdateEnd")); 248 249 250 // Service names of controllers. 251 const OUString FrameworkHelper::msModuleControllerService( 252 OUString::createFromAscii("com.sun.star.drawing.framework.ModuleController")); 253 const OUString FrameworkHelper::msConfigurationControllerService( 254 OUString::createFromAscii("com.sun.star.drawing.framework.ConfigurationController")); 255 256 //----- helper ---------------------------------------------------------------- 257 namespace 258 { 259 static ::boost::shared_ptr< ViewShell > lcl_getViewShell( const Reference< XResource >& i_rViewShellWrapper ) 260 { 261 ::boost::shared_ptr< ViewShell > pViewShell; 262 if ( !i_rViewShellWrapper.is() ) 263 return pViewShell; 264 265 try 266 { 267 Reference<lang::XUnoTunnel> xViewTunnel( i_rViewShellWrapper, UNO_QUERY_THROW ); 268 pViewShell = reinterpret_cast< ViewShellWrapper* >( 269 xViewTunnel->getSomething( ViewShellWrapper::getUnoTunnelId() ) )->GetViewShell(); 270 } 271 catch( const Exception& ) 272 { 273 DBG_UNHANDLED_EXCEPTION(); 274 } 275 return pViewShell; 276 } 277 Reference< XResource > lcl_getFirstViewInPane( const Reference< XConfigurationController >& i_rConfigController, 278 const Reference< XResourceId >& i_rPaneId ) 279 { 280 try 281 { 282 Reference< XConfiguration > xConfiguration( i_rConfigController->getRequestedConfiguration(), UNO_SET_THROW ); 283 Sequence< Reference< XResourceId > > aViewIds( xConfiguration->getResources( 284 i_rPaneId, FrameworkHelper::msViewURLPrefix, AnchorBindingMode_DIRECT ) ); 285 if ( aViewIds.getLength() > 0 ) 286 return i_rConfigController->getResource( aViewIds[0] ); 287 } 288 catch( const Exception& ) 289 { 290 DBG_UNHANDLED_EXCEPTION(); 291 } 292 return NULL; 293 } 294 } 295 296 297 //----- FrameworkHelper::ViewURLMap ------------------------------------------- 298 299 /** The ViewURLMap is used to translate between the view URLs used by the 300 drawing framework and the enums defined in the ViewShell class. 301 */ 302 class FrameworkHelper::ViewURLMap 303 : public ::std::hash_map< 304 rtl::OUString, 305 ViewShell::ShellType, 306 ::comphelper::UStringHash, 307 ::comphelper::UStringEqual> 308 { 309 public: 310 ViewURLMap (void) {} 311 }; 312 313 314 315 316 //----- Framework::DiposeListener --------------------------------------------- 317 318 namespace { 319 typedef ::cppu::WeakComponentImplHelper1 < 320 ::com::sun::star::lang::XEventListener 321 > FrameworkHelperDisposeListenerInterfaceBase; 322 } 323 324 class FrameworkHelper::DisposeListener 325 : public ::sd::MutexOwner, 326 public FrameworkHelperDisposeListenerInterfaceBase 327 { 328 public: 329 DisposeListener (const ::boost::shared_ptr<FrameworkHelper>& rpHelper); 330 ~DisposeListener (void); 331 332 virtual void SAL_CALL disposing (void); 333 334 virtual void SAL_CALL disposing (const lang::EventObject& rEventObject) 335 throw(RuntimeException); 336 337 private: 338 ::boost::shared_ptr<FrameworkHelper> mpHelper; 339 }; 340 341 342 343 344 //----- FrameworkHelper ------------------------------------------------------- 345 346 ::boost::scoped_ptr<FrameworkHelper::ViewURLMap> FrameworkHelper::mpViewURLMap(new ViewURLMap()); 347 348 349 FrameworkHelper::InstanceMap FrameworkHelper::maInstanceMap; 350 351 352 353 ::boost::shared_ptr<FrameworkHelper> FrameworkHelper::Instance ( 354 const Reference<frame::XController>& rxController) 355 { 356 // Tunnel through the controller to obtain a ViewShellBase. 357 Reference<lang::XUnoTunnel> xTunnel (rxController, UNO_QUERY); 358 if (xTunnel.is()) 359 { 360 ::sd::DrawController* pController = reinterpret_cast<sd::DrawController*>( 361 xTunnel->getSomething(sd::DrawController::getUnoTunnelId())); 362 if (pController != NULL) 363 { 364 ViewShellBase* pBase = pController->GetViewShellBase(); 365 if (pBase != NULL) 366 return Instance(*pBase); 367 } 368 } 369 370 return ::boost::shared_ptr<FrameworkHelper>(); 371 } 372 373 374 375 376 ::boost::shared_ptr<FrameworkHelper> FrameworkHelper::Instance (ViewShellBase& rBase) 377 { 378 379 ::boost::shared_ptr<FrameworkHelper> pHelper; 380 381 InstanceMap::const_iterator iHelper (maInstanceMap.find(&rBase)); 382 if (iHelper == maInstanceMap.end()) 383 { 384 ::osl::GetGlobalMutex aMutexFunctor; 385 ::osl::MutexGuard aGuard (aMutexFunctor()); 386 if (iHelper == maInstanceMap.end()) 387 { 388 pHelper = ::boost::shared_ptr<FrameworkHelper>(new FrameworkHelper(rBase)); 389 pHelper->Initialize(); 390 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 391 SdGlobalResourceContainer::Instance().AddResource(pHelper); 392 maInstanceMap[&rBase] = pHelper; 393 } 394 } 395 else 396 { 397 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 398 pHelper = iHelper->second; 399 } 400 401 return pHelper; 402 } 403 404 405 406 407 void FrameworkHelper::DisposeInstance (ViewShellBase& rBase) 408 { 409 InstanceMap::iterator iHelper (maInstanceMap.find(&rBase)); 410 if (iHelper != maInstanceMap.end()) 411 { 412 iHelper->second->Dispose(); 413 } 414 } 415 416 417 418 419 void FrameworkHelper::ReleaseInstance (ViewShellBase& rBase) 420 { 421 InstanceMap::iterator iHelper (maInstanceMap.find(&rBase)); 422 if (iHelper != maInstanceMap.end()) 423 maInstanceMap.erase(iHelper); 424 } 425 426 427 428 429 FrameworkHelper::FrameworkHelper (ViewShellBase& rBase) 430 : mrBase(rBase), 431 mxConfigurationController(), 432 mxDisposeListener() 433 434 { 435 Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY); 436 if (xControllerManager.is()) 437 { 438 mxConfigurationController = xControllerManager->getConfigurationController(); 439 } 440 441 new LifetimeController(mrBase); 442 } 443 444 445 446 447 void FrameworkHelper::Initialize (void) 448 { 449 mxDisposeListener = new DisposeListener(shared_from_this()); 450 } 451 452 453 454 455 FrameworkHelper::~FrameworkHelper (void) 456 { 457 } 458 459 460 461 462 void FrameworkHelper::Dispose (void) 463 { 464 if (mxDisposeListener.is()) 465 mxDisposeListener->dispose(); 466 mxConfigurationController = NULL; 467 } 468 469 470 471 472 bool FrameworkHelper::IsValid (void) 473 { 474 return mxConfigurationController.is(); 475 } 476 477 478 479 480 ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const OUString& rsPaneURL) 481 { 482 if ( !mxConfigurationController.is() ) 483 return ::boost::shared_ptr<ViewShell>(); 484 485 Reference<XResourceId> xPaneId( CreateResourceId( rsPaneURL ) ); 486 return lcl_getViewShell( lcl_getFirstViewInPane( mxConfigurationController, xPaneId ) ); 487 } 488 489 490 491 492 ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const Reference<XView>& rxView) 493 { 494 return lcl_getViewShell( rxView.get() ); 495 } 496 497 498 499 500 Reference<XView> FrameworkHelper::GetView (const Reference<XResourceId>& rxPaneOrViewId) 501 { 502 Reference<XView> xView; 503 504 if ( ! rxPaneOrViewId.is() || ! mxConfigurationController.is()) 505 return NULL; 506 507 try 508 { 509 if (rxPaneOrViewId->getResourceURL().match(msViewURLPrefix)) 510 { 511 xView.set( mxConfigurationController->getResource( rxPaneOrViewId ), UNO_QUERY ); 512 } 513 else 514 { 515 xView.set( lcl_getFirstViewInPane( mxConfigurationController, rxPaneOrViewId ), UNO_QUERY ); 516 } 517 } 518 catch (lang::DisposedException&) 519 { 520 Dispose(); 521 } 522 catch (RuntimeException&) 523 { 524 } 525 526 return xView; 527 } 528 529 530 531 532 Reference<XResourceId> FrameworkHelper::RequestView ( 533 const OUString& rsResourceURL, 534 const OUString& rsAnchorURL) 535 { 536 Reference<XResourceId> xViewId; 537 538 try 539 { 540 if (mxConfigurationController.is()) 541 { 542 mxConfigurationController->requestResourceActivation( 543 CreateResourceId(rsAnchorURL), 544 ResourceActivationMode_ADD); 545 xViewId = CreateResourceId(rsResourceURL, rsAnchorURL); 546 mxConfigurationController->requestResourceActivation( 547 xViewId, 548 ResourceActivationMode_REPLACE); 549 } 550 } 551 catch (lang::DisposedException&) 552 { 553 Dispose(); 554 xViewId = NULL; 555 } 556 catch (RuntimeException&) 557 { 558 xViewId = NULL; 559 } 560 561 return xViewId; 562 } 563 564 565 566 567 void FrameworkHelper::RequestTaskPanel ( 568 const OUString& rsTaskPanelURL, 569 const bool bEnsureTaskPaneIsVisible) 570 { 571 try 572 { 573 if (mxConfigurationController.is()) 574 { 575 // Check the existence of the task pane. 576 if ( ! bEnsureTaskPaneIsVisible) 577 { 578 Reference<XConfiguration> xConfiguration ( 579 mxConfigurationController->getCurrentConfiguration()); 580 if (xConfiguration.is()) 581 if ( ! xConfiguration->hasResource( 582 CreateResourceId(msTaskPaneURL, msRightPaneURL))) 583 { 584 // Task pane does is not active. Do not force it. 585 return; 586 } 587 } 588 589 // Create the resource id from URLs for the pane, the task pane 590 // view, and the task panel. 591 mxConfigurationController->requestResourceActivation( 592 CreateResourceId(msRightPaneURL), 593 ResourceActivationMode_ADD); 594 mxConfigurationController->requestResourceActivation( 595 CreateResourceId(msTaskPaneURL, msRightPaneURL), 596 ResourceActivationMode_REPLACE); 597 mxConfigurationController->requestResourceActivation( 598 CreateResourceId(rsTaskPanelURL, msTaskPaneURL, msRightPaneURL), 599 ResourceActivationMode_REPLACE); 600 } 601 } 602 catch (lang::DisposedException&) 603 { 604 Dispose(); 605 } 606 catch (RuntimeException&) 607 {} 608 } 609 610 611 612 613 ViewShell::ShellType FrameworkHelper::GetViewId (const rtl::OUString& rsViewURL) 614 { 615 if (mpViewURLMap->empty()) 616 { 617 (*mpViewURLMap)[msImpressViewURL] = ViewShell::ST_IMPRESS; 618 (*mpViewURLMap)[msDrawViewURL] = ViewShell::ST_DRAW; 619 (*mpViewURLMap)[msOutlineViewURL] = ViewShell::ST_OUTLINE; 620 (*mpViewURLMap)[msNotesViewURL] = ViewShell::ST_NOTES; 621 (*mpViewURLMap)[msHandoutViewURL] = ViewShell::ST_HANDOUT; 622 (*mpViewURLMap)[msSlideSorterURL] = ViewShell::ST_SLIDE_SORTER; 623 (*mpViewURLMap)[msPresentationViewURL] = ViewShell::ST_PRESENTATION; 624 (*mpViewURLMap)[msTaskPaneURL] = ViewShell::ST_TASK_PANE; 625 } 626 ViewURLMap::const_iterator iView (mpViewURLMap->find(rsViewURL)); 627 if (iView != mpViewURLMap->end()) 628 return iView->second; 629 else 630 return ViewShell::ST_NONE; 631 } 632 633 634 635 636 ::rtl::OUString FrameworkHelper::GetViewURL (ViewShell::ShellType eType) 637 { 638 switch (eType) 639 { 640 case ViewShell::ST_IMPRESS : return msImpressViewURL; 641 case ViewShell::ST_DRAW : return msDrawViewURL; 642 case ViewShell::ST_OUTLINE : return msOutlineViewURL; 643 case ViewShell::ST_NOTES : return msNotesViewURL; 644 case ViewShell::ST_HANDOUT : return msHandoutViewURL; 645 case ViewShell::ST_SLIDE_SORTER : return msSlideSorterURL; 646 case ViewShell::ST_PRESENTATION : return msPresentationViewURL; 647 case ViewShell::ST_TASK_PANE : return msTaskPaneURL; 648 default: 649 return OUString(); 650 } 651 } 652 653 654 655 656 void FrameworkHelper::HandleModeChangeSlot ( 657 sal_uLong nSlotId, 658 SfxRequest& rRequest) 659 { 660 sal_Bool bIsActive = sal_True; 661 662 if ( ! mxConfigurationController.is()) 663 return; 664 665 switch (nSlotId) 666 { 667 case SID_DRAWINGMODE: 668 case SID_NOTESMODE: 669 case SID_HANDOUTMODE: 670 case SID_DIAMODE: 671 case SID_OUTLINEMODE: 672 { 673 const SfxItemSet* pRequestArguments = rRequest.GetArgs(); 674 if (pRequestArguments) 675 { 676 SFX_REQUEST_ARG (rRequest, 677 pIsActive, 678 SfxBoolItem, 679 (sal_uInt16)nSlotId, 680 sal_False); 681 bIsActive = pIsActive->GetValue (); 682 } 683 } 684 break; 685 } 686 687 try 688 { 689 if ( ! mxConfigurationController.is()) 690 throw RuntimeException(); 691 692 693 Reference<XResourceId> xPaneId ( 694 CreateResourceId(framework::FrameworkHelper::msCenterPaneURL)); 695 Reference<XView> xView (GetView(xPaneId)); 696 ::boost::shared_ptr<ViewShell> pCenterViewShell (GetViewShell(xView)); 697 698 ::rtl::OUString sRequestedView; 699 if (bIsActive) 700 { 701 switch (nSlotId) 702 { 703 case SID_NORMAL_MULTI_PANE_GUI: 704 case SID_DRAWINGMODE: 705 sRequestedView = FrameworkHelper::msImpressViewURL; 706 break; 707 708 case SID_NOTESMODE: 709 sRequestedView = FrameworkHelper::msNotesViewURL; 710 break; 711 712 case SID_HANDOUTMODE: 713 sRequestedView = FrameworkHelper::msHandoutViewURL; 714 break; 715 716 case SID_SLIDE_SORTER_MULTI_PANE_GUI: 717 case SID_DIAMODE: 718 sRequestedView = FrameworkHelper::msSlideSorterURL; 719 break; 720 721 case SID_OUTLINEMODE: 722 sRequestedView = FrameworkHelper::msOutlineViewURL; 723 break; 724 } 725 } 726 727 if (xView.is() 728 && xView->getResourceId()->getResourceURL().equals(sRequestedView)) 729 { 730 // We do not have to switch the view shell but maybe the edit mode 731 // has changed. 732 DrawViewShell* pDrawViewShell 733 = dynamic_cast<DrawViewShell*>(pCenterViewShell.get()); 734 if (pDrawViewShell != NULL) 735 { 736 pCenterViewShell->Broadcast ( 737 ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_START)); 738 739 pDrawViewShell->ChangeEditMode ( 740 EM_PAGE, pDrawViewShell->IsLayerModeActive()); 741 742 pCenterViewShell->Broadcast ( 743 ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_END)); 744 } 745 } 746 else 747 { 748 mxConfigurationController->requestResourceActivation( 749 CreateResourceId(sRequestedView, msCenterPaneURL), 750 ResourceActivationMode_REPLACE); 751 } 752 } 753 catch (RuntimeException&) 754 { 755 DBG_UNHANDLED_EXCEPTION(); 756 } 757 } 758 759 760 761 762 void FrameworkHelper::RunOnConfigurationEvent( 763 const ::rtl::OUString& rsEventType, 764 const Callback& rCallback) 765 { 766 RunOnEvent( 767 rsEventType, 768 FrameworkHelperAllPassFilter(), 769 rCallback); 770 } 771 772 773 774 775 void FrameworkHelper::RunOnResourceActivation( 776 const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId, 777 const Callback& rCallback) 778 { 779 if (mxConfigurationController.is() 780 && mxConfigurationController->getResource(rxResourceId).is()) 781 { 782 rCallback(false); 783 } 784 else 785 { 786 RunOnEvent( 787 msResourceActivationEvent, 788 FrameworkHelperResourceIdFilter(rxResourceId), 789 rCallback); 790 } 791 } 792 793 794 795 796 /** A callback that sets a flag to a specified value when the callback is 797 called. 798 */ 799 class FlagUpdater 800 { 801 public: 802 FlagUpdater (bool& rFlag) : mrFlag(rFlag) {} 803 void operator() (bool) {mrFlag = true;} 804 private: 805 bool& mrFlag; 806 }; 807 808 809 810 811 void FrameworkHelper::RequestSynchronousUpdate (void) 812 { 813 rtl::Reference<ConfigurationController> pCC ( 814 dynamic_cast<ConfigurationController*>(mxConfigurationController.get())); 815 if (pCC.is()) 816 pCC->RequestSynchronousUpdate(); 817 } 818 819 820 821 822 void FrameworkHelper::WaitForEvent (const OUString& rsEventType) const 823 { 824 bool bConfigurationUpdateSeen (false); 825 826 RunOnEvent( 827 rsEventType, 828 FrameworkHelperAllPassFilter(), 829 FlagUpdater(bConfigurationUpdateSeen)); 830 831 sal_uInt32 nStartTime = osl_getGlobalTimer(); 832 while ( ! bConfigurationUpdateSeen) 833 { 834 Application::Reschedule(); 835 836 if( (osl_getGlobalTimer() - nStartTime) > 60000 ) 837 { 838 DBG_ERROR("FrameworkHelper::WaitForEvent(), no event for a minute? giving up!"); 839 break; 840 } 841 } 842 } 843 844 845 846 847 void FrameworkHelper::WaitForUpdate (void) const 848 { 849 WaitForEvent(msConfigurationUpdateEndEvent); 850 } 851 852 853 854 855 void FrameworkHelper::RunOnEvent( 856 const ::rtl::OUString& rsEventType, 857 const ConfigurationChangeEventFilter& rFilter, 858 const Callback& rCallback) const 859 { 860 new CallbackCaller(mrBase,rsEventType,rFilter,rCallback); 861 } 862 863 864 865 866 void FrameworkHelper::disposing (const lang::EventObject& rEventObject) 867 { 868 if (rEventObject.Source == mxConfigurationController) 869 mxConfigurationController = NULL; 870 } 871 872 873 874 875 void FrameworkHelper::UpdateConfiguration (void) 876 { 877 if (mxConfigurationController.is()) 878 { 879 try 880 { 881 if (mxConfigurationController.is()) 882 mxConfigurationController->update(); 883 } 884 catch (lang::DisposedException&) 885 { 886 Dispose(); 887 } 888 catch (RuntimeException&) 889 { 890 DBG_UNHANDLED_EXCEPTION(); 891 } 892 } 893 } 894 895 896 897 898 OUString FrameworkHelper::ResourceIdToString (const Reference<XResourceId>& rxResourceId) 899 { 900 OUString sString; 901 if (rxResourceId.is()) 902 { 903 sString += rxResourceId->getResourceURL(); 904 if (rxResourceId->hasAnchor()) 905 { 906 Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs()); 907 for (sal_Int32 nIndex=0; nIndex<aAnchorURLs.getLength(); ++nIndex) 908 { 909 sString += OUString::createFromAscii(" | "); 910 sString += aAnchorURLs[nIndex]; 911 } 912 } 913 } 914 return sString; 915 } 916 917 918 919 920 Reference<XResourceId> FrameworkHelper::CreateResourceId (const ::rtl::OUString& rsResourceURL) 921 { 922 return new ::sd::framework::ResourceId(rsResourceURL); 923 } 924 925 926 927 928 Reference<XResourceId> FrameworkHelper::CreateResourceId ( 929 const OUString& rsResourceURL, 930 const OUString& rsAnchorURL) 931 { 932 return new ::sd::framework::ResourceId(rsResourceURL, rsAnchorURL); 933 } 934 935 936 937 938 Reference<XResourceId> FrameworkHelper::CreateResourceId ( 939 const OUString& rsResourceURL, 940 const OUString& rsFirstAnchorURL, 941 const OUString& rsSecondAnchorURL) 942 { 943 ::std::vector<OUString> aAnchorURLs (2); 944 aAnchorURLs[0] = rsFirstAnchorURL; 945 aAnchorURLs[1] = rsSecondAnchorURL; 946 return new ::sd::framework::ResourceId(rsResourceURL, aAnchorURLs); 947 } 948 949 950 951 952 Reference<XResourceId> FrameworkHelper::CreateResourceId ( 953 const ::rtl::OUString& rsResourceURL, 954 const Reference<XResourceId>& rxAnchorId) 955 { 956 if (rxAnchorId.is()) 957 return new ::sd::framework::ResourceId( 958 rsResourceURL, 959 rxAnchorId->getResourceURL(), 960 rxAnchorId->getAnchorURLs()); 961 else 962 return new ::sd::framework::ResourceId(rsResourceURL); 963 } 964 965 966 967 968 Reference<XConfigurationController> FrameworkHelper::GetConfigurationController (void) const 969 { 970 return mxConfigurationController; 971 } 972 973 974 975 976 //----- FrameworkHelper::DisposeListener -------------------------------------- 977 978 FrameworkHelper::DisposeListener::DisposeListener ( 979 const ::boost::shared_ptr<FrameworkHelper>& rpHelper) 980 : FrameworkHelperDisposeListenerInterfaceBase(maMutex), 981 mpHelper(rpHelper) 982 { 983 Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY); 984 if (xComponent.is()) 985 xComponent->addEventListener(this); 986 } 987 988 989 990 991 FrameworkHelper::DisposeListener::~DisposeListener (void) 992 { 993 } 994 995 996 997 998 void SAL_CALL FrameworkHelper::DisposeListener::disposing (void) 999 { 1000 Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY); 1001 if (xComponent.is()) 1002 xComponent->removeEventListener(this); 1003 1004 mpHelper.reset(); 1005 } 1006 1007 1008 1009 1010 void SAL_CALL FrameworkHelper::DisposeListener::disposing (const lang::EventObject& rEventObject) 1011 throw(RuntimeException) 1012 { 1013 if (mpHelper.get() != NULL) 1014 mpHelper->disposing(rEventObject); 1015 } 1016 1017 1018 1019 1020 //===== FrameworkHelperResourceIdFilter ======================================= 1021 1022 FrameworkHelperResourceIdFilter::FrameworkHelperResourceIdFilter ( 1023 const Reference<XResourceId>& rxResourceId) 1024 : mxResourceId(rxResourceId) 1025 { 1026 } 1027 1028 1029 } } // end of namespace sd::framework 1030 1031 namespace { 1032 1033 //===== CallbackCaller ======================================================== 1034 1035 CallbackCaller::CallbackCaller ( 1036 ::sd::ViewShellBase& rBase, 1037 const OUString& rsEventType, 1038 const ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter& rFilter, 1039 const ::sd::framework::FrameworkHelper::Callback& rCallback) 1040 : CallbackCallerInterfaceBase(MutexOwner::maMutex), 1041 msEventType(rsEventType), 1042 mxConfigurationController(), 1043 maFilter(rFilter), 1044 maCallback(rCallback) 1045 { 1046 try 1047 { 1048 Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY_THROW); 1049 mxConfigurationController = xControllerManager->getConfigurationController(); 1050 if (mxConfigurationController.is()) 1051 { 1052 if (mxConfigurationController->hasPendingRequests()) 1053 mxConfigurationController->addConfigurationChangeListener(this,msEventType,Any()); 1054 else 1055 { 1056 // There are no requests waiting to be processed. Therefore 1057 // no event, especially not the one we are waiting for, will 1058 // be sent in the near future and the callback would never be 1059 // called. 1060 // Call the callback now and tell him that the event it is 1061 // waiting for was not sent. 1062 mxConfigurationController = NULL; 1063 maCallback(false); 1064 } 1065 } 1066 } 1067 catch (RuntimeException&) 1068 { 1069 DBG_UNHANDLED_EXCEPTION(); 1070 } 1071 } 1072 1073 1074 1075 1076 CallbackCaller::~CallbackCaller (void) 1077 { 1078 } 1079 1080 1081 1082 1083 void CallbackCaller::disposing (void) 1084 { 1085 try 1086 { 1087 if (mxConfigurationController.is()) 1088 { 1089 Reference<XConfigurationController> xCC (mxConfigurationController); 1090 mxConfigurationController = NULL; 1091 xCC->removeConfigurationChangeListener(this); 1092 } 1093 } 1094 catch (RuntimeException&) 1095 { 1096 DBG_UNHANDLED_EXCEPTION(); 1097 } 1098 } 1099 1100 1101 1102 1103 void SAL_CALL CallbackCaller::disposing (const lang::EventObject& rEvent) 1104 throw (RuntimeException) 1105 { 1106 if (rEvent.Source == mxConfigurationController) 1107 { 1108 mxConfigurationController = NULL; 1109 maCallback(false); 1110 } 1111 } 1112 1113 1114 1115 1116 void SAL_CALL CallbackCaller::notifyConfigurationChange ( 1117 const ConfigurationChangeEvent& rEvent) 1118 throw (RuntimeException) 1119 { 1120 if (rEvent.Type.equals(msEventType) && maFilter(rEvent)) 1121 { 1122 maCallback(true); 1123 if (mxConfigurationController.is()) 1124 { 1125 // Reset the reference to the configuration controller so that 1126 // dispose() will not try to remove the listener a second time. 1127 Reference<XConfigurationController> xCC (mxConfigurationController); 1128 mxConfigurationController = NULL; 1129 1130 // Removing this object from the controller may very likely lead 1131 // to its destruction, so no calls after that. 1132 xCC->removeConfigurationChangeListener(this); 1133 } 1134 } 1135 } 1136 1137 1138 1139 1140 //----- LifetimeController ------------------------------------------------- 1141 1142 LifetimeController::LifetimeController (::sd::ViewShellBase& rBase) 1143 : LifetimeControllerInterfaceBase(maMutex), 1144 mrBase(rBase), 1145 mbListeningToViewShellBase(false), 1146 mbListeningToController(false) 1147 { 1148 // Register as listener at the ViewShellBase. Because that is not done 1149 // via a reference we have to increase the reference count manually. 1150 // This is necessary even though listening to the XController did 1151 // increase the reference count because the controller may release its 1152 // reference to us before the ViewShellBase is destroyed. 1153 StartListening(mrBase); 1154 acquire(); 1155 mbListeningToViewShellBase = true; 1156 1157 Reference<XComponent> xComponent (rBase.GetController(), UNO_QUERY); 1158 if (xComponent.is()) 1159 { 1160 xComponent->addEventListener(this); 1161 mbListeningToController = true; 1162 } 1163 } 1164 1165 1166 1167 1168 LifetimeController::~LifetimeController (void) 1169 { 1170 OSL_ASSERT(!mbListeningToController && !mbListeningToViewShellBase); 1171 } 1172 1173 1174 1175 1176 void LifetimeController::disposing (void) 1177 { 1178 } 1179 1180 1181 1182 1183 void SAL_CALL LifetimeController::disposing (const lang::EventObject& rEvent) 1184 throw(RuntimeException) 1185 { 1186 (void)rEvent; 1187 mbListeningToController = false; 1188 Update(); 1189 } 1190 1191 1192 1193 1194 void LifetimeController::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint) 1195 { 1196 (void)rBroadcaster; 1197 const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint); 1198 if (pSimpleHint != NULL && pSimpleHint->GetId() == SFX_HINT_DYING) 1199 { 1200 mbListeningToViewShellBase = false; 1201 Update(); 1202 release(); 1203 } 1204 } 1205 1206 1207 1208 1209 void LifetimeController::Update (void) 1210 { 1211 if (mbListeningToViewShellBase && mbListeningToController) 1212 { 1213 // Both the controller and the ViewShellBase are alive. Keep 1214 // waiting for their destruction. 1215 } 1216 else if (mbListeningToViewShellBase) 1217 { 1218 // The controller has been destroyed but the ViewShellBase is still 1219 // alive. Dispose the associated FrameworkHelper but keep it around 1220 // so that no new instance is created for the dying framework. 1221 ::sd::framework::FrameworkHelper::DisposeInstance(mrBase); 1222 } 1223 else 1224 { 1225 // Both the controller and the ViewShellBase have been destroyed. 1226 // Remove the FrameworkHelper so that the next call its Instance() 1227 // method can create a new instance. 1228 ::sd::framework::FrameworkHelper::ReleaseInstance(mrBase); 1229 } 1230 } 1231 1232 1233 1234 } // end of anonymous namespace. 1235