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