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 0 : 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 (void)
191 : {
192 0 : }
193 :
194 0 : void PresenterController::disposing (void)
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 (void)
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 (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 (void)
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 (void) const
453 : {
454 0 : return mpTheme;
455 : }
456 :
457 0 : ::rtl::Reference<PresenterWindowManager> PresenterController::GetWindowManager (void) const
458 : {
459 0 : return mpWindowManager;
460 : }
461 :
462 : Reference<presentation::XSlideShowController>
463 0 : PresenterController::GetSlideShowController(void) const
464 : {
465 0 : return mxSlideShowController;
466 : }
467 :
468 0 : rtl::Reference<PresenterPaneContainer> PresenterController::GetPaneContainer (void) const
469 : {
470 0 : return mpPaneContainer;
471 : }
472 :
473 0 : ::rtl::Reference<PresenterPaneBorderPainter> PresenterController::GetPaneBorderPainter (void) const
474 : {
475 0 : return mpPaneBorderPainter;
476 : }
477 :
478 0 : ::boost::shared_ptr<PresenterCanvasHelper> PresenterController::GetCanvasHelper (void) const
479 : {
480 0 : return mpCanvasHelper;
481 : }
482 :
483 0 : Reference<drawing::XPresenterHelper> PresenterController::GetPresenterHelper (void) const
484 : {
485 0 : return mxPresenterHelper;
486 : }
487 :
488 0 : ::boost::shared_ptr<PresenterPaintManager> PresenterController::GetPaintManager (void) 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 (void) const
572 : {
573 0 : return mxConfigurationController;
574 : }
575 :
576 0 : Reference<drawing::XDrawPage> PresenterController::GetCurrentSlide (void) 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 0 : xSlidePropertySet->getPropertyValue("TransitionType") >>= aTransitionType;
589 0 : if( aTransitionType > 0 )
590 : {
591 0 : bTransition = true;
592 0 : }
593 : }
594 0 : return bTransition;
595 : }
596 :
597 0 : bool PresenterController::HasCustomAnimation (Reference<drawing::XDrawPage>& rxPage)
598 : {
599 0 : bool bCustomAnimation = false;
600 0 : presentation::AnimationEffect aEffect = presentation::AnimationEffect_NONE;
601 0 : presentation::AnimationEffect aTextEffect = presentation::AnimationEffect_NONE;
602 0 : if( rxPage.is() )
603 : {
604 0 : sal_uInt32 i, nCount = rxPage->getCount();
605 0 : for ( i = 0; i < nCount; i++ )
606 : {
607 0 : Reference<drawing::XShape> xShape(rxPage->getByIndex(i), UNO_QUERY);
608 0 : Reference<beans::XPropertySet> xShapePropertySet(xShape, UNO_QUERY);
609 0 : xShapePropertySet->getPropertyValue("Effect") >>= aEffect;
610 0 : xShapePropertySet->getPropertyValue("TextEffect") >>= aTextEffect;
611 0 : if( aEffect != presentation::AnimationEffect_NONE ||
612 0 : aTextEffect != presentation::AnimationEffect_NONE )
613 : {
614 0 : bCustomAnimation = true;
615 0 : break;
616 : }
617 0 : }
618 : }
619 0 : return bCustomAnimation;
620 : }
621 :
622 0 : void PresenterController::SetAccessibilityActiveState (const bool bIsActive)
623 : {
624 0 : if ( mbIsAccessibilityActive != bIsActive)
625 : {
626 0 : mbIsAccessibilityActive = bIsActive;
627 0 : UpdatePaneTitles();
628 : }
629 0 : }
630 :
631 0 : bool PresenterController::IsAccessibilityActive (void) const
632 : {
633 0 : return mbIsAccessibilityActive;
634 : }
635 :
636 0 : void PresenterController::HandleMouseClick (const awt::MouseEvent& rEvent)
637 : {
638 0 : if (mxSlideShowController.is())
639 : {
640 0 : switch (rEvent.Buttons)
641 : {
642 : case awt::MouseButton::LEFT:
643 0 : if (rEvent.Modifiers == awt::KeyModifier::MOD2)
644 0 : mxSlideShowController->gotoNextSlide();
645 : else
646 0 : mxSlideShowController->gotoNextEffect();
647 0 : break;
648 :
649 : case awt::MouseButton::RIGHT:
650 0 : mxSlideShowController->gotoPreviousSlide();
651 0 : break;
652 :
653 : default:
654 : // Other or multiple buttons.
655 0 : break;
656 : }
657 : }
658 0 : }
659 :
660 0 : void PresenterController::RequestViews (
661 : const bool bIsSlideSorterActive,
662 : const bool bIsNotesViewActive,
663 : const bool bIsHelpViewActive)
664 : {
665 0 : PresenterPaneContainer::PaneList::const_iterator iPane;
666 0 : PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end());
667 0 : for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane)
668 : {
669 0 : bool bActivate (true);
670 0 : const OUString sViewURL ((*iPane)->msViewURL);
671 0 : if (sViewURL == PresenterViewFactory::msNotesViewURL)
672 : {
673 0 : bActivate = bIsNotesViewActive && !bIsSlideSorterActive && !bIsHelpViewActive;
674 : }
675 0 : else if (sViewURL == PresenterViewFactory::msSlideSorterURL)
676 : {
677 0 : bActivate = bIsSlideSorterActive;
678 : }
679 0 : else if (sViewURL == PresenterViewFactory::msCurrentSlidePreviewViewURL
680 0 : || sViewURL == PresenterViewFactory::msNextSlidePreviewViewURL)
681 : {
682 0 : bActivate = !bIsSlideSorterActive && ! bIsHelpViewActive;
683 : }
684 0 : else if (sViewURL == PresenterViewFactory::msToolBarViewURL)
685 : {
686 0 : bActivate = true;
687 : }
688 0 : else if (sViewURL == PresenterViewFactory::msHelpViewURL)
689 : {
690 0 : bActivate = bIsHelpViewActive;
691 : }
692 :
693 0 : if (bActivate)
694 0 : ShowView(sViewURL);
695 : else
696 0 : HideView(sViewURL);
697 0 : }
698 0 : }
699 :
700 : //----- XConfigurationChangeListener ------------------------------------------
701 :
702 0 : void SAL_CALL PresenterController::notifyConfigurationChange (
703 : const ConfigurationChangeEvent& rEvent)
704 : throw (RuntimeException, std::exception)
705 : {
706 0 : ThrowIfDisposed();
707 :
708 0 : sal_Int32 nType (0);
709 0 : if ( ! (rEvent.UserData >>= nType))
710 0 : return;
711 :
712 0 : switch (nType)
713 : {
714 : case ResourceActivationEventType:
715 0 : if (rEvent.ResourceId->compareTo(mxMainPaneId) == 0)
716 : {
717 0 : InitializeMainPane(Reference<XPane>(rEvent.ResourceObject,UNO_QUERY));
718 : }
719 0 : else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_DIRECT))
720 : {
721 : // A pane bound to the main pane has been created and is
722 : // stored in the pane container.
723 0 : Reference<XPane> xPane (rEvent.ResourceObject,UNO_QUERY);
724 0 : if (xPane.is())
725 : {
726 : PresenterPaneContainer::SharedPaneDescriptor pDescriptor (
727 0 : mpPaneContainer->FindPaneId(xPane->getResourceId()));
728 :
729 : // When there is a call out anchor location set then tell the
730 : // window about it.
731 0 : if (pDescriptor->mbHasCalloutAnchor)
732 0 : pDescriptor->mxPane->SetCalloutAnchor(
733 0 : pDescriptor->maCalloutAnchorLocation);
734 0 : }
735 : }
736 0 : else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT))
737 : {
738 : // A view bound to one of the panes has been created and is
739 : // stored in the pane container along with its pane.
740 0 : Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY);
741 0 : if (xView.is())
742 : {
743 : SharedBitmapDescriptor pViewBackground(
744 0 : GetViewBackground(xView->getResourceId()->getResourceURL()));
745 0 : mpPaneContainer->StoreView(xView, pViewBackground);
746 0 : UpdateViews();
747 0 : mpWindowManager->NotifyViewCreation(xView);
748 0 : }
749 : }
750 0 : break;
751 :
752 : case ResourceDeactivationEventType:
753 0 : if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT))
754 : {
755 : // If this is a view then remove it from the pane container.
756 0 : Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY);
757 0 : if (xView.is())
758 : {
759 : PresenterPaneContainer::SharedPaneDescriptor pDescriptor(
760 0 : mpPaneContainer->RemoveView(xView));
761 :
762 : // A possibly opaque view has been removed. Update()
763 : // updates the clip polygon.
764 0 : mpWindowManager->Update();
765 : // Request the repainting of the area previously
766 : // occupied by the view.
767 0 : if (pDescriptor.get() != NULL)
768 0 : GetPaintManager()->Invalidate(pDescriptor->mxBorderWindow);
769 0 : }
770 : }
771 0 : break;
772 :
773 : case ConfigurationUpdateEndEventType:
774 0 : if (IsAccessibilityActive())
775 : {
776 0 : mpAccessibleObject->UpdateAccessibilityHierarchy();
777 0 : UpdateCurrentSlide(0);
778 : }
779 0 : break;
780 : }
781 : }
782 :
783 : //----- XEventListener --------------------------------------------------------
784 :
785 0 : void SAL_CALL PresenterController::disposing (
786 : const lang::EventObject& rEvent)
787 : throw (RuntimeException, std::exception)
788 : {
789 0 : if (rEvent.Source == mxController)
790 0 : mxController = NULL;
791 0 : else if (rEvent.Source == mxConfigurationController)
792 0 : mxConfigurationController = NULL;
793 0 : else if (rEvent.Source == mxSlideShowController)
794 0 : mxSlideShowController = NULL;
795 0 : else if (rEvent.Source == mxMainWindow)
796 0 : mxMainWindow = NULL;
797 0 : }
798 :
799 : //----- XFrameActionListener --------------------------------------------------
800 :
801 0 : void SAL_CALL PresenterController::frameAction (
802 : const frame::FrameActionEvent& rEvent)
803 : throw (RuntimeException, std::exception)
804 : {
805 0 : if (rEvent.Action == frame::FrameAction_FRAME_ACTIVATED)
806 : {
807 0 : if (mxSlideShowController.is())
808 0 : mxSlideShowController->activate();
809 : }
810 0 : }
811 :
812 : //----- XKeyListener ----------------------------------------------------------
813 :
814 0 : void SAL_CALL PresenterController::keyPressed (const awt::KeyEvent& rEvent)
815 : throw (RuntimeException, std::exception)
816 : {
817 : // Tell all views about the unhandled key event.
818 0 : PresenterPaneContainer::PaneList::const_iterator iPane;
819 0 : for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
820 : {
821 0 : if ( ! (*iPane)->mbIsActive)
822 0 : continue;
823 :
824 0 : Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY);
825 0 : if (xKeyListener.is())
826 0 : xKeyListener->keyPressed(rEvent);
827 0 : }
828 0 : }
829 :
830 0 : void SAL_CALL PresenterController::keyReleased (const awt::KeyEvent& rEvent)
831 : throw (RuntimeException, std::exception)
832 : {
833 0 : if (rEvent.Source != mxMainWindow)
834 0 : return;
835 :
836 0 : switch (rEvent.KeyCode)
837 : {
838 : case awt::Key::ESCAPE:
839 : case awt::Key::SUBTRACT:
840 : {
841 0 : if( mxController.is() )
842 : {
843 0 : Reference< XPresentationSupplier > xPS( mxController->getModel(), UNO_QUERY );
844 0 : if( xPS.is() )
845 : {
846 0 : Reference< XPresentation > xP( xPS->getPresentation() );
847 0 : if( xP.is() )
848 0 : xP->end();
849 0 : }
850 : }
851 : }
852 0 : break;
853 :
854 : case awt::Key::PAGEDOWN:
855 0 : if (mxSlideShowController.is())
856 : {
857 0 : if (rEvent.Modifiers == awt::KeyModifier::MOD2)
858 0 : mxSlideShowController->gotoNextSlide();
859 : else
860 0 : mxSlideShowController->gotoNextEffect();
861 : }
862 0 : break;
863 :
864 : case awt::Key::RIGHT:
865 : case awt::Key::SPACE:
866 : case awt::Key::DOWN:
867 : case awt::Key::N:
868 0 : if (mxSlideShowController.is())
869 : {
870 0 : mxSlideShowController->gotoNextEffect();
871 : }
872 0 : break;
873 :
874 : case awt::Key::PAGEUP:
875 0 : if (mxSlideShowController.is())
876 : {
877 0 : if (rEvent.Modifiers == awt::KeyModifier::MOD2)
878 0 : mxSlideShowController->gotoPreviousSlide();
879 : else
880 0 : mxSlideShowController->gotoPreviousEffect();
881 : }
882 0 : break;
883 :
884 : case awt::Key::LEFT:
885 : case awt::Key::UP:
886 : case awt::Key::P:
887 : case awt::Key::BACKSPACE:
888 0 : if (mxSlideShowController.is())
889 : {
890 0 : mxSlideShowController->gotoPreviousEffect();
891 : }
892 0 : break;
893 :
894 : case awt::Key::HOME:
895 0 : if (mxSlideShowController.is())
896 : {
897 0 : mxSlideShowController->gotoFirstSlide();
898 : }
899 0 : break;
900 :
901 : case awt::Key::END:
902 0 : if (mxSlideShowController.is())
903 : {
904 0 : mxSlideShowController->gotoLastSlide();
905 : }
906 0 : break;
907 :
908 : case awt::Key::W:
909 : case awt::Key::COMMA:
910 0 : if (mxSlideShowController.is())
911 : {
912 0 : if (mxSlideShowController->isPaused())
913 0 : mxSlideShowController->resume();
914 : else
915 0 : mxSlideShowController->blankScreen(0x00ffffff);
916 : }
917 0 : break;
918 :
919 : case awt::Key::B:
920 : case awt::Key::POINT:
921 0 : if (mxSlideShowController.is())
922 : {
923 0 : if (mxSlideShowController->isPaused())
924 0 : mxSlideShowController->resume();
925 : else
926 0 : mxSlideShowController->blankScreen(0x00000000);
927 : }
928 0 : break;
929 :
930 : case awt::Key::NUM0:
931 : case awt::Key::NUM1:
932 : case awt::Key::NUM2:
933 : case awt::Key::NUM3:
934 : case awt::Key::NUM4:
935 : case awt::Key::NUM5:
936 : case awt::Key::NUM6:
937 : case awt::Key::NUM7:
938 : case awt::Key::NUM8:
939 : case awt::Key::NUM9:
940 0 : HandleNumericKeyPress(rEvent.KeyCode-awt::Key::NUM0, rEvent.Modifiers);
941 0 : break;
942 :
943 : case awt::Key::RETURN:
944 0 : if (mnPendingSlideNumber > 0)
945 : {
946 0 : if (mxSlideShowController.is())
947 0 : mxSlideShowController->gotoSlideIndex(mnPendingSlideNumber - 1);
948 0 : mnPendingSlideNumber = -1;
949 : }
950 : else
951 : {
952 0 : if (mxSlideShowController.is())
953 0 : mxSlideShowController->gotoNextEffect();
954 : }
955 :
956 0 : break;
957 :
958 : case awt::Key::F1:
959 : // Toggle the help view.
960 0 : if (mpWindowManager.get() != NULL)
961 : {
962 0 : if (mpWindowManager->GetViewMode() != PresenterWindowManager::VM_Help)
963 0 : mpWindowManager->SetViewMode(PresenterWindowManager::VM_Help);
964 : else
965 0 : mpWindowManager->SetHelpViewState(false);
966 : }
967 :
968 0 : break;
969 :
970 : default:
971 : // Tell all views about the unhandled key event.
972 0 : PresenterPaneContainer::PaneList::const_iterator iPane;
973 0 : for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane)
974 : {
975 0 : if ( ! (*iPane)->mbIsActive)
976 0 : continue;
977 :
978 0 : Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY);
979 0 : if (xKeyListener.is())
980 0 : xKeyListener->keyReleased(rEvent);
981 0 : }
982 0 : break;
983 : }
984 : }
985 :
986 0 : void PresenterController::HandleNumericKeyPress (
987 : const sal_Int32 nKey,
988 : const sal_Int32 nModifiers)
989 : {
990 0 : switch (nModifiers)
991 : {
992 : case 0:
993 0 : if (mnPendingSlideNumber == -1)
994 0 : mnPendingSlideNumber = 0;
995 0 : UpdatePendingSlideNumber(mnPendingSlideNumber * 10 + nKey);
996 0 : break;
997 :
998 : case awt::KeyModifier::MOD1:
999 : // Ctrl-1, Ctrl-2, and Ctrl-3 are used to switch between views
1000 : // (slide view, notes view, normal)
1001 0 : mnPendingSlideNumber = -1;
1002 0 : if (mpWindowManager.get() == NULL)
1003 0 : return;
1004 0 : switch(nKey)
1005 : {
1006 : case 1:
1007 0 : mpWindowManager->SetViewMode(PresenterWindowManager::VM_Standard);
1008 0 : break;
1009 : case 2:
1010 0 : mpWindowManager->SetViewMode(PresenterWindowManager::VM_Notes);
1011 0 : break;
1012 : case 3:
1013 0 : mpWindowManager->SetViewMode(PresenterWindowManager::VM_SlideOverview);
1014 0 : break;
1015 : default:
1016 : // Ignore unsupported key.
1017 0 : break;
1018 : }
1019 :
1020 : default:
1021 : // Ignore unsupported modifiers.
1022 0 : break;
1023 : }
1024 : }
1025 :
1026 : //----- XFocusListener --------------------------------------------------------
1027 :
1028 0 : void SAL_CALL PresenterController::focusGained (const css::awt::FocusEvent& rEvent)
1029 : throw (css::uno::RuntimeException, std::exception)
1030 : {
1031 : (void)rEvent;
1032 0 : }
1033 :
1034 0 : void SAL_CALL PresenterController::focusLost (const css::awt::FocusEvent& rEvent)
1035 : throw (css::uno::RuntimeException, std::exception)
1036 : {
1037 : (void)rEvent;
1038 0 : }
1039 :
1040 : //----- XMouseListener --------------------------------------------------------
1041 :
1042 0 : void SAL_CALL PresenterController::mousePressed (const css::awt::MouseEvent& rEvent)
1043 : throw (css::uno::RuntimeException, std::exception)
1044 : {
1045 : (void)rEvent;
1046 0 : if (mxMainWindow.is())
1047 0 : mxMainWindow->setFocus();
1048 0 : }
1049 :
1050 0 : void SAL_CALL PresenterController::mouseReleased (const css::awt::MouseEvent& rEvent)
1051 : throw (css::uno::RuntimeException, std::exception)
1052 : {
1053 : (void)rEvent;
1054 0 : }
1055 :
1056 0 : void SAL_CALL PresenterController::mouseEntered (const css::awt::MouseEvent& rEvent)
1057 : throw (css::uno::RuntimeException, std::exception)
1058 : {
1059 : (void)rEvent;
1060 0 : }
1061 :
1062 0 : void SAL_CALL PresenterController::mouseExited (const css::awt::MouseEvent& rEvent)
1063 : throw (css::uno::RuntimeException, std::exception)
1064 : {
1065 : (void)rEvent;
1066 0 : }
1067 :
1068 : //----- XMouseMotionListener --------------------------------------------------
1069 :
1070 0 : void SAL_CALL PresenterController::mouseMoved (const css::awt::MouseEvent& rEvent)
1071 : throw (css::uno::RuntimeException, std::exception)
1072 : {
1073 : (void)rEvent;
1074 0 : }
1075 :
1076 0 : void SAL_CALL PresenterController::mouseDragged (const css::awt::MouseEvent& rEvent)
1077 : throw (css::uno::RuntimeException, std::exception)
1078 : {
1079 : (void)rEvent;
1080 0 : }
1081 :
1082 :
1083 :
1084 0 : void PresenterController::InitializeMainPane (const Reference<XPane>& rxPane)
1085 : {
1086 0 : if ( ! rxPane.is())
1087 0 : return;
1088 :
1089 0 : mpAccessibleObject = new PresenterAccessible(
1090 : mxComponentContext,
1091 : this,
1092 0 : rxPane);
1093 :
1094 0 : LoadTheme(rxPane);
1095 :
1096 : // Main pane has been created and is now observed by the window
1097 : // manager.
1098 0 : mpWindowManager->SetParentPane(rxPane);
1099 0 : mpWindowManager->SetTheme(mpTheme);
1100 :
1101 0 : if (mpPaneBorderPainter.get() != NULL)
1102 0 : mpPaneBorderPainter->SetTheme(mpTheme);
1103 :
1104 : // Add key listener
1105 0 : mxMainWindow = rxPane->getWindow();
1106 0 : if (mxMainWindow.is())
1107 : {
1108 0 : mxMainWindow->addKeyListener(this);
1109 0 : mxMainWindow->addFocusListener(this);
1110 0 : mxMainWindow->addMouseListener(this);
1111 0 : mxMainWindow->addMouseMotionListener(this);
1112 : }
1113 0 : Reference<XPane2> xPane2 (rxPane, UNO_QUERY);
1114 0 : if (xPane2.is())
1115 0 : xPane2->setVisible(sal_True);
1116 :
1117 0 : mpPaintManager.reset(new PresenterPaintManager(mxMainWindow, mxPresenterHelper, mpPaneContainer));
1118 :
1119 0 : mxCanvas = Reference<rendering::XSpriteCanvas>(rxPane->getCanvas(), UNO_QUERY);
1120 :
1121 0 : if (mxSlideShowController.is())
1122 0 : mxSlideShowController->activate();
1123 :
1124 0 : UpdateCurrentSlide(0);
1125 : }
1126 :
1127 0 : void PresenterController::LoadTheme (const Reference<XPane>& rxPane)
1128 : {
1129 : // Create (load) the current theme.
1130 0 : if (rxPane.is())
1131 0 : mpTheme.reset(new PresenterTheme(mxComponentContext, OUString(), rxPane->getCanvas()));
1132 0 : }
1133 :
1134 0 : double PresenterController::GetSlideAspectRatio (void) const
1135 : {
1136 0 : double nSlideAspectRatio (28.0/21.0);
1137 :
1138 : try
1139 : {
1140 0 : if (mxController.is())
1141 : {
1142 : Reference<drawing::XDrawPagesSupplier> xSlideSupplier (
1143 0 : mxController->getModel(), UNO_QUERY_THROW);
1144 0 : Reference<drawing::XDrawPages> xSlides (xSlideSupplier->getDrawPages());
1145 0 : if (xSlides.is() && xSlides->getCount()>0)
1146 : {
1147 0 : Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW);
1148 0 : sal_Int32 nWidth (28000);
1149 0 : sal_Int32 nHeight (21000);
1150 0 : if ((xProperties->getPropertyValue("Width") >>= nWidth)
1151 0 : && (xProperties->getPropertyValue("Height") >>= nHeight)
1152 0 : && nHeight > 0)
1153 : {
1154 0 : nSlideAspectRatio = double(nWidth) / double(nHeight);
1155 0 : }
1156 0 : }
1157 : }
1158 : }
1159 0 : catch (RuntimeException&)
1160 : {
1161 : OSL_ASSERT(false);
1162 : }
1163 :
1164 0 : return nSlideAspectRatio;
1165 : }
1166 :
1167 0 : void PresenterController::UpdatePendingSlideNumber (const sal_Int32 nPendingSlideNumber)
1168 : {
1169 0 : mnPendingSlideNumber = nPendingSlideNumber;
1170 :
1171 0 : if (mpTheme.get() == NULL)
1172 0 : return;
1173 :
1174 0 : if ( ! mxMainWindow.is())
1175 0 : return;
1176 :
1177 : PresenterTheme::SharedFontDescriptor pFont (
1178 0 : mpTheme->GetFont("PendingSlideNumberFont"));
1179 0 : if (pFont.get() == NULL)
1180 0 : return;
1181 :
1182 0 : pFont->PrepareFont(Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY));
1183 0 : if ( ! pFont->mxFont.is())
1184 0 : return;
1185 :
1186 0 : const OUString sText (OUString::number(mnPendingSlideNumber));
1187 0 : rendering::StringContext aContext (sText, 0, sText.getLength());
1188 : Reference<rendering::XTextLayout> xLayout (
1189 0 : pFont->mxFont->createTextLayout(
1190 : aContext,
1191 : rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
1192 0 : 0));
1193 : }
1194 :
1195 0 : void PresenterController::ThrowIfDisposed (void) const
1196 : throw (::com::sun::star::lang::DisposedException)
1197 : {
1198 0 : if (rBHelper.bDisposed || rBHelper.bInDispose)
1199 : {
1200 : throw lang::DisposedException (
1201 : OUString( "PresenterController object has already been disposed"),
1202 0 : const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1203 : }
1204 0 : }
1205 :
1206 0 : void PresenterController::SwitchMonitors (void)
1207 : {
1208 0 : Reference<lang::XEventListener> xScreen( mxScreen );
1209 0 : if (!xScreen.is())
1210 0 : return;
1211 :
1212 0 : PresenterScreen *pScreen = dynamic_cast<PresenterScreen *>(xScreen.get());
1213 0 : if (!pScreen)
1214 0 : return;
1215 :
1216 0 : pScreen->SwitchMonitors();
1217 : }
1218 :
1219 0 : } } // end of namespace ::sdext::presenter
1220 :
1221 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|