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