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 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sdext.hxx" 26 27 #include "PresenterController.hxx" 28 29 #include "PresenterAccessibility.hxx" 30 #include "PresenterAnimator.hxx" 31 #include "PresenterCanvasHelper.hxx" 32 #include "PresenterCurrentSlideObserver.hxx" 33 #include "PresenterFrameworkObserver.hxx" 34 #include "PresenterHelper.hxx" 35 #include "PresenterNotesView.hxx" 36 #include "PresenterPaintManager.hxx" 37 #include "PresenterPaneAnimator.hxx" 38 #include "PresenterPaneBase.hxx" 39 #include "PresenterPaneContainer.hxx" 40 #include "PresenterPaneBorderPainter.hxx" 41 #include "PresenterTheme.hxx" 42 #include "PresenterViewFactory.hxx" 43 #include "PresenterWindowManager.hxx" 44 45 #include <com/sun/star/accessibility/AccessibleRole.hpp> 46 #include <com/sun/star/accessibility/XAccessible.hpp> 47 #include <com/sun/star/awt/Key.hpp> 48 #include <com/sun/star/awt/KeyModifier.hpp> 49 #include <com/sun/star/awt/MouseButton.hpp> 50 #include <com/sun/star/awt/XWindowPeer.hpp> 51 #include <com/sun/star/container/XNamed.hpp> 52 #include <com/sun/star/drawing/XDrawView.hpp> 53 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp> 54 #include <com/sun/star/drawing/framework/ResourceActivationMode.hpp> 55 #include <com/sun/star/drawing/framework/ResourceId.hpp> 56 #include <com/sun/star/drawing/framework/XControllerManager.hpp> 57 #include <com/sun/star/frame/FrameSearchFlag.hpp> 58 #include <com/sun/star/frame/XDispatchProvider.hpp> 59 #include <com/sun/star/presentation/XPresentation.hpp> 60 #include <com/sun/star/presentation/XPresentationSupplier.hpp> 61 #include <com/sun/star/rendering/CompositeOperation.hpp> 62 #include <com/sun/star/rendering/TextDirection.hpp> 63 64 #include <rtl/ustrbuf.hxx> 65 #include <boost/bind.hpp> 66 67 using namespace ::com::sun::star; 68 using namespace ::com::sun::star::uno; 69 using namespace ::com::sun::star::presentation; 70 using namespace ::com::sun::star::drawing::framework; 71 using ::rtl::OUString; 72 using ::rtl::OUStringBuffer; 73 74 namespace { 75 const sal_Int32 ResourceActivationEventType = 0; 76 const sal_Int32 ResourceDeactivationEventType = 1; 77 const sal_Int32 ConfigurationUpdateEndEventType = 2; 78 } 79 80 81 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) 82 83 84 namespace sdext { namespace presenter { 85 86 PresenterController::InstanceContainer PresenterController::maInstances; 87 88 ::rtl::Reference<PresenterController> PresenterController::Instance ( 89 const css::uno::Reference<css::frame::XFrame>& rxFrame) 90 { 91 InstanceContainer::const_iterator iInstance (maInstances.find(rxFrame)); 92 if (iInstance != maInstances.end()) 93 return iInstance->second; 94 else 95 return ::rtl::Reference<PresenterController>(); 96 } 97 98 99 100 101 PresenterController::PresenterController ( 102 const Reference<XComponentContext>& rxContext, 103 const Reference<frame::XController>& rxController, 104 const Reference<presentation::XSlideShowController>& rxSlideShowController, 105 const rtl::Reference<PresenterPaneContainer>& rpPaneContainer, 106 const Reference<XResourceId>& rxMainPaneId) 107 : PresenterControllerInterfaceBase(m_aMutex), 108 mxComponentContext(rxContext), 109 mxController(rxController), 110 mxConfigurationController(), 111 mxSlideShowController(rxSlideShowController), 112 mxMainPaneId(rxMainPaneId), 113 mpPaneContainer(rpPaneContainer), 114 mnCurrentSlideIndex(-1), 115 mxCurrentSlide(), 116 mxNextSlide(), 117 mpWindowManager(new PresenterWindowManager(rxContext,mpPaneContainer,this)), 118 mpCurrentPaneAnimation(), 119 mnWindowBackgroundColor(0x00ffffff), 120 mpTheme(), 121 mxMainWindow(), 122 mpPaneBorderPainter(), 123 mpAnimator(new PresenterAnimator()), 124 mpCanvasHelper(new PresenterCanvasHelper()), 125 mxPresenterHelper(), 126 mpPaintManager(), 127 mnPendingSlideNumber(-1), 128 mxUrlTransformer(), 129 mpAccessibleObject(), 130 mbIsAccessibilityActive(false) 131 { 132 OSL_ASSERT(mxController.is()); 133 134 if ( ! mxSlideShowController.is()) 135 throw new lang::IllegalArgumentException( 136 A2S("missing slide show controller"), 137 static_cast<XWeak*>(this), 138 2); 139 140 new PresenterCurrentSlideObserver(this,rxSlideShowController); 141 142 // Listen for configuration changes. 143 Reference<XControllerManager> xCM (mxController, UNO_QUERY_THROW); 144 mxConfigurationController = xCM->getConfigurationController(); 145 if (mxConfigurationController.is()) 146 { 147 mxConfigurationController->addConfigurationChangeListener( 148 this, 149 A2S("ResourceActivation"), 150 Any(ResourceActivationEventType)); 151 mxConfigurationController->addConfigurationChangeListener( 152 this, 153 A2S("ResourceDeactivation"), 154 Any(ResourceDeactivationEventType)); 155 mxConfigurationController->addConfigurationChangeListener( 156 this, 157 A2S("ConfigurationUpdateEnd"), 158 Any(ConfigurationUpdateEndEventType)); 159 } 160 161 // Listen for the frame being activated. 162 Reference<frame::XFrame> xFrame (mxController->getFrame()); 163 if (xFrame.is()) 164 xFrame->addFrameActionListener(this); 165 166 // Create the border painter. 167 mpPaneBorderPainter = new PresenterPaneBorderPainter(rxContext); 168 mpWindowManager->SetPaneBorderPainter(mpPaneBorderPainter); 169 170 // Create an object that is able to load the bitmaps in a format that is 171 // supported by the canvas. 172 Reference<lang::XMultiComponentFactory> xFactory ( 173 rxContext->getServiceManager(), UNO_QUERY); 174 if ( ! xFactory.is()) 175 return; 176 mxPresenterHelper = Reference<drawing::XPresenterHelper>( 177 xFactory->createInstanceWithContext( 178 A2S("com.sun.star.drawing.PresenterHelper"), 179 rxContext), 180 UNO_QUERY_THROW); 181 182 if (mxSlideShowController.is()) 183 { 184 mxSlideShowController->activate(); 185 Reference<beans::XPropertySet> xProperties (mxSlideShowController, UNO_QUERY); 186 if (xProperties.is()) 187 { 188 Reference<awt::XWindow> xWindow ( 189 xProperties->getPropertyValue(A2S("ParentWindow")), UNO_QUERY); 190 if (xWindow.is()) 191 xWindow->addKeyListener(this); 192 } 193 } 194 195 UpdateCurrentSlide(0); 196 197 maInstances[mxController->getFrame()] = this; 198 199 // Create a URLTransformer. 200 if (xFactory.is()) 201 { 202 mxUrlTransformer = Reference<util::XURLTransformer>( 203 xFactory->createInstanceWithContext( 204 A2S("com.sun.star.util.URLTransformer"), 205 mxComponentContext), 206 UNO_QUERY); 207 } 208 } 209 210 211 212 213 PresenterController::~PresenterController (void) 214 { 215 } 216 217 218 219 220 void PresenterController::disposing (void) 221 { 222 maInstances.erase(mxController->getFrame()); 223 224 if (mxMainWindow.is()) 225 { 226 mxMainWindow->removeKeyListener(this); 227 mxMainWindow->removeFocusListener(this); 228 mxMainWindow->removeMouseListener(this); 229 mxMainWindow->removeMouseMotionListener(this); 230 mxMainWindow = NULL; 231 } 232 if (mxConfigurationController.is()) 233 mxConfigurationController->removeConfigurationChangeListener(this); 234 235 Reference<XComponent> xWindowManagerComponent ( 236 static_cast<XWeak*>(mpWindowManager.get()), UNO_QUERY); 237 mpWindowManager = NULL; 238 if (xWindowManagerComponent.is()) 239 xWindowManagerComponent->dispose(); 240 241 if (mxController.is()) 242 { 243 Reference<frame::XFrame> xFrame (mxController->getFrame()); 244 if (xFrame.is()) 245 xFrame->removeFrameActionListener(this); 246 mxController = NULL; 247 } 248 249 mxComponentContext = NULL; 250 mxConfigurationController = NULL; 251 mxSlideShowController = NULL; 252 mxMainPaneId = NULL; 253 mpPaneContainer = NULL; 254 mnCurrentSlideIndex = -1; 255 mxCurrentSlide = NULL; 256 mxNextSlide = NULL; 257 mpCurrentPaneAnimation.reset(); 258 mpTheme.reset(); 259 { 260 Reference<lang::XComponent> xComponent ( 261 static_cast<XWeak*>(mpPaneBorderPainter.get()), UNO_QUERY); 262 mpPaneBorderPainter = NULL; 263 if (xComponent.is()) 264 xComponent->dispose(); 265 } 266 mpAnimator.reset(); 267 mpCanvasHelper.reset(); 268 { 269 Reference<lang::XComponent> xComponent (mxPresenterHelper, UNO_QUERY); 270 mxPresenterHelper = NULL; 271 if (xComponent.is()) 272 xComponent->dispose(); 273 } 274 mpPaintManager.reset(); 275 mnPendingSlideNumber = -1; 276 { 277 Reference<lang::XComponent> xComponent (mxUrlTransformer, UNO_QUERY); 278 mxUrlTransformer = NULL; 279 if (xComponent.is()) 280 xComponent->dispose(); 281 } 282 } 283 284 285 286 287 void PresenterController::UpdateCurrentSlide (const sal_Int32 nOffset) 288 { 289 GetSlides(nOffset); 290 UpdatePaneTitles(); 291 UpdateViews(); 292 293 // Update the accessibility object. 294 if (IsAccessibilityActive()) 295 { 296 sal_Int32 nSlideCount (0); 297 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY); 298 if (xIndexAccess.is()) 299 nSlideCount = xIndexAccess->getCount(); 300 mpAccessibleObject->NotifyCurrentSlideChange(mnCurrentSlideIndex, nSlideCount); 301 } 302 } 303 304 305 306 307 void PresenterController::GetSlides (const sal_Int32 nOffset) 308 { 309 if ( ! mxSlideShowController.is()) 310 return; 311 312 // Get the current slide from the slide show controller. 313 mxCurrentSlide = NULL; 314 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY); 315 sal_Int32 nSlideIndex = -1; 316 try 317 { 318 nSlideIndex = mxSlideShowController->getCurrentSlideIndex() + nOffset; 319 if (mxSlideShowController->isPaused()) 320 nSlideIndex = -1; 321 322 if (xIndexAccess.is() && nSlideIndex>=0) 323 { 324 if (nSlideIndex < xIndexAccess->getCount()) 325 { 326 mnCurrentSlideIndex = nSlideIndex; 327 mxCurrentSlide = Reference<drawing::XDrawPage>( 328 xIndexAccess->getByIndex(nSlideIndex), UNO_QUERY); 329 } 330 } 331 } 332 catch (RuntimeException&) 333 { 334 } 335 336 // Get the next slide. 337 mxNextSlide = NULL; 338 try 339 { 340 const sal_Int32 nNextSlideIndex (mxSlideShowController->getNextSlideIndex()+nOffset); 341 if (nNextSlideIndex >= 0) 342 { 343 if (xIndexAccess.is()) 344 { 345 if (nNextSlideIndex < xIndexAccess->getCount()) 346 mxNextSlide = Reference<drawing::XDrawPage>( 347 xIndexAccess->getByIndex(nNextSlideIndex), UNO_QUERY); 348 } 349 } 350 } 351 catch (RuntimeException&) 352 { 353 } 354 } 355 356 357 358 359 void PresenterController::UpdatePaneTitles (void) 360 { 361 if ( ! mxSlideShowController.is()) 362 return; 363 364 // Get placeholders and their values. 365 const OUString sCurrentSlideNumberPlaceholder (A2S("CURRENT_SLIDE_NUMBER")); 366 const OUString sCurrentSlideNamePlaceholder (A2S("CURRENT_SLIDE_NAME")); 367 const OUString sSlideCountPlaceholder (A2S("SLIDE_COUNT")); 368 369 // Get string for slide count. 370 OUString sSlideCount (A2S("---")); 371 Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY); 372 if (xIndexAccess.is()) 373 sSlideCount = OUString::valueOf(xIndexAccess->getCount()); 374 375 // Get string for current slide index. 376 OUString sCurrentSlideNumber (OUString::valueOf(mnCurrentSlideIndex + 1)); 377 378 // Get name of the current slide. 379 OUString sCurrentSlideName; 380 Reference<container::XNamed> xNamedSlide (mxCurrentSlide, UNO_QUERY); 381 if (xNamedSlide.is()) 382 sCurrentSlideName = xNamedSlide->getName(); 383 Reference<beans::XPropertySet> xSlideProperties (mxCurrentSlide, UNO_QUERY); 384 if (xSlideProperties.is()) 385 { 386 try 387 { 388 OUString sName; 389 if (xSlideProperties->getPropertyValue(A2S("LinkDisplayName")) >>= sName) 390 { 391 // Find out whether the name of the current slide has been 392 // automatically created or has been set by the user. 393 if (sName != sCurrentSlideName) 394 sCurrentSlideName = sName; 395 } 396 } 397 catch (beans::UnknownPropertyException&) 398 { 399 } 400 } 401 402 // Replace the placeholders with their current values. 403 PresenterPaneContainer::PaneList::const_iterator iPane; 404 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane) 405 { 406 OSL_ASSERT((*iPane).get() != NULL); 407 408 OUString sTemplate (IsAccessibilityActive() 409 ? (*iPane)->msAccessibleTitleTemplate 410 : (*iPane)->msTitleTemplate); 411 if (sTemplate.getLength() <= 0) 412 continue; 413 414 OUStringBuffer sResult; 415 sResult.ensureCapacity(sTemplate.getLength()); 416 417 sal_Int32 nIndex (0); 418 while (true) 419 { 420 sal_Int32 nStartIndex = sTemplate.indexOf('%', nIndex); 421 if (nStartIndex < 0) 422 { 423 // Add the remaining part of the string. 424 sResult.append(sTemplate.copy(nIndex, sTemplate.getLength()-nIndex)); 425 break; 426 } 427 else 428 { 429 // Add the part preceding the next %. 430 sResult.append(sTemplate.copy(nIndex, nStartIndex-nIndex)); 431 432 // Get the placeholder 433 ++nIndex; 434 ++nStartIndex; 435 const sal_Int32 nEndIndex (sTemplate.indexOf('%', nStartIndex+1)); 436 const OUString sPlaceholder (sTemplate.copy(nStartIndex, nEndIndex-nStartIndex)); 437 nIndex = nEndIndex+1; 438 439 // Replace the placeholder with its current value. 440 if (sPlaceholder == sCurrentSlideNumberPlaceholder) 441 sResult.append(sCurrentSlideNumber); 442 else if (sPlaceholder == sCurrentSlideNamePlaceholder) 443 sResult.append(sCurrentSlideName); 444 else if (sPlaceholder == sSlideCountPlaceholder) 445 sResult.append(sSlideCount); 446 } 447 } 448 449 (*iPane)->msTitle = sResult.makeStringAndClear(); 450 if ((*iPane)->mxPane.is()) 451 (*iPane)->mxPane->SetTitle((*iPane)->msTitle); 452 } 453 } 454 455 456 457 458 void PresenterController::UpdateViews (void) 459 { 460 // Tell all views about the slides they should display. 461 PresenterPaneContainer::PaneList::const_iterator iPane; 462 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane) 463 { 464 Reference<drawing::XDrawView> xDrawView ((*iPane)->mxView, UNO_QUERY); 465 if (xDrawView.is()) 466 xDrawView->setCurrentPage(mxCurrentSlide); 467 } 468 } 469 470 471 472 473 SharedBitmapDescriptor 474 PresenterController::GetViewBackground (const ::rtl::OUString& rsViewURL) const 475 { 476 if (mpTheme.get() != NULL) 477 { 478 const OUString sStyleName (mpTheme->GetStyleName(rsViewURL)); 479 return mpTheme->GetBitmap(sStyleName, A2S("Background")); 480 } 481 return SharedBitmapDescriptor(); 482 } 483 484 485 486 487 PresenterTheme::SharedFontDescriptor 488 PresenterController::GetViewFont (const ::rtl::OUString& rsViewURL) const 489 { 490 if (mpTheme.get() != NULL) 491 { 492 const OUString sStyleName (mpTheme->GetStyleName(rsViewURL)); 493 return mpTheme->GetFont(sStyleName); 494 } 495 return PresenterTheme::SharedFontDescriptor(); 496 } 497 498 499 500 501 ::boost::shared_ptr<PresenterTheme> PresenterController::GetTheme (void) const 502 { 503 return mpTheme; 504 } 505 506 507 508 509 ::rtl::Reference<PresenterWindowManager> PresenterController::GetWindowManager (void) const 510 { 511 return mpWindowManager; 512 } 513 514 515 516 517 Reference<presentation::XSlideShowController> 518 PresenterController::GetSlideShowController(void) const 519 { 520 return mxSlideShowController; 521 } 522 523 524 525 526 rtl::Reference<PresenterPaneContainer> PresenterController::GetPaneContainer (void) const 527 { 528 return mpPaneContainer; 529 } 530 531 532 533 534 ::rtl::Reference<PresenterPaneBorderPainter> PresenterController::GetPaneBorderPainter (void) const 535 { 536 return mpPaneBorderPainter; 537 } 538 539 540 541 542 ::boost::shared_ptr<PresenterAnimator> PresenterController::GetAnimator (void) const 543 { 544 return mpAnimator; 545 } 546 547 548 549 550 ::boost::shared_ptr<PresenterCanvasHelper> PresenterController::GetCanvasHelper (void) const 551 { 552 return mpCanvasHelper; 553 } 554 555 556 557 558 Reference<drawing::XPresenterHelper> PresenterController::GetPresenterHelper (void) const 559 { 560 return mxPresenterHelper; 561 } 562 563 564 565 566 ::boost::shared_ptr<PresenterPaintManager> PresenterController::GetPaintManager (void) const 567 { 568 return mpPaintManager; 569 } 570 571 572 573 574 void PresenterController::HideSlideSorter (void) 575 { 576 if (mpCurrentPaneAnimation.get() != NULL) 577 { 578 mpCurrentPaneAnimation->HidePane(); 579 mpCurrentPaneAnimation.reset(); 580 } 581 } 582 583 584 585 586 void PresenterController::ShowView (const OUString& rsViewURL) 587 { 588 PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( 589 mpPaneContainer->FindViewURL(rsViewURL)); 590 if (pDescriptor.get() != NULL) 591 { 592 pDescriptor->mbIsActive = true; 593 mxConfigurationController->requestResourceActivation( 594 pDescriptor->mxPaneId, 595 ResourceActivationMode_ADD); 596 mxConfigurationController->requestResourceActivation( 597 ResourceId::createWithAnchor( 598 mxComponentContext, 599 rsViewURL, 600 pDescriptor->mxPaneId), 601 ResourceActivationMode_REPLACE); 602 } 603 } 604 605 606 607 608 void PresenterController::HideView (const OUString& rsViewURL) 609 { 610 PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( 611 mpPaneContainer->FindViewURL(rsViewURL)); 612 if (pDescriptor.get() != NULL) 613 { 614 mxConfigurationController->requestResourceDeactivation( 615 ResourceId::createWithAnchor( 616 mxComponentContext, 617 rsViewURL, 618 pDescriptor->mxPaneId)); 619 } 620 } 621 622 623 624 625 bool PresenterController::IsViewVisible (const OUString& rsViewURL) const 626 { 627 PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( 628 mpPaneContainer->FindViewURL(rsViewURL)); 629 if (pDescriptor.get() != NULL) 630 { 631 return mxConfigurationController->getResource( 632 ResourceId::createWithAnchor( 633 mxComponentContext, 634 rsViewURL, 635 pDescriptor->mxPaneId)).is(); 636 } 637 return false; 638 } 639 640 641 642 643 void PresenterController::DispatchUnoCommand (const OUString& rsCommand) const 644 { 645 if ( ! mxUrlTransformer.is()) 646 return; 647 648 util::URL aURL; 649 aURL.Complete = rsCommand; 650 mxUrlTransformer->parseStrict(aURL); 651 652 Reference<frame::XDispatch> xDispatch (GetDispatch(aURL)); 653 if ( ! xDispatch.is()) 654 return; 655 656 xDispatch->dispatch(aURL, Sequence<beans::PropertyValue>()); 657 } 658 659 660 661 662 Reference<css::frame::XDispatch> PresenterController::GetDispatch (const util::URL& rURL) const 663 { 664 if ( ! mxController.is()) 665 return NULL; 666 667 Reference<frame::XDispatchProvider> xDispatchProvider (mxController->getFrame(), UNO_QUERY); 668 if ( ! xDispatchProvider.is()) 669 return NULL; 670 671 return xDispatchProvider->queryDispatch( 672 rURL, 673 OUString(), 674 frame::FrameSearchFlag::SELF); 675 } 676 677 678 679 680 util::URL PresenterController::CreateURLFromString (const ::rtl::OUString& rsURL) const 681 { 682 util::URL aURL; 683 684 if (mxUrlTransformer.is()) 685 { 686 aURL.Complete = rsURL; 687 mxUrlTransformer->parseStrict(aURL); 688 } 689 690 return aURL; 691 } 692 693 694 695 696 Reference<drawing::framework::XConfigurationController> 697 PresenterController::GetConfigurationController (void) const 698 { 699 return mxConfigurationController; 700 } 701 702 703 704 705 Reference<drawing::XDrawPage> PresenterController::GetCurrentSlide (void) const 706 { 707 return mxCurrentSlide; 708 } 709 710 711 712 713 ::rtl::Reference<PresenterAccessible> PresenterController::GetAccessible (void) const 714 { 715 return mpAccessibleObject; 716 } 717 718 719 720 721 void PresenterController::SetAccessibilityActiveState (const bool bIsActive) 722 { 723 if ( mbIsAccessibilityActive != bIsActive) 724 { 725 mbIsAccessibilityActive = bIsActive; 726 UpdatePaneTitles(); 727 } 728 } 729 730 731 732 733 bool PresenterController::IsAccessibilityActive (void) const 734 { 735 return mbIsAccessibilityActive; 736 } 737 738 739 740 741 void PresenterController::HandleMouseClick (const awt::MouseEvent& rEvent) 742 { 743 if (mxSlideShowController.is()) 744 { 745 switch (rEvent.Buttons) 746 { 747 case awt::MouseButton::LEFT: 748 if (rEvent.Modifiers == awt::KeyModifier::MOD2) 749 mxSlideShowController->gotoNextSlide(); 750 else 751 mxSlideShowController->gotoNextEffect(); 752 break; 753 754 case awt::MouseButton::RIGHT: 755 mxSlideShowController->gotoPreviousSlide(); 756 break; 757 758 default: 759 // Other or multiple buttons. 760 break; 761 } 762 } 763 } 764 765 766 767 768 void PresenterController::RequestViews ( 769 const bool bIsSlideSorterActive, 770 const bool bIsNotesViewActive, 771 const bool bIsHelpViewActive) 772 { 773 PresenterPaneContainer::PaneList::const_iterator iPane; 774 PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end()); 775 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane) 776 { 777 bool bActivate (true); 778 const OUString sViewURL ((*iPane)->msViewURL); 779 if (sViewURL == PresenterViewFactory::msNotesViewURL) 780 { 781 bActivate = bIsNotesViewActive && !bIsSlideSorterActive && !bIsHelpViewActive; 782 } 783 else if (sViewURL == PresenterViewFactory::msSlideSorterURL) 784 { 785 bActivate = bIsSlideSorterActive; 786 } 787 else if (sViewURL == PresenterViewFactory::msCurrentSlidePreviewViewURL 788 || sViewURL == PresenterViewFactory::msNextSlidePreviewViewURL) 789 { 790 bActivate = !bIsSlideSorterActive && ! bIsHelpViewActive; 791 } 792 else if (sViewURL == PresenterViewFactory::msToolBarViewURL) 793 { 794 bActivate = true; 795 } 796 else if (sViewURL == PresenterViewFactory::msHelpViewURL) 797 { 798 bActivate = bIsHelpViewActive; 799 } 800 801 if (bActivate) 802 ShowView(sViewURL); 803 else 804 HideView(sViewURL); 805 } 806 } 807 808 809 810 811 //----- XConfigurationChangeListener ------------------------------------------ 812 813 void SAL_CALL PresenterController::notifyConfigurationChange ( 814 const ConfigurationChangeEvent& rEvent) 815 throw (RuntimeException) 816 { 817 ThrowIfDisposed(); 818 819 sal_Int32 nType (0); 820 if ( ! (rEvent.UserData >>= nType)) 821 return; 822 823 switch (nType) 824 { 825 case ResourceActivationEventType: 826 if (rEvent.ResourceId->compareTo(mxMainPaneId) == 0) 827 { 828 InitializeMainPane(Reference<XPane>(rEvent.ResourceObject,UNO_QUERY)); 829 } 830 else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_DIRECT)) 831 { 832 // A pane bound to the main pane has been created and is 833 // stored in the pane container. 834 Reference<XPane> xPane (rEvent.ResourceObject,UNO_QUERY); 835 if (xPane.is()) 836 { 837 PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( 838 mpPaneContainer->FindPaneId(xPane->getResourceId())); 839 840 // When there is a call out anchor location set then tell the 841 // window about it. 842 if (pDescriptor->mbHasCalloutAnchor) 843 pDescriptor->mxPane->SetCalloutAnchor( 844 pDescriptor->maCalloutAnchorLocation); 845 } 846 } 847 else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT)) 848 { 849 // A view bound to one of the panes has been created and is 850 // stored in the pane container along with its pane. 851 Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY); 852 if (xView.is()) 853 { 854 SharedBitmapDescriptor pViewBackground( 855 GetViewBackground(xView->getResourceId()->getResourceURL())); 856 mpPaneContainer->StoreView(xView, pViewBackground); 857 UpdateViews(); 858 mpWindowManager->NotifyViewCreation(xView); 859 } 860 } 861 break; 862 863 case ResourceDeactivationEventType: 864 if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT)) 865 { 866 // If this is a view then remove it from the pane container. 867 Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY); 868 if (xView.is()) 869 { 870 PresenterPaneContainer::SharedPaneDescriptor pDescriptor( 871 mpPaneContainer->RemoveView(xView)); 872 873 // A possibly opaque view has been removed. Update() 874 // updates the clip polygon. 875 mpWindowManager->Update(); 876 // Request the repainting of the area previously 877 // occupied by the view. 878 if (pDescriptor.get() != NULL) 879 GetPaintManager()->Invalidate(pDescriptor->mxBorderWindow); 880 } 881 } 882 break; 883 884 case ConfigurationUpdateEndEventType: 885 if (IsAccessibilityActive()) 886 { 887 mpAccessibleObject->UpdateAccessibilityHierarchy(); 888 UpdateCurrentSlide(0); 889 } 890 break; 891 } 892 } 893 894 895 896 897 //----- XEventListener -------------------------------------------------------- 898 899 void SAL_CALL PresenterController::disposing ( 900 const lang::EventObject& rEvent) 901 throw (RuntimeException) 902 { 903 if (rEvent.Source == mxController) 904 mxController = NULL; 905 else if (rEvent.Source == mxConfigurationController) 906 mxConfigurationController = NULL; 907 else if (rEvent.Source == mxSlideShowController) 908 mxSlideShowController = NULL; 909 else if (rEvent.Source == mxMainWindow) 910 mxMainWindow = NULL; 911 } 912 913 914 915 916 //----- XFrameActionListener -------------------------------------------------- 917 918 void SAL_CALL PresenterController::frameAction ( 919 const frame::FrameActionEvent& rEvent) 920 throw (RuntimeException) 921 { 922 if (rEvent.Action == frame::FrameAction_FRAME_ACTIVATED) 923 { 924 if (mxSlideShowController.is()) 925 mxSlideShowController->activate(); 926 } 927 } 928 929 930 931 932 //----- XKeyListener ---------------------------------------------------------- 933 934 void SAL_CALL PresenterController::keyPressed (const awt::KeyEvent& rEvent) 935 throw (RuntimeException) 936 { 937 // Tell all views about the unhandled key event. 938 PresenterPaneContainer::PaneList::const_iterator iPane; 939 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane) 940 { 941 if ( ! (*iPane)->mbIsActive) 942 continue; 943 944 Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY); 945 if (xKeyListener.is()) 946 xKeyListener->keyPressed(rEvent); 947 } 948 } 949 950 951 952 953 void SAL_CALL PresenterController::keyReleased (const awt::KeyEvent& rEvent) 954 throw (RuntimeException) 955 { 956 if (rEvent.Source != mxMainWindow) 957 return; 958 959 switch (rEvent.KeyCode) 960 { 961 case awt::Key::ESCAPE: 962 case awt::Key::SUBTRACT: 963 { 964 if( mxController.is() ) 965 { 966 Reference< XPresentationSupplier > xPS( mxController->getModel(), UNO_QUERY ); 967 if( xPS.is() ) 968 { 969 Reference< XPresentation > xP( xPS->getPresentation() ); 970 if( xP.is() ) 971 xP->end(); 972 } 973 } 974 } 975 break; 976 977 case awt::Key::PAGEDOWN: 978 if (mxSlideShowController.is()) 979 { 980 if (rEvent.Modifiers == awt::KeyModifier::MOD2) 981 mxSlideShowController->gotoNextSlide(); 982 else 983 mxSlideShowController->gotoNextEffect(); 984 } 985 break; 986 987 case awt::Key::RIGHT: 988 case awt::Key::SPACE: 989 case awt::Key::DOWN: 990 case awt::Key::N: 991 if (mxSlideShowController.is()) 992 { 993 mxSlideShowController->gotoNextEffect(); 994 } 995 break; 996 997 case awt::Key::LEFT: 998 case awt::Key::PAGEUP: 999 if (mxSlideShowController.is()) 1000 { 1001 if (rEvent.Modifiers == awt::KeyModifier::MOD2) 1002 mxSlideShowController->gotoPreviousSlide(); 1003 else 1004 mxSlideShowController->gotoPreviousEffect(); 1005 } 1006 break; 1007 1008 case awt::Key::UP: 1009 case awt::Key::P: 1010 case awt::Key::BACKSPACE: 1011 if (mxSlideShowController.is()) 1012 { 1013 mxSlideShowController->gotoPreviousEffect(); 1014 } 1015 break; 1016 1017 case awt::Key::HOME: 1018 if (mxSlideShowController.is()) 1019 { 1020 mxSlideShowController->gotoFirstSlide(); 1021 } 1022 break; 1023 1024 case awt::Key::END: 1025 if (mxSlideShowController.is()) 1026 { 1027 mxSlideShowController->gotoLastSlide(); 1028 } 1029 break; 1030 1031 case awt::Key::W: 1032 case awt::Key::COMMA: 1033 if (mxSlideShowController.is()) 1034 { 1035 if (mxSlideShowController->isPaused()) 1036 mxSlideShowController->resume(); 1037 else 1038 mxSlideShowController->blankScreen(0x00ffffff); 1039 } 1040 break; 1041 1042 case awt::Key::B: 1043 case awt::Key::POINT: 1044 if (mxSlideShowController.is()) 1045 { 1046 if (mxSlideShowController->isPaused()) 1047 mxSlideShowController->resume(); 1048 else 1049 mxSlideShowController->blankScreen(0x00000000); 1050 } 1051 break; 1052 1053 case awt::Key::NUM0: 1054 case awt::Key::NUM1: 1055 case awt::Key::NUM2: 1056 case awt::Key::NUM3: 1057 case awt::Key::NUM4: 1058 case awt::Key::NUM5: 1059 case awt::Key::NUM6: 1060 case awt::Key::NUM7: 1061 case awt::Key::NUM8: 1062 case awt::Key::NUM9: 1063 HandleNumericKeyPress(rEvent.KeyCode-awt::Key::NUM0, rEvent.Modifiers); 1064 break; 1065 1066 case awt::Key::RETURN: 1067 if (mnPendingSlideNumber > 0) 1068 { 1069 if (mxSlideShowController.is()) 1070 mxSlideShowController->gotoSlideIndex(mnPendingSlideNumber - 1); 1071 mnPendingSlideNumber = -1; 1072 } 1073 else 1074 { 1075 if (mxSlideShowController.is()) 1076 mxSlideShowController->gotoNextEffect(); 1077 } 1078 1079 break; 1080 1081 case awt::Key::F1: 1082 // Toggle the help view. 1083 if (mpWindowManager.get() != NULL) 1084 { 1085 if (mpWindowManager->GetViewMode() != PresenterWindowManager::VM_Help) 1086 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Help); 1087 else 1088 mpWindowManager->SetHelpViewState(false); 1089 } 1090 1091 break; 1092 1093 default: 1094 // Tell all views about the unhandled key event. 1095 PresenterPaneContainer::PaneList::const_iterator iPane; 1096 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane) 1097 { 1098 if ( ! (*iPane)->mbIsActive) 1099 continue; 1100 1101 Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY); 1102 if (xKeyListener.is()) 1103 xKeyListener->keyReleased(rEvent); 1104 } 1105 break; 1106 } 1107 } 1108 1109 1110 1111 1112 void PresenterController::HandleNumericKeyPress ( 1113 const sal_Int32 nKey, 1114 const sal_Int32 nModifiers) 1115 { 1116 switch (nModifiers) 1117 { 1118 case 0: 1119 if (mnPendingSlideNumber == -1) 1120 mnPendingSlideNumber = 0; 1121 UpdatePendingSlideNumber(mnPendingSlideNumber * 10 + nKey); 1122 break; 1123 1124 case awt::KeyModifier::MOD1: 1125 // Ctrl-1, Ctrl-2, and Ctrl-3 are used to switch between views 1126 // (slide view, notes view, normal) 1127 mnPendingSlideNumber = -1; 1128 if (mpWindowManager.get() == NULL) 1129 return; 1130 switch(nKey) 1131 { 1132 case 1: 1133 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Standard); 1134 break; 1135 case 2: 1136 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Notes); 1137 break; 1138 case 3: 1139 mpWindowManager->SetViewMode(PresenterWindowManager::VM_SlideOverview); 1140 break; 1141 default: 1142 // Ignore unsupported key. 1143 break; 1144 } 1145 1146 default: 1147 // Ignore unsupported modifiers. 1148 break; 1149 } 1150 } 1151 1152 1153 1154 1155 //----- XFocusListener -------------------------------------------------------- 1156 1157 void SAL_CALL PresenterController::focusGained (const css::awt::FocusEvent& rEvent) 1158 throw (css::uno::RuntimeException) 1159 { 1160 (void)rEvent; 1161 } 1162 1163 1164 1165 1166 void SAL_CALL PresenterController::focusLost (const css::awt::FocusEvent& rEvent) 1167 throw (css::uno::RuntimeException) 1168 { 1169 (void)rEvent; 1170 } 1171 1172 1173 1174 1175 //----- XMouseListener -------------------------------------------------------- 1176 1177 void SAL_CALL PresenterController::mousePressed (const css::awt::MouseEvent& rEvent) 1178 throw (css::uno::RuntimeException) 1179 { 1180 (void)rEvent; 1181 if (mxMainWindow.is()) 1182 mxMainWindow->setFocus(); 1183 } 1184 1185 1186 1187 1188 void SAL_CALL PresenterController::mouseReleased (const css::awt::MouseEvent& rEvent) 1189 throw (css::uno::RuntimeException) 1190 { 1191 (void)rEvent; 1192 } 1193 1194 1195 1196 1197 void SAL_CALL PresenterController::mouseEntered (const css::awt::MouseEvent& rEvent) 1198 throw (css::uno::RuntimeException) 1199 { 1200 (void)rEvent; 1201 } 1202 1203 1204 1205 1206 void SAL_CALL PresenterController::mouseExited (const css::awt::MouseEvent& rEvent) 1207 throw (css::uno::RuntimeException) 1208 { 1209 (void)rEvent; 1210 } 1211 1212 1213 1214 1215 //----- XMouseMotionListener -------------------------------------------------- 1216 1217 void SAL_CALL PresenterController::mouseMoved (const css::awt::MouseEvent& rEvent) 1218 throw (css::uno::RuntimeException) 1219 { 1220 (void)rEvent; 1221 } 1222 1223 1224 1225 1226 void SAL_CALL PresenterController::mouseDragged (const css::awt::MouseEvent& rEvent) 1227 throw (css::uno::RuntimeException) 1228 { 1229 (void)rEvent; 1230 } 1231 1232 1233 1234 1235 //----------------------------------------------------------------------------- 1236 1237 void PresenterController::InitializeMainPane (const Reference<XPane>& rxPane) 1238 { 1239 if ( ! rxPane.is()) 1240 return; 1241 1242 mpAccessibleObject = new PresenterAccessible( 1243 mxComponentContext, 1244 this, 1245 rxPane); 1246 1247 LoadTheme(rxPane); 1248 1249 // Main pane has been created and is now observed by the window 1250 // manager. 1251 mpWindowManager->SetParentPane(rxPane); 1252 mpWindowManager->SetTheme(mpTheme); 1253 1254 if (mpPaneBorderPainter.get() != NULL) 1255 mpPaneBorderPainter->SetTheme(mpTheme); 1256 1257 // Add key listener 1258 mxMainWindow = rxPane->getWindow(); 1259 if (mxMainWindow.is()) 1260 { 1261 mxMainWindow->addKeyListener(this); 1262 mxMainWindow->addFocusListener(this); 1263 mxMainWindow->addMouseListener(this); 1264 mxMainWindow->addMouseMotionListener(this); 1265 } 1266 Reference<XPane2> xPane2 (rxPane, UNO_QUERY); 1267 if (xPane2.is()) 1268 xPane2->setVisible(sal_True); 1269 1270 mpPaintManager.reset(new PresenterPaintManager(mxMainWindow, mxPresenterHelper, mpPaneContainer)); 1271 1272 mxCanvas = Reference<rendering::XSpriteCanvas>(rxPane->getCanvas(), UNO_QUERY); 1273 1274 if (mxSlideShowController.is()) 1275 mxSlideShowController->activate(); 1276 1277 UpdateCurrentSlide(0); 1278 } 1279 1280 1281 1282 1283 void PresenterController::LoadTheme (const Reference<XPane>& rxPane) 1284 { 1285 // Create (load) the current theme. 1286 if (rxPane.is()) 1287 mpTheme.reset(new PresenterTheme(mxComponentContext, OUString(), rxPane->getCanvas())); 1288 } 1289 1290 1291 1292 1293 double PresenterController::GetSlideAspectRatio (void) const 1294 { 1295 double nSlideAspectRatio (28.0/21.0); 1296 1297 try 1298 { 1299 if (mxController.is()) 1300 { 1301 Reference<drawing::XDrawPagesSupplier> xSlideSupplier ( 1302 mxController->getModel(), UNO_QUERY_THROW); 1303 Reference<drawing::XDrawPages> xSlides (xSlideSupplier->getDrawPages()); 1304 if (xSlides.is() && xSlides->getCount()>0) 1305 { 1306 Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW); 1307 sal_Int32 nWidth (28000); 1308 sal_Int32 nHeight (21000); 1309 if ((xProperties->getPropertyValue(OUString::createFromAscii("Width")) >>= nWidth) 1310 && (xProperties->getPropertyValue(OUString::createFromAscii("Height")) >>= nHeight) 1311 && nHeight > 0) 1312 { 1313 nSlideAspectRatio = double(nWidth) / double(nHeight); 1314 } 1315 } 1316 } 1317 } 1318 catch (RuntimeException&) 1319 { 1320 OSL_ASSERT(false); 1321 } 1322 1323 return nSlideAspectRatio; 1324 } 1325 1326 1327 1328 1329 void PresenterController::UpdatePendingSlideNumber (const sal_Int32 nPendingSlideNumber) 1330 { 1331 mnPendingSlideNumber = nPendingSlideNumber; 1332 1333 if (mpTheme.get() == NULL) 1334 return; 1335 1336 if ( ! mxMainWindow.is()) 1337 return; 1338 1339 PresenterTheme::SharedFontDescriptor pFont ( 1340 mpTheme->GetFont(A2S("PendingSlideNumberFont"))); 1341 if (pFont.get() == NULL) 1342 return; 1343 1344 pFont->PrepareFont(Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY)); 1345 if ( ! pFont->mxFont.is()) 1346 return; 1347 1348 const OUString sText (OUString::valueOf(mnPendingSlideNumber)); 1349 rendering::StringContext aContext (sText, 0, sText.getLength()); 1350 Reference<rendering::XTextLayout> xLayout ( 1351 pFont->mxFont->createTextLayout( 1352 aContext, 1353 rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 1354 0)); 1355 } 1356 1357 1358 1359 1360 void PresenterController::ThrowIfDisposed (void) const 1361 throw (::com::sun::star::lang::DisposedException) 1362 { 1363 if (rBHelper.bDisposed || rBHelper.bInDispose) 1364 { 1365 throw lang::DisposedException ( 1366 OUString(RTL_CONSTASCII_USTRINGPARAM( 1367 "PresenterController object has already been disposed")), 1368 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); 1369 } 1370 } 1371 1372 1373 } } // end of namespace ::sdext::presenter 1374 1375