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