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