LibreOffice Module sdext (master)  1
PresenterSlideShowView.cxx
Go to the documentation of this file.
1 
2 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * This file is part of the LibreOffice project.
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * This file incorporates work covered by the following license notice:
11  *
12  * Licensed to the Apache Software Foundation (ASF) under one or more
13  * contributor license agreements. See the NOTICE file distributed
14  * with this work for additional information regarding copyright
15  * ownership. The ASF licenses this file to you under the Apache
16  * License, Version 2.0 (the "License"); you may not use this file
17  * except in compliance with the License. You may obtain a copy of
18  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19  */
20 
24 #include "PresenterHelper.hxx"
26 #include <com/sun/star/awt/InvalidateStyle.hpp>
27 #include <com/sun/star/awt/PosSize.hpp>
28 #include <com/sun/star/awt/Pointer.hpp>
29 #include <com/sun/star/awt/Toolkit.hpp>
30 #include <com/sun/star/awt/WindowAttribute.hpp>
31 #include <com/sun/star/awt/XWindow.hpp>
32 #include <com/sun/star/awt/XWindowPeer.hpp>
33 #include <com/sun/star/drawing/XPresenterHelper.hpp>
34 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
35 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
36 #include <com/sun/star/rendering/CompositeOperation.hpp>
37 #include <com/sun/star/rendering/TextDirection.hpp>
38 #include <com/sun/star/rendering/TexturingMode.hpp>
39 #include <osl/mutex.hxx>
40 
41 using namespace ::com::sun::star;
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::drawing::framework;
44 
45 namespace sdext::presenter {
46 
47 //===== PresenterSlideShowView ================================================
48 
50  const css::uno::Reference<css::uno::XComponentContext>& rxContext,
51  const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId,
52  const css::uno::Reference<css::frame::XController>& rxController,
53  const ::rtl::Reference<PresenterController>& rpPresenterController)
55  mxComponentContext(rxContext),
56  mpPresenterController(rpPresenterController),
57  mxViewId(rxViewId),
58  mxController(rxController),
59  mxSlideShowController(PresenterHelper::GetSlideShowController(rxController)),
60  mxSlideShow(),
61  mxCanvas(),
62  mxViewCanvas(),
63  mxPointer(),
64  mxWindow(),
65  mxViewWindow(),
66  mxTopPane(),
68  mxBackgroundPolygon1(),
69  mxBackgroundPolygon2(),
70  mbIsViewAdded(false),
71  mnPageAspectRatio(28.0/21.0),
72  maBroadcaster(m_aMutex),
73  mpBackground(),
74  mbIsForcedPaintPending(false),
75  mbIsPaintPending(true),
76  msClickToExitPresentationText(),
77  msClickToExitPresentationTitle(),
78  msTitleTemplate(),
79  mbIsEndSlideVisible(false),
80  mxCurrentSlide()
81 {
82  if (mpPresenterController.get() != nullptr)
83  {
84  mnPageAspectRatio = mpPresenterController->GetSlideAspectRatio();
85  mpBackground = mpPresenterController->GetViewBackground(mxViewId->getResourceURL());
86  }
87 }
88 
90 {
91  mxSlideShow.set( mxSlideShowController->getSlideShow(), UNO_SET_THROW);
92  Reference<lang::XComponent> xSlideShowComponent (mxSlideShow, UNO_QUERY);
93  xSlideShowComponent->addEventListener(static_cast<awt::XWindowListener*>(this));
94 
95  Reference<lang::XMultiComponentFactory> xFactory (
96  mxComponentContext->getServiceManager(), UNO_SET_THROW);
97  mxPresenterHelper.set (xFactory->createInstanceWithContext(
98  "com.sun.star.comp.Draw.PresenterHelper",
100  UNO_QUERY_THROW);
101 
102  // Use view id and controller to retrieve window and canvas from
103  // configuration controller.
104  Reference<XControllerManager> xCM (mxController, UNO_QUERY_THROW);
105  Reference<XConfigurationController> xCC (xCM->getConfigurationController());
106 
107  if (xCC.is())
108  {
109  mxTopPane.set(xCC->getResource(mxViewId->getAnchor()->getAnchor()), UNO_QUERY);
110 
111  Reference<XPane> xPane (xCC->getResource(mxViewId->getAnchor()), UNO_QUERY_THROW);
112 
113  mxWindow = xPane->getWindow();
114  mxCanvas = xPane->getCanvas();
115 
116  if (mxWindow.is())
117  {
118  mxWindow->addPaintListener(this);
119  mxWindow->addWindowListener(this);
120  }
121 
122  // The window does not have to paint a background. We do
123  // that ourself.
124  Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
125  if (xPeer.is())
126  xPeer->setBackground(util::Color(0xff000000));
127  }
128 
129  // Create a window for the actual slide show view. It is places
130  // centered and with maximal size inside the pane.
132 
134 
135  if (mxViewWindow.is())
136  {
137  // Register listeners at window.
138  mxViewWindow->addPaintListener(this);
139  mxViewWindow->addMouseListener(this);
140  mxViewWindow->addMouseMotionListener(this);
141  }
142 
143  if (mxViewWindow.is())
144  Resize();
145 
146  if (mxWindow.is())
147  mxWindow->setVisible(true);
148 
149  // Add the new slide show view to the slide show.
150  if (mxSlideShow.is() && ! mbIsViewAdded)
151  {
153  mbIsViewAdded = true;
154  }
155 
156  // Read text for one past last slide.
157  PresenterConfigurationAccess aConfiguration (
161  aConfiguration.GetConfigurationNode(
162  "Presenter/Views/CurrentSlidePreview/"
163  "Strings/ClickToExitPresentationText/String")
165  aConfiguration.GetConfigurationNode(
166  "Presenter/Views/CurrentSlidePreview/"
167  "Strings/ClickToExitPresentationTitle/String")
169 }
170 
172 {
173 }
174 
176 {
177  // Tell all listeners that we are disposed.
178  lang::EventObject aEvent;
179  aEvent.Source = static_cast<XWeak*>(this);
180 
183  if (pIterator != nullptr)
184  pIterator->disposeAndClear(aEvent);
185 
186  // Do this for
187  // XPaintListener, XModifyListener,XMouseListener,XMouseMotionListener,XWindowListener?
188 
189  if (mxWindow.is())
190  {
191  mxWindow->removePaintListener(this);
192  mxWindow->removeMouseListener(this);
193  mxWindow->removeMouseMotionListener(this);
194  mxWindow->removeWindowListener(this);
195  mxWindow = nullptr;
196  }
197  mxSlideShowController = nullptr;
198  mxSlideShow = nullptr;
199  if (mxViewCanvas.is())
200  {
201  Reference<XComponent> xComponent (mxViewCanvas, UNO_QUERY);
202  mxViewCanvas = nullptr;
203  if (xComponent.is())
204  xComponent->dispose();
205  }
206  if (mxViewWindow.is())
207  {
208  Reference<XComponent> xComponent = mxViewWindow;
209  mxViewWindow = nullptr;
210  if (xComponent.is())
211  xComponent->dispose();
212  }
213  if (mxPointer.is())
214  {
215  Reference<XComponent> xComponent (mxPointer, UNO_QUERY);
216  mxPointer = nullptr;
217  if (xComponent.is())
218  xComponent->dispose();
219  }
220  if (mxBackgroundPolygon1.is())
221  {
222  Reference<XComponent> xComponent (mxBackgroundPolygon1, UNO_QUERY);
223  mxBackgroundPolygon1 = nullptr;
224  if (xComponent.is())
225  xComponent->dispose();
226  }
227  if (mxBackgroundPolygon2.is())
228  {
229  Reference<XComponent> xComponent (mxBackgroundPolygon2, UNO_QUERY);
230  mxBackgroundPolygon2 = nullptr;
231  if (xComponent.is())
232  xComponent->dispose();
233  }
234 
235  mxComponentContext = nullptr;
236  mpPresenterController = nullptr;
237  mxViewId = nullptr;
238  mxController = nullptr;
239  mxCanvas = nullptr;
240  mpBackground.reset();
243  msTitleTemplate.clear();
244  mxCurrentSlide = nullptr;
245 }
246 
247 //----- XDrawView -------------------------------------------------------------
248 
250  const css::uno::Reference<css::drawing::XDrawPage>& rxSlide)
251 {
252  mxCurrentSlide = rxSlide;
253  if (mpPresenterController.get() != nullptr
254  && mxSlideShowController.is()
255  && ! mpPresenterController->GetCurrentSlide().is()
256  && ! mxSlideShowController->isPaused())
257  {
258  mbIsEndSlideVisible = true;
259  Reference<awt::XWindowPeer> xPeer (mxViewWindow, UNO_QUERY);
260  if (xPeer.is())
261  xPeer->invalidate(awt::InvalidateStyle::NOTRANSPARENT);
262 
263  // For the end slide we use a special title, without the (n of m)
264  // part. Save the title template for the case that the user goes
265  // backwards.
267  mpPresenterController->GetPaneContainer()->FindViewURL(mxViewId->getResourceURL()));
268  if (pDescriptor.get() != nullptr)
269  {
270  msTitleTemplate = pDescriptor->msTitleTemplate;
271  pDescriptor->msTitleTemplate = msClickToExitPresentationTitle;
272  mpPresenterController->UpdatePaneTitles();
273  }
274  }
275  else if (mbIsEndSlideVisible)
276  {
277  mbIsEndSlideVisible = false;
278 
279  // Restore the title template.
281  mpPresenterController->GetPaneContainer()->FindViewURL(mxViewId->getResourceURL()));
282  if (pDescriptor.get() != nullptr)
283  {
284  pDescriptor->msTitleTemplate = msTitleTemplate;
285  pDescriptor->msTitle.clear();
286  mpPresenterController->UpdatePaneTitles();
287  }
288  }
289 }
290 
291 css::uno::Reference<css::drawing::XDrawPage> SAL_CALL PresenterSlideShowView::getCurrentPage()
292 {
293  return mxCurrentSlide;
294 }
295 
296 //----- CachablePresenterView -------------------------------------------------
297 
299 {
300  if (mxSlideShow.is() && mbIsViewAdded)
301  {
302  mxSlideShow->removeView(this);
303  mbIsViewAdded = false;
304  }
305 }
306 
307 //----- XSlideShowView --------------------------------------------------------
308 
309 Reference<rendering::XSpriteCanvas> SAL_CALL PresenterSlideShowView::getCanvas()
310 {
311  ThrowIfDisposed();
312 
313  return Reference<rendering::XSpriteCanvas>(mxViewCanvas, UNO_QUERY);
314 }
315 
317 {
318  ThrowIfDisposed();
319  mbIsForcedPaintPending = false;
320  mbIsPaintPending = false;
321 
322  if (!(mxViewCanvas.is() && mxViewWindow.is()))
323  return;
324 
325  // Create a polygon for the window outline.
326  awt::Rectangle aViewWindowBox (mxViewWindow->getPosSize());
327  Reference<rendering::XPolyPolygon2D> xPolygon (PresenterGeometryHelper::CreatePolygon(
328  awt::Rectangle(0,0, aViewWindowBox.Width,aViewWindowBox.Height),
329  mxViewCanvas->getDevice()));
330 
331  rendering::ViewState aViewState (
332  geometry::AffineMatrix2D(1,0,0, 0,1,0),
333  nullptr);
334  double const aColor[4] = {0,0,0,0};
335  rendering::RenderState aRenderState(
336  geometry::AffineMatrix2D(1,0,0, 0,1,0),
337  nullptr,
338  Sequence<double>(aColor,4),
339  rendering::CompositeOperation::SOURCE);
340  mxViewCanvas->fillPolyPolygon(xPolygon, aViewState, aRenderState);
341 }
342 
343 geometry::AffineMatrix2D SAL_CALL PresenterSlideShowView::getTransformation()
344 {
345  ThrowIfDisposed();
346 
347  if (mxViewWindow.is())
348  {
349  // When the mbIsInModifyNotification is set then a slightly modified
350  // version of the transformation is returned in order to get past
351  // optimizations the avoid updates when the transformation is
352  // unchanged (when the window size changes then due to the constant
353  // aspect ratio the size of the preview may remain the same while
354  // the position changes. The position, however, is represented by
355  // the position of the view window. This transformation is given
356  // relative to the view window and therefore does not contain the
357  // position.)
358  const awt::Rectangle aWindowBox = mxViewWindow->getPosSize();
359  return geometry::AffineMatrix2D(
360  aWindowBox.Width-1, 0, 0,
361  0, aWindowBox.Height-1, 0);
362  }
363  else
364  {
365  return geometry::AffineMatrix2D(1,0,0, 0,1,0);
366  }
367 }
368 
369 geometry::IntegerSize2D SAL_CALL PresenterSlideShowView::getTranslationOffset()
370 {
371  ThrowIfDisposed();
372  return geometry::IntegerSize2D(0,0);
373 }
374 
376  const Reference<util::XModifyListener>& rxListener)
377 {
378  ThrowIfDisposed();
381  rxListener);
382 }
383 
385  const Reference<util::XModifyListener>& rxListener)
386 {
387  ThrowIfDisposed();
390  rxListener);
391 }
392 
394  const Reference<awt::XPaintListener>& rxListener)
395 {
396  ThrowIfDisposed();
399  rxListener);
400 }
401 
403  const Reference<awt::XPaintListener>& rxListener)
404 {
405  ThrowIfDisposed();
408  rxListener);
409 }
410 
412  const Reference<awt::XMouseListener>& rxListener)
413 {
414  ThrowIfDisposed();
417  rxListener);
418 }
419 
421  const Reference<awt::XMouseListener>& rxListener)
422 {
423  ThrowIfDisposed();
426  rxListener);
427 }
428 
430  const Reference<awt::XMouseMotionListener>& rxListener)
431 {
432  ThrowIfDisposed();
435  rxListener);
436 }
437 
439  const Reference<awt::XMouseMotionListener>& rxListener)
440 {
441  ThrowIfDisposed();
444  rxListener);
445 }
446 
447 void SAL_CALL PresenterSlideShowView::setMouseCursor(::sal_Int16 nPointerShape)
448 {
449  ThrowIfDisposed();
450 
451  // Create a pointer when it does not yet exist.
452  if ( ! mxPointer.is())
453  {
454  mxPointer = awt::Pointer::create(mxComponentContext);
455  }
456 
457  // Set the pointer to the given shape and the window(peer) to the
458  // pointer.
459  Reference<awt::XWindowPeer> xPeer (mxViewWindow, UNO_QUERY);
460  if (mxPointer.is() && xPeer.is())
461  {
462  mxPointer->setType(nPointerShape);
463  xPeer->setPointer(mxPointer);
464  }
465 }
466 
467 awt::Rectangle SAL_CALL PresenterSlideShowView::getCanvasArea( )
468 {
469  if( mxViewWindow.is() && mxTopPane.is() )
470  return mxPresenterHelper->getWindowExtentsRelative( mxViewWindow, mxTopPane->getWindow() );
471 
472  awt::Rectangle aRectangle;
473 
474  aRectangle.X = aRectangle.Y = aRectangle.Width = aRectangle.Height = 0;
475 
476  return aRectangle;
477 }
478 
479 //----- lang::XEventListener --------------------------------------------------
480 
481 void SAL_CALL PresenterSlideShowView::disposing (const lang::EventObject& rEvent)
482 {
483  if (rEvent.Source == mxViewWindow)
484  mxViewWindow = nullptr;
485  else if (rEvent.Source == mxSlideShow)
486  mxSlideShow = nullptr;
487 }
488 
489 //----- XPaintListener --------------------------------------------------------
490 
491 void SAL_CALL PresenterSlideShowView::windowPaint (const awt::PaintEvent& rEvent)
492 {
493  // Deactivated views must not be painted.
495  return;
496 
497  awt::Rectangle aViewWindowBox (mxViewWindow->getPosSize());
498  if (aViewWindowBox.Width <= 0 || aViewWindowBox.Height <= 0)
499  return;
500 
501  if (rEvent.Source == mxWindow)
502  PaintOuterWindow(rEvent.UpdateRect);
503  else if (mbIsEndSlideVisible)
504  PaintEndSlide(rEvent.UpdateRect);
505  else
506  PaintInnerWindow(rEvent);
507 }
508 
509 //----- XMouseListener --------------------------------------------------------
510 
511 void SAL_CALL PresenterSlideShowView::mousePressed (const awt::MouseEvent& rEvent)
512 {
513  awt::MouseEvent aEvent (rEvent);
514  aEvent.Source = static_cast<XWeak*>(this);
517  if (pIterator != nullptr)
518  {
519  pIterator->notifyEach(&awt::XMouseListener::mousePressed, aEvent);
520  }
521 
522  // Only when the end slide is displayed we forward the mouse event to
523  // the PresenterController so that it switches to the next slide and
524  // ends the presentation.
526  if (mpPresenterController.get() != nullptr)
527  mpPresenterController->HandleMouseClick(rEvent);
528 }
529 
530 void SAL_CALL PresenterSlideShowView::mouseReleased (const awt::MouseEvent& rEvent)
531 {
532  awt::MouseEvent aEvent (rEvent);
533  aEvent.Source = static_cast<XWeak*>(this);
536  if (pIterator != nullptr)
537  {
538  pIterator->notifyEach(&awt::XMouseListener::mouseReleased, aEvent);
539  }
540 }
541 
542 void SAL_CALL PresenterSlideShowView::mouseEntered (const awt::MouseEvent& rEvent)
543 {
544  awt::MouseEvent aEvent (rEvent);
545  aEvent.Source = static_cast<XWeak*>(this);
548  if (pIterator != nullptr)
549  {
550  pIterator->notifyEach(&awt::XMouseListener::mouseEntered, aEvent);
551  }
552 }
553 
554 void SAL_CALL PresenterSlideShowView::mouseExited (const awt::MouseEvent& rEvent)
555 {
556  awt::MouseEvent aEvent (rEvent);
557  aEvent.Source = static_cast<XWeak*>(this);
560  if (pIterator != nullptr)
561  {
562  pIterator->notifyEach(&awt::XMouseListener::mouseExited, aEvent);
563  }
564 }
565 
566 //----- XMouseMotionListener --------------------------------------------------
567 
568 void SAL_CALL PresenterSlideShowView::mouseDragged (const awt::MouseEvent& rEvent)
569 {
570  awt::MouseEvent aEvent (rEvent);
571  aEvent.Source = static_cast<XWeak*>(this);
574  if (pIterator != nullptr)
575  {
576  pIterator->notifyEach(&awt::XMouseMotionListener::mouseDragged, aEvent);
577  }
578 }
579 
580 void SAL_CALL PresenterSlideShowView::mouseMoved (const awt::MouseEvent& rEvent)
581 {
582  awt::MouseEvent aEvent (rEvent);
583  aEvent.Source = static_cast<XWeak*>(this);
586  if (pIterator != nullptr)
587  {
588  pIterator->notifyEach(&awt::XMouseMotionListener::mouseMoved, aEvent);
589  }
590 }
591 
592 //----- XWindowListener -------------------------------------------------------
593 
594 void SAL_CALL PresenterSlideShowView::windowResized (const awt::WindowEvent&)
595 {
596  ThrowIfDisposed();
597  ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
598 
599  Resize();
600 }
601 
602 void SAL_CALL PresenterSlideShowView::windowMoved (const awt::WindowEvent&)
603 {
604  if ( ! mbIsPaintPending)
605  mbIsForcedPaintPending = true;
606 }
607 
608 void SAL_CALL PresenterSlideShowView::windowShown (const lang::EventObject&)
609 {
610  Resize();
611 }
612 
613 void SAL_CALL PresenterSlideShowView::windowHidden (const lang::EventObject&) {}
614 
615 //----- XView -----------------------------------------------------------------
616 
617 Reference<XResourceId> SAL_CALL PresenterSlideShowView::getResourceId()
618 {
619  return mxViewId;
620 }
621 
623 {
624  return false;
625 }
626 
627 //----- CachablePresenterView -------------------------------------------------
628 
630 {
631  if (mxSlideShow.is() && ! mbIsViewAdded)
632  {
634  mbIsViewAdded = true;
635  }
636 }
637 
639 {
640  if (mxSlideShow.is() && mbIsViewAdded)
641  {
642  mxSlideShow->removeView(this);
643  mbIsViewAdded = false;
644  }
645 }
646 
647 
648 void PresenterSlideShowView::PaintOuterWindow (const awt::Rectangle& rRepaintBox)
649 {
650  if ( ! mxCanvas.is())
651  return;
652 
653  if (mpBackground.get() == nullptr)
654  return;
655 
656  const rendering::ViewState aViewState(
657  geometry::AffineMatrix2D(1,0,0, 0,1,0),
658  PresenterGeometryHelper::CreatePolygon(rRepaintBox, mxCanvas->getDevice()));
659 
660  rendering::RenderState aRenderState (
661  geometry::AffineMatrix2D(1,0,0, 0,1,0),
662  nullptr,
663  Sequence<double>(4),
664  rendering::CompositeOperation::SOURCE);
665 
666  Reference<rendering::XBitmap> xBackgroundBitmap (mpBackground->GetNormalBitmap());
667  if (xBackgroundBitmap.is())
668  {
669  Sequence<rendering::Texture> aTextures (1);
670  const geometry::IntegerSize2D aBitmapSize(xBackgroundBitmap->getSize());
671  aTextures[0] = rendering::Texture (
672  geometry::AffineMatrix2D(
673  aBitmapSize.Width,0,0,
674  0,aBitmapSize.Height,0),
675  1,
676  0,
677  xBackgroundBitmap,
678  nullptr,
679  nullptr,
680  rendering::StrokeAttributes(),
681  rendering::TexturingMode::REPEAT,
682  rendering::TexturingMode::REPEAT);
683 
684  if (mxBackgroundPolygon1.is())
685  mxCanvas->fillTexturedPolyPolygon(
687  aViewState,
688  aRenderState,
689  aTextures);
690  if (mxBackgroundPolygon2.is())
691  mxCanvas->fillTexturedPolyPolygon(
693  aViewState,
694  aRenderState,
695  aTextures);
696  }
697  else
698  {
699  PresenterCanvasHelper::SetDeviceColor(aRenderState, mpBackground->maReplacementColor);
700 
701  if (mxBackgroundPolygon1.is())
702  mxCanvas->fillPolyPolygon(mxBackgroundPolygon1, aViewState, aRenderState);
703  if (mxBackgroundPolygon2.is())
704  mxCanvas->fillPolyPolygon(mxBackgroundPolygon2, aViewState, aRenderState);
705  }
706 }
707 
708 void PresenterSlideShowView::PaintEndSlide (const awt::Rectangle& rRepaintBox)
709 {
710  if ( ! mxCanvas.is())
711  return;
712 
713  const rendering::ViewState aViewState(
714  geometry::AffineMatrix2D(1,0,0, 0,1,0),
715  PresenterGeometryHelper::CreatePolygon(rRepaintBox, mxCanvas->getDevice()));
716 
717  rendering::RenderState aRenderState (
718  geometry::AffineMatrix2D(1,0,0, 0,1,0),
719  nullptr,
720  Sequence<double>(4),
721  rendering::CompositeOperation::SOURCE);
722  PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x00000000));
723  mxCanvas->fillPolyPolygon(
724  PresenterGeometryHelper::CreatePolygon(mxViewWindow->getPosSize(), mxCanvas->getDevice()),
725  aViewState,
726  aRenderState);
727 
728  do
729  {
730  if (mpPresenterController.get() == nullptr)
731  break;
732  std::shared_ptr<PresenterTheme> pTheme (mpPresenterController->GetTheme());
733  if (pTheme == nullptr)
734  break;
735 
736  const OUString sViewStyle (pTheme->GetStyleName(mxViewId->getResourceURL()));
737  PresenterTheme::SharedFontDescriptor pFont (pTheme->GetFont(sViewStyle));
738  if (pFont.get() == nullptr)
739  break;
740 
742  PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x00ffffff));
743  aRenderState.AffineTransform.m02 = 20;
744  aRenderState.AffineTransform.m12 = 40;
745  const rendering::StringContext aContext (
747  pFont->PrepareFont(mxCanvas);
748  const Reference<rendering::XTextLayout> xLayout (
749  pFont->mxFont->createTextLayout(aContext,rendering::TextDirection::WEAK_LEFT_TO_RIGHT,0));
750  mxCanvas->drawTextLayout(
751  xLayout,
752  aViewState,
753  aRenderState);
754  }
755  while (false);
756 
757  // Finally, in double buffered environments, request the changes to be
758  // made visible.
759  Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
760  if (xSpriteCanvas.is())
761  xSpriteCanvas->updateScreen(true);
762 }
763 
764 void PresenterSlideShowView::PaintInnerWindow (const awt::PaintEvent& rEvent)
765 {
766  // Forward window paint to listeners.
767  awt::PaintEvent aEvent (rEvent);
768  aEvent.Source = static_cast<XWeak*>(this);
771  if (pIterator != nullptr)
772  {
773  pIterator->notifyEach(&awt::XPaintListener::windowPaint, aEvent);
774  }
775 
781  {
782  mxSlideShow->removeView(this);
784  }
785 
786  // Finally, in double buffered environments, request the changes to be
787  // made visible.
788  Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
789  if (xSpriteCanvas.is())
790  xSpriteCanvas->updateScreen(true);
791 }
792 
794  const Reference<awt::XWindow>& rxParentWindow) const
795 {
796  Reference<awt::XWindow> xViewWindow;
797  try
798  {
799  Reference<lang::XMultiComponentFactory> xFactory (mxComponentContext->getServiceManager());
800  if ( ! xFactory.is())
801  return xViewWindow;
802 
803  Reference<awt::XToolkit2> xToolkit = awt::Toolkit::create(mxComponentContext);
804  awt::WindowDescriptor aWindowDescriptor (
805  awt::WindowClass_CONTAINER,
806  OUString(),
807  Reference<awt::XWindowPeer>(rxParentWindow,UNO_QUERY_THROW),
808  -1, // parent index not available
809  awt::Rectangle(0,0,10,10),
810  awt::WindowAttribute::SIZEABLE
811  | awt::WindowAttribute::MOVEABLE
812  | awt::WindowAttribute::NODECORATION);
813  xViewWindow.set( xToolkit->createWindow(aWindowDescriptor),UNO_QUERY_THROW);
814 
815  // Make the background transparent. The slide show paints its own background.
816  Reference<awt::XWindowPeer> xPeer (xViewWindow, UNO_QUERY_THROW);
817  xPeer->setBackground(0xff000000);
818 
819  xViewWindow->setVisible(true);
820  }
821  catch (RuntimeException&)
822  {
823  }
824  return xViewWindow;
825 }
826 
827 Reference<rendering::XCanvas> PresenterSlideShowView::CreateViewCanvas (
828  const Reference<awt::XWindow>& rxViewWindow) const
829 {
830  // Create a canvas for the view window.
831  return mxPresenterHelper->createSharedCanvas(
832  Reference<rendering::XSpriteCanvas>(mxTopPane->getCanvas(), UNO_QUERY),
833  mxTopPane->getWindow(),
834  mxTopPane->getCanvas(),
835  mxTopPane->getWindow(),
836  rxViewWindow);
837 }
838 
840 {
841  if ( ! mxWindow.is() || ! mxViewWindow.is())
842  return;
843 
844  const awt::Rectangle aWindowBox (mxWindow->getPosSize());
845  awt::Rectangle aViewWindowBox;
846  if (aWindowBox.Height > 0)
847  {
848  const double nWindowAspectRatio (
849  double(aWindowBox.Width) / double(aWindowBox.Height));
850  if (nWindowAspectRatio > mnPageAspectRatio)
851  {
852  // Slides will be painted with the full parent window height.
853  aViewWindowBox.Width = sal_Int32(aWindowBox.Height * mnPageAspectRatio + 0.5);
854  aViewWindowBox.Height = aWindowBox.Height;
855  aViewWindowBox.X = (aWindowBox.Width - aViewWindowBox.Width) / 2;
856  aViewWindowBox.Y = 0;
857  }
858  else
859  {
860  // Slides will be painted with the full parent window width.
861  aViewWindowBox.Width = aWindowBox.Width;
862  aViewWindowBox.Height = sal_Int32(aWindowBox.Width / mnPageAspectRatio + 0.5);
863  aViewWindowBox.X = 0;
864  aViewWindowBox.Y = (aWindowBox.Height - aViewWindowBox.Height) / 2;
865  }
866  mxViewWindow->setPosSize(
867  aViewWindowBox.X,
868  aViewWindowBox.Y,
869  aViewWindowBox.Width,
870  aViewWindowBox.Height,
871  awt::PosSize::POSSIZE);
872  }
873 
874  // Clear the background polygon so that on the next paint it is created
875  // for the new size.
877 
878  // Notify listeners that the transformation that maps the view into the
879  // window has changed.
880  lang::EventObject aEvent (static_cast<XWeak*>(this));
883  if (pIterator != nullptr)
884  {
885  pIterator->notifyEach(&util::XModifyListener::modified, aEvent);
886  }
887 
888  // Due to constant aspect ratio resizing may lead a preview that changes
889  // its position but not its size. This invalidates the back buffer and
890  // we have to enforce a complete repaint.
891  if ( ! mbIsPaintPending)
892  mbIsForcedPaintPending = true;
893 }
894 
896 {
897  const awt::Rectangle aWindowBox (mxWindow->getPosSize());
898  const awt::Rectangle aViewWindowBox (mxViewWindow->getPosSize());
899  if (aWindowBox.Height == aViewWindowBox.Height && aWindowBox.Width == aViewWindowBox.Width)
900  {
901  mxBackgroundPolygon1 = nullptr;
902  mxBackgroundPolygon2 = nullptr;
903  }
904  else if (aWindowBox.Height == aViewWindowBox.Height)
905  {
906  // Paint two boxes to the left and right of the view window.
908  awt::Rectangle(
909  0,
910  0,
911  aViewWindowBox.X,
912  aWindowBox.Height),
913  mxCanvas->getDevice());
915  awt::Rectangle(
916  aViewWindowBox.X + aViewWindowBox.Width,
917  0,
918  aWindowBox.Width - aViewWindowBox.X - aViewWindowBox.Width,
919  aWindowBox.Height),
920  mxCanvas->getDevice());
921  }
922  else
923  {
924  // Paint two boxes above and below the view window.
926  awt::Rectangle(
927  0,
928  0,
929  aWindowBox.Width,
930  aViewWindowBox.Y),
931  mxCanvas->getDevice());
933  awt::Rectangle(
934  0,
935  aViewWindowBox.Y + aViewWindowBox.Height,
936  aWindowBox.Width,
937  aWindowBox.Height - aViewWindowBox.Y - aViewWindowBox.Height),
938  mxCanvas->getDevice());
939  }
940 }
941 
943 {
944  if (rBHelper.bDisposed || rBHelper.bInDispose)
945  {
946  throw lang::DisposedException (
947  "PresenterSlideShowView object has already been disposed",
948  static_cast<uno::XWeak*>(this));
949  }
950 }
951 
953 {
954  Reference<presentation::XSlideShowView> xView (this);
955  mxSlideShow->addView(xView);
956  // Prevent embedded sounds being played twice at the same time by
957  // disabling sound for the new slide show view.
958  beans::PropertyValue aProperty;
959  aProperty.Name = "IsSoundEnabled";
960  Sequence<Any> aValues (2);
961  aValues[0] <<= xView;
962  aValues[1] <<= false;
963  aProperty.Value <<= aValues;
964  mxSlideShow->setProperty(aProperty);
965 }
966 
967 } // end of namespace ::sd::presenter
968 
969 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
cppu::WeakComponentImplHelper< css::presentation::XSlideShowView, css::awt::XPaintListener, css::awt::XMouseListener, css::awt::XMouseMotionListener, css::awt::XWindowListener, css::drawing::framework::XView, css::drawing::XDrawView > PresenterSlideShowViewInterfaceBase
css::uno::Reference< css::rendering::XCanvas > mxViewCanvas
virtual css::uno::Reference< css::rendering::XSpriteCanvas > SAL_CALL getCanvas() override
Reference< rendering::XCanvas > mxCanvas
css::uno::Reference< css::awt::XWindow > CreateViewWindow(const css::uno::Reference< css::awt::XWindow > &rxParentWindow) const
Create the window into which the slide show will render its content.
std::shared_ptr< FontDescriptor > SharedFontDescriptor
PresenterSlideShowView(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::drawing::framework::XResourceId > &rxViewId, const css::uno::Reference< css::frame::XController > &rxController, const ::rtl::Reference< PresenterController > &rpPresenterController)
virtual void SAL_CALL setMouseCursor(::sal_Int16 nPointerShape) override
css::uno::Reference< css::frame::XController > mxController
virtual void SAL_CALL mouseDragged(const css::awt::MouseEvent &rEvent) override
osl::Mutex m_aMutex
SharedBitmapDescriptor mpBackground
css::uno::Reference< css::drawing::XPresenterHelper > mxPresenterHelper
css::uno::Reference< css::rendering::XCanvas > mxCanvas
css::uno::Reference< css::rendering::XPolyPolygon2D > mxBackgroundPolygon2
virtual css::geometry::IntegerSize2D SAL_CALL getTranslationOffset() override
virtual void SAL_CALL mouseMoved(const css::awt::MouseEvent &rEvent) override
virtual void SAL_CALL removeTransformationChangedListener(const css::uno::Reference< css::util::XModifyListener > &xListener) override
void SAL_CALL disposeAndClear(const css::lang::EventObject &rEvt)
virtual css::uno::Reference< css::drawing::XDrawPage > SAL_CALL getCurrentPage() override
Reference< drawing::XPresenterHelper > mxPresenterHelper
OInterfaceContainerHelper *SAL_CALL getContainer(const keyType &key) const
This class gives access to the configuration.
virtual void SAL_CALL windowShown(const css::lang::EventObject &rEvent) override
css::uno::Reference< css::drawing::XDrawPage > mxCurrentSlide
virtual css::awt::Rectangle SAL_CALL getCanvasArea() override
virtual void SAL_CALL disposing() override
virtual void SAL_CALL mouseEntered(const css::awt::MouseEvent &rEvent) override
css::uno::Reference< css::drawing::framework::XResourceId > mxViewId
virtual void SAL_CALL addMouseMotionListener(const css::uno::Reference< css::awt::XMouseMotionListener > &xListener) override
css::uno::Reference< css::rendering::XCanvas > CreateViewCanvas(const css::uno::Reference< css::awt::XWindow > &rxWindow) const
void addListener(const keyType &key, const css::uno::Reference< css::uno::XInterface > &r)
css::uno::Reference< css::lang::XComponent > xComponent
virtual void SAL_CALL addMouseListener(const css::uno::Reference< css::awt::XMouseListener > &xListener) override
virtual void SAL_CALL setCurrentPage(const css::uno::Reference< css::drawing::XDrawPage > &rxSlide) override
css::uno::Reference< css::uno::XComponentContext > mxComponentContext
void removeListener(const keyType &key, const css::uno::Reference< css::uno::XInterface > &r)
void PaintEndSlide(const css::awt::Rectangle &rRepaintBox)
virtual void SAL_CALL mousePressed(const css::awt::MouseEvent &rEvent) override
virtual void SAL_CALL windowResized(const css::awt::WindowEvent &rEvent) override
virtual void SAL_CALL removePaintListener(const css::uno::Reference< css::awt::XPaintListener > &xListener) override
virtual void DeactivatePresenterView() override
Called when the view is put into a cache.
void PaintInnerWindow(const css::awt::PaintEvent &rEvent)
css::uno::Reference< css::presentation::XSlideShowController > GetSlideShowController(const css::uno::Reference< css::frame::XController > &rxController)
Return the slide show controller of a running presentation that has the same document as the given fr...
virtual void SAL_CALL removeMouseMotionListener(const css::uno::Reference< css::awt::XMouseMotionListener > &xListener) override
virtual void SAL_CALL addTransformationChangedListener(const css::uno::Reference< css::util::XModifyListener > &xListener) override
css::uno::Any GetConfigurationNode(const OUString &rsPathToNode)
Return a configuration node below the root of the called object.
unsigned char sal_Bool
virtual void SAL_CALL windowHidden(const css::lang::EventObject &rEvent) override
virtual void SAL_CALL windowPaint(const css::awt::PaintEvent &rEvent) override
virtual void SAL_CALL mouseExited(const css::awt::MouseEvent &rEvent) override
::cppu::OBroadcastHelper maBroadcaster
This broadcast helper is used to notify listeners registered to a SlideShowView object.
virtual void SAL_CALL removeMouseListener(const css::uno::Reference< css::awt::XMouseListener > &xListener) override
virtual void SAL_CALL windowMoved(const css::awt::WindowEvent &rEvent) override
static css::uno::Reference< css::rendering::XPolyPolygon2D > CreatePolygon(const css::awt::Rectangle &rBox, const css::uno::Reference< css::rendering::XGraphicDevice > &rxDevice)
virtual void SAL_CALL addPaintListener(const css::uno::Reference< css::awt::XPaintListener > &xListener) override
virtual css::uno::Reference< css::drawing::framework::XResourceId > SAL_CALL getResourceId() override
double mnPageAspectRatio
Aspect ratio of the current slide.
::rtl::Reference< PresenterController > mpPresenterController
css::uno::Reference< css::awt::XPointer > mxPointer
css::uno::Reference< css::presentation::XSlideShowController > mxSlideShowController
virtual sal_Bool SAL_CALL isAnchorOnly() override
rtl::Reference< PresenterController > mpPresenterController
css::uno::Reference< css::drawing::framework::XPane > mxTopPane
virtual void SAL_CALL mouseReleased(const css::awt::MouseEvent &rEvent) override
virtual css::geometry::AffineMatrix2D SAL_CALL getTransformation() override
css::uno::Reference< css::awt::XWindow > mxWindow
static void SetDeviceColor(css::rendering::RenderState &rRenderState, const css::util::Color aColor)
std::shared_ptr< PaneDescriptor > SharedPaneDescriptor
virtual void ReleaseView() override
Called before the view is disposed.
void PaintOuterWindow(const css::awt::Rectangle &rRepaintBox)
Reference< XSingleServiceFactory > xFactory
void notifyEach(void(SAL_CALL ListenerT::*NotificationMethod)(const EventT &), const EventT &Event)
css::uno::Reference< css::uno::XComponentContext > mxComponentContext
AnyEventRef aEvent
css::uno::Reference< css::awt::XWindow > mxViewWindow
css::uno::Reference< css::rendering::XPolyPolygon2D > mxBackgroundPolygon1
css::uno::Reference< css::presentation::XSlideShow > mxSlideShow