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