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
Instance(const css::uno::Reference<css::frame::XFrame> & rxFrame)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
PresenterController(const Reference<XComponentContext> & rxContext,const Reference<frame::XController> & rxController,const Reference<presentation::XSlideShowController> & rxSlideShowController,const rtl::Reference<PresenterPaneContainer> & rpPaneContainer,const Reference<XResourceId> & rxMainPaneId)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
~PresenterController(void)213 PresenterController::~PresenterController (void)
214 {
215 }
216
217
218
219
disposing(void)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
UpdateCurrentSlide(const sal_Int32 nOffset)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
GetSlides(const sal_Int32 nOffset)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
UpdatePaneTitles(void)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
UpdateViews(void)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
GetViewBackground(const::rtl::OUString & rsViewURL) const474 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
GetViewFont(const::rtl::OUString & rsViewURL) const488 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
GetTheme(void) const501 ::boost::shared_ptr<PresenterTheme> PresenterController::GetTheme (void) const
502 {
503 return mpTheme;
504 }
505
506
507
508
GetWindowManager(void) const509 ::rtl::Reference<PresenterWindowManager> PresenterController::GetWindowManager (void) const
510 {
511 return mpWindowManager;
512 }
513
514
515
516
517 Reference<presentation::XSlideShowController>
GetSlideShowController(void) const518 PresenterController::GetSlideShowController(void) const
519 {
520 return mxSlideShowController;
521 }
522
523
524
525
GetPaneContainer(void) const526 rtl::Reference<PresenterPaneContainer> PresenterController::GetPaneContainer (void) const
527 {
528 return mpPaneContainer;
529 }
530
531
532
533
GetPaneBorderPainter(void) const534 ::rtl::Reference<PresenterPaneBorderPainter> PresenterController::GetPaneBorderPainter (void) const
535 {
536 return mpPaneBorderPainter;
537 }
538
539
540
541
GetAnimator(void) const542 ::boost::shared_ptr<PresenterAnimator> PresenterController::GetAnimator (void) const
543 {
544 return mpAnimator;
545 }
546
547
548
549
GetCanvasHelper(void) const550 ::boost::shared_ptr<PresenterCanvasHelper> PresenterController::GetCanvasHelper (void) const
551 {
552 return mpCanvasHelper;
553 }
554
555
556
557
GetPresenterHelper(void) const558 Reference<drawing::XPresenterHelper> PresenterController::GetPresenterHelper (void) const
559 {
560 return mxPresenterHelper;
561 }
562
563
564
565
GetPaintManager(void) const566 ::boost::shared_ptr<PresenterPaintManager> PresenterController::GetPaintManager (void) const
567 {
568 return mpPaintManager;
569 }
570
571
572
573
HideSlideSorter(void)574 void PresenterController::HideSlideSorter (void)
575 {
576 if (mpCurrentPaneAnimation.get() != NULL)
577 {
578 mpCurrentPaneAnimation->HidePane();
579 mpCurrentPaneAnimation.reset();
580 }
581 }
582
583
584
585
ShowView(const OUString & rsViewURL)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
HideView(const OUString & rsViewURL)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
IsViewVisible(const OUString & rsViewURL) const625 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
DispatchUnoCommand(const OUString & rsCommand) const643 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
GetDispatch(const util::URL & rURL) const662 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
CreateURLFromString(const::rtl::OUString & rsURL) const680 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>
GetConfigurationController(void) const697 PresenterController::GetConfigurationController (void) const
698 {
699 return mxConfigurationController;
700 }
701
702
703
704
GetCurrentSlide(void) const705 Reference<drawing::XDrawPage> PresenterController::GetCurrentSlide (void) const
706 {
707 return mxCurrentSlide;
708 }
709
710
711
712
GetAccessible(void) const713 ::rtl::Reference<PresenterAccessible> PresenterController::GetAccessible (void) const
714 {
715 return mpAccessibleObject;
716 }
717
718
719
720
SetAccessibilityActiveState(const bool bIsActive)721 void PresenterController::SetAccessibilityActiveState (const bool bIsActive)
722 {
723 if ( mbIsAccessibilityActive != bIsActive)
724 {
725 mbIsAccessibilityActive = bIsActive;
726 UpdatePaneTitles();
727 }
728 }
729
730
731
732
IsAccessibilityActive(void) const733 bool PresenterController::IsAccessibilityActive (void) const
734 {
735 return mbIsAccessibilityActive;
736 }
737
738
739
740
HandleMouseClick(const awt::MouseEvent & rEvent)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
RequestViews(const bool bIsSlideSorterActive,const bool bIsNotesViewActive,const bool bIsHelpViewActive)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
notifyConfigurationChange(const ConfigurationChangeEvent & rEvent)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
disposing(const lang::EventObject & rEvent)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
frameAction(const frame::FrameActionEvent & rEvent)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
keyPressed(const awt::KeyEvent & rEvent)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
keyReleased(const awt::KeyEvent & rEvent)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
HandleNumericKeyPress(const sal_Int32 nKey,const sal_Int32 nModifiers)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
focusGained(const css::awt::FocusEvent & rEvent)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
focusLost(const css::awt::FocusEvent & rEvent)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
mousePressed(const css::awt::MouseEvent & rEvent)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
mouseReleased(const css::awt::MouseEvent & rEvent)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
mouseEntered(const css::awt::MouseEvent & rEvent)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
mouseExited(const css::awt::MouseEvent & rEvent)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
mouseMoved(const css::awt::MouseEvent & rEvent)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
mouseDragged(const css::awt::MouseEvent & rEvent)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
InitializeMainPane(const Reference<XPane> & rxPane)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
LoadTheme(const Reference<XPane> & rxPane)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
GetSlideAspectRatio(void) const1293 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
UpdatePendingSlideNumber(const sal_Int32 nPendingSlideNumber)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
ThrowIfDisposed(void) const1360 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