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