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