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 { 816 ThrowIfDisposed(); 817 818 sal_Int32 nType (0); 819 if ( ! (rEvent.UserData >>= nType)) 820 return; 821 822 switch (nType) 823 { 824 case ResourceActivationEventType: 825 if (rEvent.ResourceId->compareTo(mxMainPaneId) == 0) 826 { 827 InitializeMainPane(Reference<XPane>(rEvent.ResourceObject,UNO_QUERY)); 828 } 829 else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_DIRECT)) 830 { 831 // A pane bound to the main pane has been created and is 832 // stored in the pane container. 833 Reference<XPane> xPane (rEvent.ResourceObject,UNO_QUERY); 834 if (xPane.is()) 835 { 836 PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( 837 mpPaneContainer->FindPaneId(xPane->getResourceId())); 838 839 // When there is a call out anchor location set then tell the 840 // window about it. 841 if (pDescriptor->mbHasCalloutAnchor) 842 pDescriptor->mxPane->SetCalloutAnchor( 843 pDescriptor->maCalloutAnchorLocation); 844 } 845 } 846 else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT)) 847 { 848 // A view bound to one of the panes has been created and is 849 // stored in the pane container along with its pane. 850 Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY); 851 if (xView.is()) 852 { 853 SharedBitmapDescriptor pViewBackground( 854 GetViewBackground(xView->getResourceId()->getResourceURL())); 855 mpPaneContainer->StoreView(xView, pViewBackground); 856 UpdateViews(); 857 mpWindowManager->NotifyViewCreation(xView); 858 } 859 } 860 break; 861 862 case ResourceDeactivationEventType: 863 if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT)) 864 { 865 // If this is a view then remove it from the pane container. 866 Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY); 867 if (xView.is()) 868 { 869 PresenterPaneContainer::SharedPaneDescriptor pDescriptor( 870 mpPaneContainer->RemoveView(xView)); 871 872 // A possibly opaque view has been removed. Update() 873 // updates the clip polygon. 874 mpWindowManager->Update(); 875 // Request the repainting of the area previously 876 // occupied by the view. 877 if (pDescriptor.get() != NULL) 878 GetPaintManager()->Invalidate(pDescriptor->mxBorderWindow); 879 } 880 } 881 break; 882 883 case ConfigurationUpdateEndEventType: 884 if (IsAccessibilityActive()) 885 { 886 mpAccessibleObject->UpdateAccessibilityHierarchy(); 887 UpdateCurrentSlide(0); 888 } 889 break; 890 } 891 } 892 893 894 895 896 //----- XEventListener -------------------------------------------------------- 897 898 void SAL_CALL PresenterController::disposing ( 899 const lang::EventObject& rEvent) 900 { 901 if (rEvent.Source == mxController) 902 mxController = NULL; 903 else if (rEvent.Source == mxConfigurationController) 904 mxConfigurationController = NULL; 905 else if (rEvent.Source == mxSlideShowController) 906 mxSlideShowController = NULL; 907 else if (rEvent.Source == mxMainWindow) 908 mxMainWindow = NULL; 909 } 910 911 912 913 914 //----- XFrameActionListener -------------------------------------------------- 915 916 void SAL_CALL PresenterController::frameAction ( 917 const frame::FrameActionEvent& rEvent) 918 { 919 if (rEvent.Action == frame::FrameAction_FRAME_ACTIVATED) 920 { 921 if (mxSlideShowController.is()) 922 mxSlideShowController->activate(); 923 } 924 } 925 926 927 928 929 //----- XKeyListener ---------------------------------------------------------- 930 931 void SAL_CALL PresenterController::keyPressed (const awt::KeyEvent& rEvent) 932 { 933 // Tell all views about the unhandled key event. 934 PresenterPaneContainer::PaneList::const_iterator iPane; 935 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane) 936 { 937 if ( ! (*iPane)->mbIsActive) 938 continue; 939 940 Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY); 941 if (xKeyListener.is()) 942 xKeyListener->keyPressed(rEvent); 943 } 944 } 945 946 947 948 949 void SAL_CALL PresenterController::keyReleased (const awt::KeyEvent& rEvent) 950 { 951 if (rEvent.Source != mxMainWindow) 952 return; 953 954 switch (rEvent.KeyCode) 955 { 956 case awt::Key::ESCAPE: 957 case awt::Key::SUBTRACT: 958 { 959 if( mxController.is() ) 960 { 961 Reference< XPresentationSupplier > xPS( mxController->getModel(), UNO_QUERY ); 962 if( xPS.is() ) 963 { 964 Reference< XPresentation > xP( xPS->getPresentation() ); 965 if( xP.is() ) 966 xP->end(); 967 } 968 } 969 } 970 break; 971 972 case awt::Key::PAGEDOWN: 973 if (mxSlideShowController.is()) 974 { 975 if (rEvent.Modifiers == awt::KeyModifier::MOD2) 976 mxSlideShowController->gotoNextSlide(); 977 else 978 mxSlideShowController->gotoNextEffect(); 979 } 980 break; 981 982 case awt::Key::RIGHT: 983 case awt::Key::SPACE: 984 case awt::Key::DOWN: 985 case awt::Key::N: 986 if (mxSlideShowController.is()) 987 { 988 mxSlideShowController->gotoNextEffect(); 989 } 990 break; 991 992 case awt::Key::LEFT: 993 case awt::Key::PAGEUP: 994 if (mxSlideShowController.is()) 995 { 996 if (rEvent.Modifiers == awt::KeyModifier::MOD2) 997 mxSlideShowController->gotoPreviousSlide(); 998 else 999 mxSlideShowController->gotoPreviousEffect(); 1000 } 1001 break; 1002 1003 case awt::Key::UP: 1004 case awt::Key::P: 1005 case awt::Key::BACKSPACE: 1006 if (mxSlideShowController.is()) 1007 { 1008 mxSlideShowController->gotoPreviousEffect(); 1009 } 1010 break; 1011 1012 case awt::Key::HOME: 1013 if (mxSlideShowController.is()) 1014 { 1015 mxSlideShowController->gotoFirstSlide(); 1016 } 1017 break; 1018 1019 case awt::Key::END: 1020 if (mxSlideShowController.is()) 1021 { 1022 mxSlideShowController->gotoLastSlide(); 1023 } 1024 break; 1025 1026 case awt::Key::W: 1027 case awt::Key::COMMA: 1028 if (mxSlideShowController.is()) 1029 { 1030 if (mxSlideShowController->isPaused()) 1031 mxSlideShowController->resume(); 1032 else 1033 mxSlideShowController->blankScreen(0x00ffffff); 1034 } 1035 break; 1036 1037 case awt::Key::B: 1038 case awt::Key::POINT: 1039 if (mxSlideShowController.is()) 1040 { 1041 if (mxSlideShowController->isPaused()) 1042 mxSlideShowController->resume(); 1043 else 1044 mxSlideShowController->blankScreen(0x00000000); 1045 } 1046 break; 1047 1048 case awt::Key::NUM0: 1049 case awt::Key::NUM1: 1050 case awt::Key::NUM2: 1051 case awt::Key::NUM3: 1052 case awt::Key::NUM4: 1053 case awt::Key::NUM5: 1054 case awt::Key::NUM6: 1055 case awt::Key::NUM7: 1056 case awt::Key::NUM8: 1057 case awt::Key::NUM9: 1058 HandleNumericKeyPress(rEvent.KeyCode-awt::Key::NUM0, rEvent.Modifiers); 1059 break; 1060 1061 case awt::Key::RETURN: 1062 if (mnPendingSlideNumber > 0) 1063 { 1064 if (mxSlideShowController.is()) 1065 mxSlideShowController->gotoSlideIndex(mnPendingSlideNumber - 1); 1066 mnPendingSlideNumber = -1; 1067 } 1068 else 1069 { 1070 if (mxSlideShowController.is()) 1071 mxSlideShowController->gotoNextEffect(); 1072 } 1073 1074 break; 1075 1076 case awt::Key::F1: 1077 // Toggle the help view. 1078 if (mpWindowManager.get() != NULL) 1079 { 1080 if (mpWindowManager->GetViewMode() != PresenterWindowManager::VM_Help) 1081 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Help); 1082 else 1083 mpWindowManager->SetHelpViewState(false); 1084 } 1085 1086 break; 1087 1088 default: 1089 // Tell all views about the unhandled key event. 1090 PresenterPaneContainer::PaneList::const_iterator iPane; 1091 for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane) 1092 { 1093 if ( ! (*iPane)->mbIsActive) 1094 continue; 1095 1096 Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY); 1097 if (xKeyListener.is()) 1098 xKeyListener->keyReleased(rEvent); 1099 } 1100 break; 1101 } 1102 } 1103 1104 1105 1106 1107 void PresenterController::HandleNumericKeyPress ( 1108 const sal_Int32 nKey, 1109 const sal_Int32 nModifiers) 1110 { 1111 switch (nModifiers) 1112 { 1113 case 0: 1114 if (mnPendingSlideNumber == -1) 1115 mnPendingSlideNumber = 0; 1116 UpdatePendingSlideNumber(mnPendingSlideNumber * 10 + nKey); 1117 break; 1118 1119 case awt::KeyModifier::MOD1: 1120 // Ctrl-1, Ctrl-2, and Ctrl-3 are used to switch between views 1121 // (slide view, notes view, normal) 1122 mnPendingSlideNumber = -1; 1123 if (mpWindowManager.get() == NULL) 1124 return; 1125 switch(nKey) 1126 { 1127 case 1: 1128 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Standard); 1129 break; 1130 case 2: 1131 mpWindowManager->SetViewMode(PresenterWindowManager::VM_Notes); 1132 break; 1133 case 3: 1134 mpWindowManager->SetViewMode(PresenterWindowManager::VM_SlideOverview); 1135 break; 1136 default: 1137 // Ignore unsupported key. 1138 break; 1139 } 1140 1141 default: 1142 // Ignore unsupported modifiers. 1143 break; 1144 } 1145 } 1146 1147 1148 1149 1150 //----- XFocusListener -------------------------------------------------------- 1151 1152 void SAL_CALL PresenterController::focusGained (const css::awt::FocusEvent& rEvent) 1153 { 1154 (void)rEvent; 1155 } 1156 1157 1158 1159 1160 void SAL_CALL PresenterController::focusLost (const css::awt::FocusEvent& rEvent) 1161 { 1162 (void)rEvent; 1163 } 1164 1165 1166 1167 1168 //----- XMouseListener -------------------------------------------------------- 1169 1170 void SAL_CALL PresenterController::mousePressed (const css::awt::MouseEvent& rEvent) 1171 { 1172 (void)rEvent; 1173 if (mxMainWindow.is()) 1174 mxMainWindow->setFocus(); 1175 } 1176 1177 1178 1179 1180 void SAL_CALL PresenterController::mouseReleased (const css::awt::MouseEvent& rEvent) 1181 { 1182 (void)rEvent; 1183 } 1184 1185 1186 1187 1188 void SAL_CALL PresenterController::mouseEntered (const css::awt::MouseEvent& rEvent) 1189 { 1190 (void)rEvent; 1191 } 1192 1193 1194 1195 1196 void SAL_CALL PresenterController::mouseExited (const css::awt::MouseEvent& rEvent) 1197 { 1198 (void)rEvent; 1199 } 1200 1201 1202 1203 1204 //----- XMouseMotionListener -------------------------------------------------- 1205 1206 void SAL_CALL PresenterController::mouseMoved (const css::awt::MouseEvent& rEvent) 1207 { 1208 (void)rEvent; 1209 } 1210 1211 1212 1213 1214 void SAL_CALL PresenterController::mouseDragged (const css::awt::MouseEvent& rEvent) 1215 { 1216 (void)rEvent; 1217 } 1218 1219 1220 1221 1222 //----------------------------------------------------------------------------- 1223 1224 void PresenterController::InitializeMainPane (const Reference<XPane>& rxPane) 1225 { 1226 if ( ! rxPane.is()) 1227 return; 1228 1229 mpAccessibleObject = new PresenterAccessible( 1230 mxComponentContext, 1231 this, 1232 rxPane); 1233 1234 LoadTheme(rxPane); 1235 1236 // Main pane has been created and is now observed by the window 1237 // manager. 1238 mpWindowManager->SetParentPane(rxPane); 1239 mpWindowManager->SetTheme(mpTheme); 1240 1241 if (mpPaneBorderPainter.get() != NULL) 1242 mpPaneBorderPainter->SetTheme(mpTheme); 1243 1244 // Add key listener 1245 mxMainWindow = rxPane->getWindow(); 1246 if (mxMainWindow.is()) 1247 { 1248 mxMainWindow->addKeyListener(this); 1249 mxMainWindow->addFocusListener(this); 1250 mxMainWindow->addMouseListener(this); 1251 mxMainWindow->addMouseMotionListener(this); 1252 } 1253 Reference<XPane2> xPane2 (rxPane, UNO_QUERY); 1254 if (xPane2.is()) 1255 xPane2->setVisible(sal_True); 1256 1257 mpPaintManager.reset(new PresenterPaintManager(mxMainWindow, mxPresenterHelper, mpPaneContainer)); 1258 1259 mxCanvas = Reference<rendering::XSpriteCanvas>(rxPane->getCanvas(), UNO_QUERY); 1260 1261 if (mxSlideShowController.is()) 1262 mxSlideShowController->activate(); 1263 1264 UpdateCurrentSlide(0); 1265 } 1266 1267 1268 1269 1270 void PresenterController::LoadTheme (const Reference<XPane>& rxPane) 1271 { 1272 // Create (load) the current theme. 1273 if (rxPane.is()) 1274 mpTheme.reset(new PresenterTheme(mxComponentContext, OUString(), rxPane->getCanvas())); 1275 } 1276 1277 1278 1279 1280 double PresenterController::GetSlideAspectRatio (void) const 1281 { 1282 double nSlideAspectRatio (28.0/21.0); 1283 1284 try 1285 { 1286 if (mxController.is()) 1287 { 1288 Reference<drawing::XDrawPagesSupplier> xSlideSupplier ( 1289 mxController->getModel(), UNO_QUERY_THROW); 1290 Reference<drawing::XDrawPages> xSlides (xSlideSupplier->getDrawPages()); 1291 if (xSlides.is() && xSlides->getCount()>0) 1292 { 1293 Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW); 1294 sal_Int32 nWidth (28000); 1295 sal_Int32 nHeight (21000); 1296 if ((xProperties->getPropertyValue(OUString::createFromAscii("Width")) >>= nWidth) 1297 && (xProperties->getPropertyValue(OUString::createFromAscii("Height")) >>= nHeight) 1298 && nHeight > 0) 1299 { 1300 nSlideAspectRatio = double(nWidth) / double(nHeight); 1301 } 1302 } 1303 } 1304 } 1305 catch (RuntimeException&) 1306 { 1307 OSL_ASSERT(false); 1308 } 1309 1310 return nSlideAspectRatio; 1311 } 1312 1313 1314 1315 1316 void PresenterController::UpdatePendingSlideNumber (const sal_Int32 nPendingSlideNumber) 1317 { 1318 mnPendingSlideNumber = nPendingSlideNumber; 1319 1320 if (mpTheme.get() == NULL) 1321 return; 1322 1323 if ( ! mxMainWindow.is()) 1324 return; 1325 1326 PresenterTheme::SharedFontDescriptor pFont ( 1327 mpTheme->GetFont(A2S("PendingSlideNumberFont"))); 1328 if (pFont.get() == NULL) 1329 return; 1330 1331 pFont->PrepareFont(Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY)); 1332 if ( ! pFont->mxFont.is()) 1333 return; 1334 1335 const OUString sText (OUString::valueOf(mnPendingSlideNumber)); 1336 rendering::StringContext aContext (sText, 0, sText.getLength()); 1337 Reference<rendering::XTextLayout> xLayout ( 1338 pFont->mxFont->createTextLayout( 1339 aContext, 1340 rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 1341 0)); 1342 } 1343 1344 1345 1346 1347 void PresenterController::ThrowIfDisposed (void) const 1348 { 1349 if (rBHelper.bDisposed || rBHelper.bInDispose) 1350 { 1351 throw lang::DisposedException ( 1352 OUString(RTL_CONSTASCII_USTRINGPARAM( 1353 "PresenterController object has already been disposed")), 1354 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); 1355 } 1356 } 1357 1358 1359 } } // end of namespace ::sdext::presenter 1360