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 maInstanceMap[&rBase] = pHelper; 388 } 389 } 390 else 391 { 392 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); 393 pHelper = iHelper->second; 394 } 395 396 return pHelper; 397 } 398 399 400 401 402 void FrameworkHelper::DisposeInstance (ViewShellBase& rBase) 403 { 404 InstanceMap::iterator iHelper (maInstanceMap.find(&rBase)); 405 if (iHelper != maInstanceMap.end()) 406 { 407 iHelper->second->Dispose(); 408 } 409 } 410 411 412 413 414 void FrameworkHelper::ReleaseInstance (ViewShellBase& rBase) 415 { 416 InstanceMap::iterator iHelper (maInstanceMap.find(&rBase)); 417 if (iHelper != maInstanceMap.end()) 418 maInstanceMap.erase(iHelper); 419 } 420 421 422 423 424 FrameworkHelper::FrameworkHelper (ViewShellBase& rBase) 425 : mrBase(rBase), 426 mxConfigurationController(), 427 mxDisposeListener() 428 429 { 430 Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY); 431 if (xControllerManager.is()) 432 { 433 mxConfigurationController = xControllerManager->getConfigurationController(); 434 } 435 436 new LifetimeController(mrBase); 437 } 438 439 440 441 442 void FrameworkHelper::Initialize (void) 443 { 444 mxDisposeListener = new DisposeListener(shared_from_this()); 445 } 446 447 448 449 450 FrameworkHelper::~FrameworkHelper (void) 451 { 452 } 453 454 455 456 457 void FrameworkHelper::Dispose (void) 458 { 459 if (mxDisposeListener.is()) 460 mxDisposeListener->dispose(); 461 mxConfigurationController = NULL; 462 } 463 464 465 466 467 bool FrameworkHelper::IsValid (void) 468 { 469 return mxConfigurationController.is(); 470 } 471 472 473 474 475 ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const OUString& rsPaneURL) 476 { 477 if ( !mxConfigurationController.is() ) 478 return ::boost::shared_ptr<ViewShell>(); 479 480 Reference<XResourceId> xPaneId( CreateResourceId( rsPaneURL ) ); 481 return lcl_getViewShell( lcl_getFirstViewInPane( mxConfigurationController, xPaneId ) ); 482 } 483 484 485 486 487 ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const Reference<XView>& rxView) 488 { 489 return lcl_getViewShell( rxView.get() ); 490 } 491 492 493 494 495 Reference<XView> FrameworkHelper::GetView (const Reference<XResourceId>& rxPaneOrViewId) 496 { 497 Reference<XView> xView; 498 499 if ( ! rxPaneOrViewId.is() || ! mxConfigurationController.is()) 500 return NULL; 501 502 try 503 { 504 if (rxPaneOrViewId->getResourceURL().match(msViewURLPrefix)) 505 { 506 xView.set( mxConfigurationController->getResource( rxPaneOrViewId ), UNO_QUERY ); 507 } 508 else 509 { 510 xView.set( lcl_getFirstViewInPane( mxConfigurationController, rxPaneOrViewId ), UNO_QUERY ); 511 } 512 } 513 catch (lang::DisposedException&) 514 { 515 Dispose(); 516 } 517 catch (RuntimeException&) 518 { 519 } 520 521 return xView; 522 } 523 524 525 526 527 Reference<XResourceId> FrameworkHelper::RequestView ( 528 const OUString& rsResourceURL, 529 const OUString& rsAnchorURL) 530 { 531 Reference<XResourceId> xViewId; 532 533 try 534 { 535 if (mxConfigurationController.is()) 536 { 537 mxConfigurationController->requestResourceActivation( 538 CreateResourceId(rsAnchorURL), 539 ResourceActivationMode_ADD); 540 xViewId = CreateResourceId(rsResourceURL, rsAnchorURL); 541 mxConfigurationController->requestResourceActivation( 542 xViewId, 543 ResourceActivationMode_REPLACE); 544 } 545 } 546 catch (lang::DisposedException&) 547 { 548 Dispose(); 549 xViewId = NULL; 550 } 551 catch (RuntimeException&) 552 { 553 xViewId = NULL; 554 } 555 556 return xViewId; 557 } 558 559 560 561 562 void FrameworkHelper::RequestTaskPanel ( 563 const OUString& rsTaskPanelURL, 564 const bool bEnsureTaskPaneIsVisible) 565 { 566 try 567 { 568 if (mxConfigurationController.is()) 569 { 570 // Check the existence of the task pane. 571 if ( ! bEnsureTaskPaneIsVisible) 572 { 573 Reference<XConfiguration> xConfiguration ( 574 mxConfigurationController->getCurrentConfiguration()); 575 if (xConfiguration.is()) 576 if ( ! xConfiguration->hasResource( 577 CreateResourceId(msTaskPaneURL, msRightPaneURL))) 578 { 579 // Task pane does is not active. Do not force it. 580 return; 581 } 582 } 583 584 // Create the resource id from URLs for the pane, the task pane 585 // view, and the task panel. 586 mxConfigurationController->requestResourceActivation( 587 CreateResourceId(msRightPaneURL), 588 ResourceActivationMode_ADD); 589 mxConfigurationController->requestResourceActivation( 590 CreateResourceId(msTaskPaneURL, msRightPaneURL), 591 ResourceActivationMode_REPLACE); 592 mxConfigurationController->requestResourceActivation( 593 CreateResourceId(rsTaskPanelURL, msTaskPaneURL, msRightPaneURL), 594 ResourceActivationMode_REPLACE); 595 } 596 } 597 catch (lang::DisposedException&) 598 { 599 Dispose(); 600 } 601 catch (RuntimeException&) 602 {} 603 } 604 605 606 607 608 ViewShell::ShellType FrameworkHelper::GetViewId (const rtl::OUString& rsViewURL) 609 { 610 if (mpViewURLMap->empty()) 611 { 612 (*mpViewURLMap)[msImpressViewURL] = ViewShell::ST_IMPRESS; 613 (*mpViewURLMap)[msDrawViewURL] = ViewShell::ST_DRAW; 614 (*mpViewURLMap)[msOutlineViewURL] = ViewShell::ST_OUTLINE; 615 (*mpViewURLMap)[msNotesViewURL] = ViewShell::ST_NOTES; 616 (*mpViewURLMap)[msHandoutViewURL] = ViewShell::ST_HANDOUT; 617 (*mpViewURLMap)[msSlideSorterURL] = ViewShell::ST_SLIDE_SORTER; 618 (*mpViewURLMap)[msPresentationViewURL] = ViewShell::ST_PRESENTATION; 619 (*mpViewURLMap)[msTaskPaneURL] = ViewShell::ST_TASK_PANE; 620 } 621 ViewURLMap::const_iterator iView (mpViewURLMap->find(rsViewURL)); 622 if (iView != mpViewURLMap->end()) 623 return iView->second; 624 else 625 return ViewShell::ST_NONE; 626 } 627 628 629 630 631 ::rtl::OUString FrameworkHelper::GetViewURL (ViewShell::ShellType eType) 632 { 633 switch (eType) 634 { 635 case ViewShell::ST_IMPRESS : return msImpressViewURL; 636 case ViewShell::ST_DRAW : return msDrawViewURL; 637 case ViewShell::ST_OUTLINE : return msOutlineViewURL; 638 case ViewShell::ST_NOTES : return msNotesViewURL; 639 case ViewShell::ST_HANDOUT : return msHandoutViewURL; 640 case ViewShell::ST_SLIDE_SORTER : return msSlideSorterURL; 641 case ViewShell::ST_PRESENTATION : return msPresentationViewURL; 642 case ViewShell::ST_TASK_PANE : return msTaskPaneURL; 643 default: 644 return OUString(); 645 } 646 } 647 648 649 650 651 void FrameworkHelper::HandleModeChangeSlot ( 652 sal_uLong nSlotId, 653 SfxRequest& rRequest) 654 { 655 sal_Bool bIsActive = sal_True; 656 657 if ( ! mxConfigurationController.is()) 658 return; 659 660 switch (nSlotId) 661 { 662 case SID_DRAWINGMODE: 663 case SID_NOTESMODE: 664 case SID_HANDOUTMODE: 665 case SID_DIAMODE: 666 case SID_OUTLINEMODE: 667 { 668 const SfxItemSet* pRequestArguments = rRequest.GetArgs(); 669 if (pRequestArguments) 670 { 671 SFX_REQUEST_ARG (rRequest, 672 pIsActive, 673 SfxBoolItem, 674 (sal_uInt16)nSlotId, 675 sal_False); 676 bIsActive = pIsActive->GetValue (); 677 } 678 } 679 break; 680 } 681 682 try 683 { 684 if ( ! mxConfigurationController.is()) 685 throw RuntimeException(); 686 687 688 Reference<XResourceId> xPaneId ( 689 CreateResourceId(framework::FrameworkHelper::msCenterPaneURL)); 690 Reference<XView> xView (GetView(xPaneId)); 691 ::boost::shared_ptr<ViewShell> pCenterViewShell (GetViewShell(xView)); 692 693 ::rtl::OUString sRequestedView; 694 if (bIsActive) 695 { 696 switch (nSlotId) 697 { 698 case SID_NORMAL_MULTI_PANE_GUI: 699 case SID_DRAWINGMODE: 700 sRequestedView = FrameworkHelper::msImpressViewURL; 701 break; 702 703 case SID_NOTESMODE: 704 sRequestedView = FrameworkHelper::msNotesViewURL; 705 break; 706 707 case SID_HANDOUTMODE: 708 sRequestedView = FrameworkHelper::msHandoutViewURL; 709 break; 710 711 case SID_SLIDE_SORTER_MULTI_PANE_GUI: 712 case SID_DIAMODE: 713 sRequestedView = FrameworkHelper::msSlideSorterURL; 714 break; 715 716 case SID_OUTLINEMODE: 717 sRequestedView = FrameworkHelper::msOutlineViewURL; 718 break; 719 } 720 } 721 722 if (xView.is() 723 && xView->getResourceId()->getResourceURL().equals(sRequestedView)) 724 { 725 // We do not have to switch the view shell but maybe the edit mode 726 // has changed. 727 DrawViewShell* pDrawViewShell 728 = dynamic_cast<DrawViewShell*>(pCenterViewShell.get()); 729 if (pDrawViewShell != NULL) 730 { 731 pCenterViewShell->Broadcast ( 732 ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_START)); 733 734 pDrawViewShell->ChangeEditMode ( 735 EM_PAGE, pDrawViewShell->IsLayerModeActive()); 736 737 pCenterViewShell->Broadcast ( 738 ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_END)); 739 } 740 } 741 else 742 { 743 mxConfigurationController->requestResourceActivation( 744 CreateResourceId(sRequestedView, msCenterPaneURL), 745 ResourceActivationMode_REPLACE); 746 } 747 } 748 catch (RuntimeException&) 749 { 750 DBG_UNHANDLED_EXCEPTION(); 751 } 752 } 753 754 755 756 757 void FrameworkHelper::RunOnConfigurationEvent( 758 const ::rtl::OUString& rsEventType, 759 const Callback& rCallback) 760 { 761 RunOnEvent( 762 rsEventType, 763 FrameworkHelperAllPassFilter(), 764 rCallback); 765 } 766 767 768 769 770 void FrameworkHelper::RunOnResourceActivation( 771 const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId, 772 const Callback& rCallback) 773 { 774 if (mxConfigurationController.is() 775 && mxConfigurationController->getResource(rxResourceId).is()) 776 { 777 rCallback(false); 778 } 779 else 780 { 781 RunOnEvent( 782 msResourceActivationEvent, 783 FrameworkHelperResourceIdFilter(rxResourceId), 784 rCallback); 785 } 786 } 787 788 789 790 791 /** A callback that sets a flag to a specified value when the callback is 792 called. 793 */ 794 class FlagUpdater 795 { 796 public: 797 FlagUpdater (bool& rFlag) : mrFlag(rFlag) {} 798 void operator() (bool) {mrFlag = true;} 799 private: 800 bool& mrFlag; 801 }; 802 803 804 805 806 void FrameworkHelper::RequestSynchronousUpdate (void) 807 { 808 rtl::Reference<ConfigurationController> pCC ( 809 dynamic_cast<ConfigurationController*>(mxConfigurationController.get())); 810 if (pCC.is()) 811 pCC->RequestSynchronousUpdate(); 812 } 813 814 815 816 817 void FrameworkHelper::WaitForEvent (const OUString& rsEventType) const 818 { 819 bool bConfigurationUpdateSeen (false); 820 821 RunOnEvent( 822 rsEventType, 823 FrameworkHelperAllPassFilter(), 824 FlagUpdater(bConfigurationUpdateSeen)); 825 826 sal_uInt32 nStartTime = osl_getGlobalTimer(); 827 while ( ! bConfigurationUpdateSeen) 828 { 829 Application::Reschedule(); 830 831 if( (osl_getGlobalTimer() - nStartTime) > 60000 ) 832 { 833 DBG_ERROR("FrameworkHelper::WaitForEvent(), no event for a minute? giving up!"); 834 break; 835 } 836 } 837 } 838 839 840 841 842 void FrameworkHelper::WaitForUpdate (void) const 843 { 844 WaitForEvent(msConfigurationUpdateEndEvent); 845 } 846 847 848 849 850 void FrameworkHelper::RunOnEvent( 851 const ::rtl::OUString& rsEventType, 852 const ConfigurationChangeEventFilter& rFilter, 853 const Callback& rCallback) const 854 { 855 new CallbackCaller(mrBase,rsEventType,rFilter,rCallback); 856 } 857 858 859 860 861 void FrameworkHelper::disposing (const lang::EventObject& rEventObject) 862 { 863 if (rEventObject.Source == mxConfigurationController) 864 mxConfigurationController = NULL; 865 } 866 867 868 869 870 void FrameworkHelper::UpdateConfiguration (void) 871 { 872 if (mxConfigurationController.is()) 873 { 874 try 875 { 876 if (mxConfigurationController.is()) 877 mxConfigurationController->update(); 878 } 879 catch (lang::DisposedException&) 880 { 881 Dispose(); 882 } 883 catch (RuntimeException&) 884 { 885 DBG_UNHANDLED_EXCEPTION(); 886 } 887 } 888 } 889 890 891 892 893 OUString FrameworkHelper::ResourceIdToString (const Reference<XResourceId>& rxResourceId) 894 { 895 OUString sString; 896 if (rxResourceId.is()) 897 { 898 sString += rxResourceId->getResourceURL(); 899 if (rxResourceId->hasAnchor()) 900 { 901 Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs()); 902 for (sal_Int32 nIndex=0; nIndex<aAnchorURLs.getLength(); ++nIndex) 903 { 904 sString += OUString::createFromAscii(" | "); 905 sString += aAnchorURLs[nIndex]; 906 } 907 } 908 } 909 return sString; 910 } 911 912 913 914 915 Reference<XResourceId> FrameworkHelper::CreateResourceId (const ::rtl::OUString& rsResourceURL) 916 { 917 return new ::sd::framework::ResourceId(rsResourceURL); 918 } 919 920 921 922 923 Reference<XResourceId> FrameworkHelper::CreateResourceId ( 924 const OUString& rsResourceURL, 925 const OUString& rsAnchorURL) 926 { 927 return new ::sd::framework::ResourceId(rsResourceURL, rsAnchorURL); 928 } 929 930 931 932 933 Reference<XResourceId> FrameworkHelper::CreateResourceId ( 934 const OUString& rsResourceURL, 935 const OUString& rsFirstAnchorURL, 936 const OUString& rsSecondAnchorURL) 937 { 938 ::std::vector<OUString> aAnchorURLs (2); 939 aAnchorURLs[0] = rsFirstAnchorURL; 940 aAnchorURLs[1] = rsSecondAnchorURL; 941 return new ::sd::framework::ResourceId(rsResourceURL, aAnchorURLs); 942 } 943 944 945 946 947 Reference<XResourceId> FrameworkHelper::CreateResourceId ( 948 const ::rtl::OUString& rsResourceURL, 949 const Reference<XResourceId>& rxAnchorId) 950 { 951 if (rxAnchorId.is()) 952 return new ::sd::framework::ResourceId( 953 rsResourceURL, 954 rxAnchorId->getResourceURL(), 955 rxAnchorId->getAnchorURLs()); 956 else 957 return new ::sd::framework::ResourceId(rsResourceURL); 958 } 959 960 961 962 963 Reference<XConfigurationController> FrameworkHelper::GetConfigurationController (void) const 964 { 965 return mxConfigurationController; 966 } 967 968 969 970 971 //----- FrameworkHelper::DisposeListener -------------------------------------- 972 973 FrameworkHelper::DisposeListener::DisposeListener ( 974 const ::boost::shared_ptr<FrameworkHelper>& rpHelper) 975 : FrameworkHelperDisposeListenerInterfaceBase(maMutex), 976 mpHelper(rpHelper) 977 { 978 Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY); 979 if (xComponent.is()) 980 xComponent->addEventListener(this); 981 } 982 983 984 985 986 FrameworkHelper::DisposeListener::~DisposeListener (void) 987 { 988 } 989 990 991 992 993 void SAL_CALL FrameworkHelper::DisposeListener::disposing (void) 994 { 995 Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY); 996 if (xComponent.is()) 997 xComponent->removeEventListener(this); 998 999 mpHelper.reset(); 1000 } 1001 1002 1003 1004 1005 void SAL_CALL FrameworkHelper::DisposeListener::disposing (const lang::EventObject& rEventObject) 1006 throw(RuntimeException) 1007 { 1008 if (mpHelper.get() != NULL) 1009 mpHelper->disposing(rEventObject); 1010 } 1011 1012 1013 1014 1015 //===== FrameworkHelperResourceIdFilter ======================================= 1016 1017 FrameworkHelperResourceIdFilter::FrameworkHelperResourceIdFilter ( 1018 const Reference<XResourceId>& rxResourceId) 1019 : mxResourceId(rxResourceId) 1020 { 1021 } 1022 1023 1024 } } // end of namespace sd::framework 1025 1026 namespace { 1027 1028 //===== CallbackCaller ======================================================== 1029 1030 CallbackCaller::CallbackCaller ( 1031 ::sd::ViewShellBase& rBase, 1032 const OUString& rsEventType, 1033 const ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter& rFilter, 1034 const ::sd::framework::FrameworkHelper::Callback& rCallback) 1035 : CallbackCallerInterfaceBase(MutexOwner::maMutex), 1036 msEventType(rsEventType), 1037 mxConfigurationController(), 1038 maFilter(rFilter), 1039 maCallback(rCallback) 1040 { 1041 try 1042 { 1043 Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY_THROW); 1044 mxConfigurationController = xControllerManager->getConfigurationController(); 1045 if (mxConfigurationController.is()) 1046 { 1047 if (mxConfigurationController->hasPendingRequests()) 1048 mxConfigurationController->addConfigurationChangeListener(this,msEventType,Any()); 1049 else 1050 { 1051 // There are no requests waiting to be processed. Therefore 1052 // no event, especially not the one we are waiting for, will 1053 // be sent in the near future and the callback would never be 1054 // called. 1055 // Call the callback now and tell him that the event it is 1056 // waiting for was not sent. 1057 mxConfigurationController = NULL; 1058 maCallback(false); 1059 } 1060 } 1061 } 1062 catch (RuntimeException&) 1063 { 1064 DBG_UNHANDLED_EXCEPTION(); 1065 } 1066 } 1067 1068 1069 1070 1071 CallbackCaller::~CallbackCaller (void) 1072 { 1073 } 1074 1075 1076 1077 1078 void CallbackCaller::disposing (void) 1079 { 1080 try 1081 { 1082 if (mxConfigurationController.is()) 1083 { 1084 Reference<XConfigurationController> xCC (mxConfigurationController); 1085 mxConfigurationController = NULL; 1086 xCC->removeConfigurationChangeListener(this); 1087 } 1088 } 1089 catch (RuntimeException&) 1090 { 1091 DBG_UNHANDLED_EXCEPTION(); 1092 } 1093 } 1094 1095 1096 1097 1098 void SAL_CALL CallbackCaller::disposing (const lang::EventObject& rEvent) 1099 throw (RuntimeException) 1100 { 1101 if (rEvent.Source == mxConfigurationController) 1102 { 1103 mxConfigurationController = NULL; 1104 maCallback(false); 1105 } 1106 } 1107 1108 1109 1110 1111 void SAL_CALL CallbackCaller::notifyConfigurationChange ( 1112 const ConfigurationChangeEvent& rEvent) 1113 throw (RuntimeException) 1114 { 1115 if (rEvent.Type.equals(msEventType) && maFilter(rEvent)) 1116 { 1117 maCallback(true); 1118 if (mxConfigurationController.is()) 1119 { 1120 // Reset the reference to the configuration controller so that 1121 // dispose() will not try to remove the listener a second time. 1122 Reference<XConfigurationController> xCC (mxConfigurationController); 1123 mxConfigurationController = NULL; 1124 1125 // Removing this object from the controller may very likely lead 1126 // to its destruction, so no calls after that. 1127 xCC->removeConfigurationChangeListener(this); 1128 } 1129 } 1130 } 1131 1132 1133 1134 1135 //----- LifetimeController ------------------------------------------------- 1136 1137 LifetimeController::LifetimeController (::sd::ViewShellBase& rBase) 1138 : LifetimeControllerInterfaceBase(maMutex), 1139 mrBase(rBase), 1140 mbListeningToViewShellBase(false), 1141 mbListeningToController(false) 1142 { 1143 // Register as listener at the ViewShellBase. Because that is not done 1144 // via a reference we have to increase the reference count manually. 1145 // This is necessary even though listening to the XController did 1146 // increase the reference count because the controller may release its 1147 // reference to us before the ViewShellBase is destroyed. 1148 StartListening(mrBase); 1149 acquire(); 1150 mbListeningToViewShellBase = true; 1151 1152 Reference<XComponent> xComponent (rBase.GetController(), UNO_QUERY); 1153 if (xComponent.is()) 1154 { 1155 xComponent->addEventListener(this); 1156 mbListeningToController = true; 1157 } 1158 } 1159 1160 1161 1162 1163 LifetimeController::~LifetimeController (void) 1164 { 1165 OSL_ASSERT(!mbListeningToController && !mbListeningToViewShellBase); 1166 } 1167 1168 1169 1170 1171 void LifetimeController::disposing (void) 1172 { 1173 } 1174 1175 1176 1177 1178 void SAL_CALL LifetimeController::disposing (const lang::EventObject& rEvent) 1179 throw(RuntimeException) 1180 { 1181 (void)rEvent; 1182 mbListeningToController = false; 1183 Update(); 1184 } 1185 1186 1187 1188 1189 void LifetimeController::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint) 1190 { 1191 (void)rBroadcaster; 1192 const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint); 1193 if (pSimpleHint != NULL && pSimpleHint->GetId() == SFX_HINT_DYING) 1194 { 1195 mbListeningToViewShellBase = false; 1196 Update(); 1197 release(); 1198 } 1199 } 1200 1201 1202 1203 1204 void LifetimeController::Update (void) 1205 { 1206 if (mbListeningToViewShellBase && mbListeningToController) 1207 { 1208 // Both the controller and the ViewShellBase are alive. Keep 1209 // waiting for their destruction. 1210 } 1211 else if (mbListeningToViewShellBase) 1212 { 1213 // The controller has been destroyed but the ViewShellBase is still 1214 // alive. Dispose the associated FrameworkHelper but keep it around 1215 // so that no new instance is created for the dying framework. 1216 ::sd::framework::FrameworkHelper::DisposeInstance(mrBase); 1217 } 1218 else 1219 { 1220 // Both the controller and the ViewShellBase have been destroyed. 1221 // Remove the FrameworkHelper so that the next call its Instance() 1222 // method can create a new instance. 1223 ::sd::framework::FrameworkHelper::ReleaseInstance(mrBase); 1224 } 1225 } 1226 1227 1228 1229 } // end of anonymous namespace. 1230