LibreOffice Module sdext (master)  1
PresenterWindowManager.cxx
Go to the documentation of this file.
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 <vcl/settings.hxx>
22 #include "PresenterController.hxx"
27 #include "PresenterPaneFactory.hxx"
28 #include "PresenterToolBar.hxx"
29 #include "PresenterViewFactory.hxx"
30 #include "PresenterTheme.hxx"
31 #include <com/sun/star/awt/InvalidateStyle.hpp>
32 #include <com/sun/star/awt/PosSize.hpp>
33 #include <com/sun/star/awt/XWindow2.hpp>
34 #include <com/sun/star/awt/XWindowPeer.hpp>
35 #include <com/sun/star/rendering/CompositeOperation.hpp>
36 #include <com/sun/star/rendering/FillRule.hpp>
37 #include <com/sun/star/rendering/Texture.hpp>
38 #include <com/sun/star/rendering/TexturingMode.hpp>
39 #include <math.h>
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 //===== PresenterWindowManager ================================================
48 
50  const Reference<XComponentContext>& rxContext,
51  const ::rtl::Reference<PresenterPaneContainer>& rpPaneContainer,
52  const ::rtl::Reference<PresenterController>& rpPresenterController)
54  mxComponentContext(rxContext),
55  mpPresenterController(rpPresenterController),
56  mxParentWindow(),
57  mxParentCanvas(),
58  mxPaneBorderManager(),
59  mpPaneBorderPainter(),
60  mpPaneContainer(rpPaneContainer),
61  mbIsLayoutPending(true),
62  mbIsLayouting(false),
63  mpTheme(),
64  mpBackgroundBitmap(),
65  mxScaledBackgroundBitmap(),
66  mxClipPolygon(),
67  meLayoutMode(LM_Generic),
68  mbIsSlideSorterActive(false),
69  mbIsHelpViewActive(false),
70  mbisPaused(false),
71  maLayoutListeners(),
72  mbIsMouseClickPending(false)
73 {
74 
75 }
76 
78 {
79 }
80 
82 {
84 
85  SetParentPane(nullptr);
86 
87  Reference<lang::XComponent> xComponent (mxPaneBorderManager, UNO_QUERY);
88  if (xComponent.is())
89  xComponent->dispose();
90  mxPaneBorderManager = nullptr;
91 
92  for (const auto& rxPane : mpPaneContainer->maPanes)
93  {
94  if (rxPane->mxBorderWindow.is())
95  {
96  rxPane->mxBorderWindow->removeWindowListener(this);
97  rxPane->mxBorderWindow->removeFocusListener(this);
98  rxPane->mxBorderWindow->removeMouseListener(this);
99  }
100  }
101 }
102 
104  const Reference<drawing::framework::XPane>& rxPane)
105 {
106  if (mxParentWindow.is())
107  {
108  mxParentWindow->removeWindowListener(this);
109  mxParentWindow->removePaintListener(this);
110  mxParentWindow->removeMouseListener(this);
111  mxParentWindow->removeFocusListener(this);
112  }
113  mxParentWindow = nullptr;
114  mxParentCanvas = nullptr;
115 
116  if (rxPane.is())
117  {
118  mxParentWindow = rxPane->getWindow();
119  mxParentCanvas = rxPane->getCanvas();
120  }
121  else
122  {
123  mxParentWindow = nullptr;
124  }
125 
126  if (mxParentWindow.is())
127  {
128  mxParentWindow->addWindowListener(this);
129  mxParentWindow->addPaintListener(this);
130  mxParentWindow->addMouseListener(this);
131  mxParentWindow->addFocusListener(this);
132 
133  // We paint our own background, make that of the parent window transparent.
134  Reference<awt::XWindowPeer> xPeer (mxParentWindow, UNO_QUERY);
135  if (xPeer.is())
136  xPeer->setBackground(util::Color(0xff000000));
137  }
138 }
139 
140 void PresenterWindowManager::SetTheme (const std::shared_ptr<PresenterTheme>& rpTheme)
141 {
142  mpTheme = rpTheme;
143 
144  // Get background bitmap or background color from the theme.
145 
146  if (mpTheme != nullptr)
147  {
148  mpBackgroundBitmap = mpTheme->GetBitmap(OUString(), "Background");
149  }
150 }
151 
152 void PresenterWindowManager::NotifyViewCreation (const Reference<XView>& rxView)
153 {
155  mpPaneContainer->FindPaneId(rxView->getResourceId()->getAnchor()));
156  OSL_ASSERT(pDescriptor);
157  if (pDescriptor)
158  {
159  Layout();
160 
161  mpPresenterController->GetPaintManager()->Invalidate(
162  pDescriptor->mxContentWindow,
163  sal_Int16(awt::InvalidateStyle::TRANSPARENT
164  | awt::InvalidateStyle::CHILDREN));
165  }
166 }
167 
169  const OUString& rsPaneURL,
170  const double nX,
171  const double nY,
172  const double nWidth,
173  const double nHeight)
174 {
176  mpPaneContainer->FindPaneURL(rsPaneURL));
177  if (pDescriptor)
178  {
179  if (pDescriptor->mxBorderWindow.is())
180  pDescriptor->mxBorderWindow->setPosSize(
181  ::sal::static_int_cast<sal_Int32>(nX),
182  ::sal::static_int_cast<sal_Int32>(nY),
183  ::sal::static_int_cast<sal_Int32>(nWidth),
184  ::sal::static_int_cast<sal_Int32>(nHeight),
185  awt::PosSize::POSSIZE);
186  }
187 }
188 
190  const ::rtl::Reference<PresenterPaneBorderPainter>& rPainter)
191 {
192  mpPaneBorderPainter = rPainter;
193 }
194 
195 //----- XWindowListener -------------------------------------------------------
196 
197 void SAL_CALL PresenterWindowManager::windowResized (const awt::WindowEvent& rEvent)
198 {
199  ThrowIfDisposed();
200  if (rEvent.Source == mxParentWindow)
201  {
202  Layout();
203  }
204  else
205  {
206  Reference<awt::XWindow> xWindow (rEvent.Source,UNO_QUERY);
207  if (xWindow.is())
208  {
209  UpdateWindowSize(xWindow);
210 
211  // Make sure the background of a transparent window is painted.
212  mpPresenterController->GetPaintManager()->Invalidate(mxParentWindow);
213  }
214  }
215 }
216 
217 void SAL_CALL PresenterWindowManager::windowMoved (const awt::WindowEvent& rEvent)
218 {
219  ThrowIfDisposed();
220  if (rEvent.Source != mxParentWindow)
221  {
222  Reference<awt::XWindow> xWindow (rEvent.Source,UNO_QUERY);
223  UpdateWindowSize(xWindow);
224 
225  // Make sure the background of a transparent window is painted.
226  mpPresenterController->GetPaintManager()->Invalidate(xWindow);
227  }
228 }
229 
230 void SAL_CALL PresenterWindowManager::windowShown (const lang::EventObject&) {}
231 
232 void SAL_CALL PresenterWindowManager::windowHidden (const lang::EventObject&) {}
233 
234 //----- XPaintListener --------------------------------------------------------
235 
236 void SAL_CALL PresenterWindowManager::windowPaint (const awt::PaintEvent& rEvent)
237 {
238  ThrowIfDisposed();
239 
240  if ( ! mxParentWindow.is())
241  return;
242  if ( ! mxParentCanvas.is())
243  return;
244 
245  if (mpTheme == nullptr)
246  return;
247 
248  try
249  {
250  if (mbIsLayoutPending)
251  Layout();
252  PaintBackground(rEvent.UpdateRect);
253  PaintChildren(rEvent);
254  }
255  catch (RuntimeException&)
256  {
257  OSL_FAIL("paint failed!");
258  }
259 }
260 
261 //----- XMouseListener --------------------------------------------------------
262 
263 void SAL_CALL PresenterWindowManager::mousePressed (const css::awt::MouseEvent&)
264 {
265  if (!mbIsSlideSorterActive) // tdf#127921
266  mbIsMouseClickPending = true;
267 }
268 
269 void SAL_CALL PresenterWindowManager::mouseReleased (const css::awt::MouseEvent& rEvent)
270 {
272  {
273  mbIsMouseClickPending = false;
274  mpPresenterController->HandleMouseClick(rEvent);
275  }
276 }
277 
278 void SAL_CALL PresenterWindowManager::mouseEntered (const css::awt::MouseEvent&)
279 {
280  mbIsMouseClickPending = false;
281 }
282 
283 void SAL_CALL PresenterWindowManager::mouseExited (const css::awt::MouseEvent&)
284 {
285  mbIsMouseClickPending = false;
286 }
287 
288 //----- XFocusListener --------------------------------------------------------
289 
290 void SAL_CALL PresenterWindowManager::focusGained (const css::awt::FocusEvent& /*rEvent*/)
291 {
292  ThrowIfDisposed();
293 }
294 
295 void SAL_CALL PresenterWindowManager::focusLost (const css::awt::FocusEvent&)
296 {
297  ThrowIfDisposed();
298 }
299 
300 //----- XEventListener --------------------------------------------------------
301 
302 void SAL_CALL PresenterWindowManager::disposing (const lang::EventObject& rEvent)
303 {
304  if (rEvent.Source == mxParentWindow)
305  mxParentWindow = nullptr;
306 }
307 
308 
309 void PresenterWindowManager::PaintChildren (const awt::PaintEvent& rEvent) const
310 {
311  // Call windowPaint on all children that lie in or touch the
312  // update rectangle.
313  for (const auto& rxPane : mpPaneContainer->maPanes)
314  {
315  try
316  {
317  // Make sure that the pane shall and can be painted.
318  if ( ! rxPane->mbIsActive)
319  continue;
320  if (rxPane->mbIsSprite)
321  continue;
322  if ( ! rxPane->mxPane.is())
323  continue;
324  if ( ! rxPane->mxBorderWindow.is())
325  continue;
326  Reference<awt::XWindow> xBorderWindow (rxPane->mxBorderWindow);
327  if ( ! xBorderWindow.is())
328  continue;
329 
330  // Get the area in which the border of the pane has to be painted.
331  const awt::Rectangle aBorderBox (xBorderWindow->getPosSize());
332  const awt::Rectangle aBorderUpdateBox(
334  rEvent.UpdateRect,
335  aBorderBox));
336  if (aBorderUpdateBox.Width<=0 || aBorderUpdateBox.Height<=0)
337  continue;
338 
339  const awt::Rectangle aLocalBorderUpdateBox(
341  aBorderUpdateBox,
342  -aBorderBox.X,
343  -aBorderBox.Y));
344 
345  // Invalidate the area of the content window.
346  mpPresenterController->GetPaintManager()->Invalidate(
347  xBorderWindow,
348  aLocalBorderUpdateBox,
349  sal_Int16(awt::InvalidateStyle::CHILDREN
350  | awt::InvalidateStyle::NOTRANSPARENT));
351  }
352  catch (RuntimeException&)
353  {
354  OSL_FAIL("paint children failed!");
355  }
356  }
357 }
358 
360 {
361  OSL_ASSERT(mpPresenterController);
362 
363  if (meLayoutMode == eMode
365  && !mbIsHelpViewActive)
366  return;
367 
368  meLayoutMode = eMode;
369  mbIsSlideSorterActive = false;
370  mbIsHelpViewActive = false;
371 
372  mpPresenterController->RequestViews(
376  Layout();
378 }
379 
381 {
382  if (mbIsSlideSorterActive == bIsActive)
383  return;
384 
385  mbIsSlideSorterActive = bIsActive;
387  mbIsHelpViewActive = false;
389 
390  mpPresenterController->RequestViews(
394  Layout();
396 }
397 
399 {
400  if (mbIsHelpViewActive == bIsActive)
401  return;
402 
403  mbIsHelpViewActive = bIsActive;
404  if (mbIsHelpViewActive)
405  mbIsSlideSorterActive = false;
407 
408  mpPresenterController->RequestViews(
412  Layout();
414 }
415 
417 {
418  if (mbisPaused == bIsPaused)
419  return;
420 
421  mbisPaused = bIsPaused;
422 
424 }
425 
427 {
428  switch (eMode)
429  {
430  case VM_Standard:
431  SetSlideSorterState(false);
432  SetHelpViewState(false);
434  break;
435 
436  case VM_Notes:
437  SetSlideSorterState(false);
438  SetHelpViewState(false);
440  break;
441 
442  case VM_SlideOverview:
443  SetHelpViewState(false);
444  SetSlideSorterState(true);
445  break;
446 
447  case VM_Help:
448  SetHelpViewState(true);
449  SetSlideSorterState(false);
450  break;
451  }
452 
453  StoreViewMode(eMode);
454 }
455 
457 {
458  if (mbIsHelpViewActive)
459  return VM_Help;
460  else if (mbIsSlideSorterActive)
461  return VM_SlideOverview;
462  else if (meLayoutMode == LM_Notes)
463  return VM_Notes;
464  else
465  return VM_Standard;
466 }
467 
469 {
470  sal_Int32 nMode (0);
471  PresenterConfigurationAccess aConfiguration (
473  "/org.openoffice.Office.PresenterScreen/",
475  aConfiguration.GetConfigurationNode("Presenter/InitialViewMode") >>= nMode;
476  switch (nMode)
477  {
478  default:
479  case 0:
481  break;
482 
483  case 1:
485  break;
486 
487  case 2:
489  break;
490  }
491 }
492 
494 {
495  try
496  {
497  PresenterConfigurationAccess aConfiguration (
499  "/org.openoffice.Office.PresenterScreen/",
501  aConfiguration.GoToChild("Presenter");
502  Any aValue;
503  switch (eViewMode)
504  {
505  default:
506  case VM_Standard:
507  aValue <<= sal_Int32(0);
508  break;
509 
510  case VM_Notes:
511  aValue <<= sal_Int32(1);
512  break;
513 
514  case VM_SlideOverview:
515  aValue <<= sal_Int32(2);
516  break;
517  }
518 
519  aConfiguration.SetProperty ("InitialViewMode", aValue);
520  aConfiguration.CommitChanges();
521  }
522  catch (Exception&)
523  {
524  }
525 }
526 
528  const Reference<document::XEventListener>& rxListener)
529 {
530  maLayoutListeners.push_back(rxListener);
531 }
532 
534  const Reference<document::XEventListener>& rxListener)
535 {
536  // Assume that there are no multiple entries.
537  auto iListener = std::find(maLayoutListeners.begin(), maLayoutListeners.end(), rxListener);
538  if (iListener != maLayoutListeners.end())
539  maLayoutListeners.erase(iListener);
540 }
541 
543 {
544  if (!mxParentWindow.is() || mbIsLayouting)
545  return;
546 
547  mbIsLayoutPending = false;
548  mbIsLayouting = true;
549  mxScaledBackgroundBitmap = nullptr;
550  mxClipPolygon = nullptr;
551 
552  try
553  {
556  else if (mbIsHelpViewActive)
557  LayoutHelpMode();
558  else
559  switch (meLayoutMode)
560  {
561  case LM_Standard:
562  default:
564  break;
565 
566  case LM_Notes:
567  LayoutNotesMode();
568  break;
569  }
570  }
571  catch (Exception&)
572  {
573  OSL_ASSERT(false);
574  throw;
575  }
576 
577  mbIsLayouting = false;
578 }
579 
581 {
582  awt::Rectangle aBox = mxParentWindow->getPosSize();
583 
584  const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
585  const double nGap (20);
586  const double nHorizontalSlideDivide (aBox.Width / nGoldenRatio);
587  double nSlidePreviewTop (0);
588 
589 
590  // For the current slide view calculate the outer height from the outer
591  // width. This takes into account the slide aspect ratio and thus has to
592  // go over the inner pane size.
595  if (pPane)
596  {
597  const awt::Size aCurrentSlideOuterBox(CalculatePaneSize(
598  nHorizontalSlideDivide - 1.5*nGap,
600  nSlidePreviewTop = (aBox.Height - aCurrentSlideOuterBox.Height) / 2;
601  double Temp=nGap;
604  Temp=aBox.Width - aCurrentSlideOuterBox.Width - nGap;
607  Temp,
608  nSlidePreviewTop,
609  aCurrentSlideOuterBox.Width,
610  aCurrentSlideOuterBox.Height);
611  }
612 
613  // For the next slide view calculate the outer height from the outer
614  // width. This takes into account the slide aspect ratio and thus has to
615  // go over the inner pane size.
617  if (pPane)
618  {
619  const awt::Size aNextSlideOuterBox (CalculatePaneSize(
620  aBox.Width - nHorizontalSlideDivide - 1.5*nGap,
622  double Temp=aBox.Width - aNextSlideOuterBox.Width - nGap;
625  Temp=nGap;
628  Temp,
629  nSlidePreviewTop,
630  aNextSlideOuterBox.Width,
631  aNextSlideOuterBox.Height);
632  }
633 
634  LayoutToolBar();
635 }
636 
638 {
639  awt::Rectangle aBox = mxParentWindow->getPosSize();
640 
641  const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());
642 
643  const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
644  const double nGap (20);
645  const double nPrimaryWidth (aBox.Width / nGoldenRatio);
646  const double nSecondaryWidth (aBox.Width - nPrimaryWidth);
647  const double nTertiaryWidth (nSecondaryWidth / nGoldenRatio);
648  double nSlidePreviewTop (0);
649  double nNotesViewBottom (aToolBarBox.Y1 - nGap);
651 
652 
653  // The notes view has no fixed aspect ratio.
656  if (pPane)
657  {
658  const geometry::RealSize2D aNotesViewOuterSize(
659  nPrimaryWidth - 1.5*nGap + 0.5,
660  nNotesViewBottom);
661  nSlidePreviewTop = (aBox.Height
662  - aToolBarBox.Y2 + aToolBarBox.Y1 - aNotesViewOuterSize.Height) / 2;
664  double Temp=aBox.Width - aNotesViewOuterSize.Width - nGap;
666  Temp=nGap;
669  Temp,
670  nSlidePreviewTop,
671  aNotesViewOuterSize.Width,
672  aNotesViewOuterSize.Height);
673  nNotesViewBottom = nSlidePreviewTop + aNotesViewOuterSize.Height;
674  }
675 
676  // For the current slide view calculate the outer height from the outer
677  // width. This takes into account the slide aspect ratio and thus has to
678  // go over the inner pane size.
680  if (pPane)
681  {
682  const awt::Size aCurrentSlideOuterBox(CalculatePaneSize(
683  nSecondaryWidth - 1.5*nGap,
686  double Temp=nGap;
688  Temp=aBox.Width - aCurrentSlideOuterBox.Width - nGap;
691  Temp,
692  nSlidePreviewTop,
693  aCurrentSlideOuterBox.Width,
694  aCurrentSlideOuterBox.Height);
695  }
696 
697  // For the next slide view calculate the outer height from the outer
698  // width. This takes into account the slide aspect ratio and thus has to
699  // go over the inner pane size.
701  if (!pPane)
702  return;
703 
704  const awt::Size aNextSlideOuterBox (CalculatePaneSize(
705  nTertiaryWidth,
708  double Temp=nGap;
710  Temp=aBox.Width - aNextSlideOuterBox.Width - nGap;
713  Temp,
714  nNotesViewBottom - aNextSlideOuterBox.Height,
715  aNextSlideOuterBox.Width,
716  aNextSlideOuterBox.Height);
717 
718 
719 }
720 
722 {
723  const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());
724 
725  awt::Rectangle aWindowBox = mxParentWindow->getPosSize();
726  const double nGap (20);
729  nGap,
730  nGap,
731  aWindowBox.Width - 2*nGap,
732  aToolBarBox.Y1 - 2*nGap);
733 }
734 
736 {
737  const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());
738 
739  awt::Rectangle aWindowBox = mxParentWindow->getPosSize();
740  const double nGap (20);
741  const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
742  const double nWidth = ::std::min(aWindowBox.Width - 2*nGap, aWindowBox.Width/nGoldenRatio);
745  (aWindowBox.Width - nWidth)/2,
746  nGap,
747  nWidth,
748  aToolBarBox.Y1 - 2*nGap);
749 }
750 
751 geometry::RealRectangle2D PresenterWindowManager::LayoutToolBar()
752 {
753  double nToolBarWidth (400);
754  double nToolBarHeight (80);
755 
756  // Get access to the tool bar.
759  if (pDescriptor)
760  {
761  PresenterToolBarView* pToolBarView
762  = dynamic_cast<PresenterToolBarView*>(pDescriptor->mxView.get());
763  if (pToolBarView != nullptr && pToolBarView->GetPresenterToolBar().is())
764  {
765  geometry::RealSize2D aSize (pToolBarView->GetPresenterToolBar()->GetMinimalSize());
766 
767  if (mpPaneBorderPainter.is())
768  {
769  const awt::Rectangle aBox (mpPaneBorderPainter->addBorder (
771  awt::Rectangle(
772  0,
773  0,
774  PresenterGeometryHelper::Round(aSize.Width),
775  PresenterGeometryHelper::Round(aSize.Height)),
776  css::drawing::framework::BorderType_TOTAL_BORDER));
777 
778  nToolBarWidth = aBox.Width;
779  nToolBarHeight = aBox.Height;
780  }
781  else
782  {
783  nToolBarWidth = aSize.Width + 20;
784  nToolBarHeight = aSize.Height + 10;
785  }
786  }
787  }
788 
789  const awt::Rectangle aBox = mxParentWindow->getPosSize();
790  const double nToolBarX ((aBox.Width - nToolBarWidth) / 2);
791  const double nToolBarY (aBox.Height - nToolBarHeight);
794  nToolBarX,
795  nToolBarY,
796  nToolBarWidth,
797  nToolBarHeight);
798 
799  return geometry::RealRectangle2D(
800  nToolBarX,
801  nToolBarY,
802  nToolBarX + nToolBarWidth - 1,
803  nToolBarY + nToolBarHeight - 1);
804 }
805 
807  const double nOuterWidth,
808  const OUString& rsPaneURL)
809 {
810  // Calculate the inner width by removing the pane border.
811  awt::Rectangle aInnerBox (mpPaneBorderPainter->RemoveBorder (
812  rsPaneURL,
813  awt::Rectangle(0,0,
814  sal_Int32(nOuterWidth+0.5),sal_Int32(nOuterWidth)),
815  drawing::framework::BorderType_TOTAL_BORDER));
816 
817  // Calculate the inner height with the help of the slide aspect ratio.
818  const double nCurrentSlideInnerHeight (
819  aInnerBox.Width / mpPresenterController->GetSlideAspectRatio());
820 
821  // Add the pane border to get the outer box.
822  awt::Rectangle aOuterBox (mpPaneBorderPainter->AddBorder (
823  rsPaneURL,
824  awt::Rectangle(0,0,
825  aInnerBox.Width,sal_Int32(nCurrentSlideInnerHeight+0.5)),
826  drawing::framework::BorderType_TOTAL_BORDER));
827 
828  return awt::Size(aOuterBox.Width, aOuterBox.Height);
829 }
830 
832 {
833  document::EventObject aEvent;
834  aEvent.Source = Reference<XInterface>(static_cast<XWeak*>(this));
835 
837  for (const auto& rxListener : aContainerCopy)
838  {
839  if (rxListener.is())
840  {
841  try
842  {
843  rxListener->notifyEvent(aEvent);
844  }
845  catch (lang::DisposedException&)
846  {
847  RemoveLayoutListener(rxListener);
848  }
849  catch (RuntimeException&)
850  {
851  }
852  }
853  }
854 }
855 
857 {
858  lang::EventObject aEvent;
859  aEvent.Source = static_cast<XWeak*>(this);
860 
861  LayoutListenerContainer aContainer;
862  aContainer.swap(maLayoutListeners);
863  for (auto& rxListener : aContainer)
864  {
865  if (rxListener.is())
866  {
867  try
868  {
869  rxListener->disposing(aEvent);
870  }
871  catch (lang::DisposedException&)
872  {
873  }
874  catch (RuntimeException&)
875  {
876  }
877  }
878  }
879 }
880 
881 void PresenterWindowManager::UpdateWindowSize (const Reference<awt::XWindow>& rxBorderWindow)
882 {
884  mpPaneContainer->FindBorderWindow(rxBorderWindow));
885  if (pDescriptor)
886  {
887  mxClipPolygon = nullptr;
888 
889  // ToTop is called last because it may invalidate the iterator.
890  if ( ! mbIsLayouting)
891  mpPaneContainer->ToTop(pDescriptor);
892  }
893 }
894 
895 void PresenterWindowManager::PaintBackground (const awt::Rectangle& rUpdateBox)
896 {
897  if ( ! mxParentWindow.is())
898  return;
899 
900  Reference<rendering::XGraphicDevice> xDevice (mxParentCanvas->getDevice());
901  if ( ! xDevice.is())
902  return;
903 
904  // Create a polygon for the background and for clipping.
905  Reference<rendering::XPolyPolygon2D> xBackgroundPolygon (
907  if ( ! mxClipPolygon.is())
909 
910  // Create View- and RenderState structs.
911  const rendering::ViewState aViewState(
912  geometry::AffineMatrix2D(1,0,0, 0,1,0),
913  PresenterGeometryHelper::CreatePolygon(rUpdateBox, xDevice));
914  rendering::RenderState aRenderState (
915  geometry::AffineMatrix2D(1,0,0, 0,1,0),
917  Sequence<double>(4),
918  rendering::CompositeOperation::SOURCE);
919 
920  // Paint the background.
921  if (!mpBackgroundBitmap)
922  return;
923 
925 
926  if (mxScaledBackgroundBitmap.is())
927  {
928  Sequence<rendering::Texture> aTextures (1);
929  const geometry::IntegerSize2D aBitmapSize(mxScaledBackgroundBitmap->getSize());
930  aTextures[0] = rendering::Texture (
931  geometry::AffineMatrix2D(
932  aBitmapSize.Width,0,0,
933  0,aBitmapSize.Height,0),
934  1,
935  0,
937  nullptr,
938  nullptr,
939  rendering::StrokeAttributes(),
940  rendering::TexturingMode::REPEAT,
941  rendering::TexturingMode::REPEAT);
942 
943  mxParentCanvas->fillTexturedPolyPolygon(
944  xBackgroundPolygon,
945  aViewState,
946  aRenderState,
947  aTextures);
948  }
949  else
950  {
951  const util::Color aBackgroundColor (mpBackgroundBitmap->maReplacementColor);
952  aRenderState.DeviceColor[0] = ((aBackgroundColor >> 16) & 0x0ff) / 255.0;
953  aRenderState.DeviceColor[1] = ((aBackgroundColor >> 8) & 0x0ff) / 255.0;
954  aRenderState.DeviceColor[2] = ((aBackgroundColor >> 0) & 0x0ff) / 255.0;
955  aRenderState.DeviceColor[3] = ((aBackgroundColor >> 24) & 0x0ff) / 255.0;
956  mxParentCanvas->fillPolyPolygon(
957  xBackgroundPolygon,
958  aViewState,
959  aRenderState);
960  }
961 }
962 
964 {
965  if ( mxScaledBackgroundBitmap.is())
966  return;
967 
968  Reference<rendering::XBitmap> xBitmap (mpBackgroundBitmap->GetNormalBitmap());
969  if (!xBitmap.is())
970  return;
971 
972  const bool bStretchVertical (mpBackgroundBitmap->meVerticalTexturingMode
974  const bool bStretchHorizontal (mpBackgroundBitmap->meHorizontalTexturingMode
976  if (bStretchHorizontal || bStretchVertical)
977  {
978  geometry::RealSize2D aSize;
979  if (bStretchVertical)
980  aSize.Height = mxParentWindow->getPosSize().Height;
981  else
982  aSize.Height = xBitmap->getSize().Height;
983  if (bStretchHorizontal)
984  aSize.Width = mxParentWindow->getPosSize().Width;
985  else
986  aSize.Width = xBitmap->getSize().Width;
987  mxScaledBackgroundBitmap = xBitmap->getScaledBitmap(aSize, false);
988  }
989  else
990  {
991  mxScaledBackgroundBitmap = xBitmap;
992  }
993 }
994 
995 Reference<rendering::XPolyPolygon2D> PresenterWindowManager::CreateClipPolyPolygon() const
996 {
997  // Create a clip polygon that includes the whole update area but has the
998  // content windows as holes.
999  const sal_Int32 nPaneCount (mpPaneContainer->maPanes.size());
1000  ::std::vector<awt::Rectangle> aRectangles;
1001  aRectangles.reserve(1+nPaneCount);
1002  aRectangles.push_back(mxParentWindow->getPosSize());
1003  for (const auto& pDescriptor : mpPaneContainer->maPanes)
1004  {
1005  if ( ! pDescriptor->mbIsActive)
1006  continue;
1007  if ( ! pDescriptor->mbIsOpaque)
1008  continue;
1009  if ( ! pDescriptor->mxBorderWindow.is() || ! pDescriptor->mxContentWindow.is())
1010  continue;
1011  Reference<awt::XWindow2> xWindow (pDescriptor->mxBorderWindow, UNO_QUERY);
1012  if (xWindow.is() && ! xWindow->isVisible())
1013  continue;
1014 
1015  const awt::Rectangle aOuterBorderBox (pDescriptor->mxBorderWindow->getPosSize());
1016  awt::Rectangle aInnerBorderBox (pDescriptor->mxContentWindow->getPosSize());
1017  aInnerBorderBox.X += aOuterBorderBox.X;
1018  aInnerBorderBox.Y += aOuterBorderBox.Y;
1019  aRectangles.push_back(aInnerBorderBox);
1020  }
1021  Reference<rendering::XPolyPolygon2D> xPolyPolygon (
1023  aRectangles,
1024  mxParentCanvas->getDevice()));
1025  if (xPolyPolygon.is())
1026  xPolyPolygon->setFillRule(rendering::FillRule_EVEN_ODD);
1027  return xPolyPolygon;
1028 }
1029 
1031 {
1032  mxClipPolygon = nullptr;
1033  mbIsLayoutPending = true;
1034 
1035  mpPresenterController->GetPaintManager()->Invalidate(mxParentWindow);
1036 }
1037 
1039 {
1040  if (rBHelper.bDisposed || rBHelper.bInDispose)
1041  {
1042  throw lang::DisposedException (
1043  "PresenterWindowManager has already been disposed",
1044  const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1045  }
1046 }
1047 
1048 } // end of namespace ::sdext::presenter
1049 
1050 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::rtl::Reference< PresenterController > mpPresenterController
static sal_Int32 Round(const double nValue)
static constexpr OUStringLiteral msCurrentSlidePreviewPaneURL
css::uno::Reference< css::rendering::XCanvas > mxParentCanvas
osl::Mutex m_aMutex
void PaintChildren(const css::awt::PaintEvent &rEvent) const
css::uno::Reference< css::rendering::XBitmap > mxScaledBackgroundBitmap
static constexpr OUStringLiteral msToolBarPaneURL
::std::vector< css::uno::Reference< css::document::XEventListener > > LayoutListenerContainer
virtual void SAL_CALL mouseExited(const css::awt::MouseEvent &rEvent) override
bool mbIsLayouting
This flag is set to while the Layout() method is being executed.
void CommitChanges()
Write any changes that have been made back to the configuration.
void RestoreViewMode()
Restore the layout mode (or slide sorter state) from the configuration.
virtual void SAL_CALL mouseEntered(const css::awt::MouseEvent &rEvent) override
css::uno::Reference< css::uno::XInterface > mxPaneBorderManager
::cppu::WeakComponentImplHelper< css::awt::XWindowListener, css::awt::XPaintListener, css::awt::XMouseListener, css::awt::XFocusListener > PresenterWindowManagerInterfaceBase
virtual void SAL_CALL windowHidden(const css::lang::EventObject &rEvent) override
void SetViewMode(const ViewMode eMode)
The high-level method to switch the view mode.
virtual void SAL_CALL windowResized(const css::awt::WindowEvent &rEvent) override
This class gives access to the configuration.
std::shared_ptr< PresenterTheme > mpTheme
virtual void SAL_CALL focusGained(const css::awt::FocusEvent &rEvent) override
virtual void SAL_CALL mousePressed(const css::awt::MouseEvent &rEvent) override
bool SetProperty(const OUString &rsPropertyName, const css::uno::Any &rValue)
Modify the property child of the currently focused node.
void SetTheme(const std::shared_ptr< PresenterTheme > &rpTheme)
::rtl::Reference< PresenterPaneBorderPainter > mpPaneBorderPainter
void RemoveLayoutListener(const css::uno::Reference< css::document::XEventListener > &rxListener)
PresenterWindowManager(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const ::rtl::Reference< PresenterPaneContainer > &rpPaneContainer, const ::rtl::Reference< PresenterController > &rpPresenterController)
View for the PresenterToolBar.
static css::awt::Rectangle TranslateRectangle(const css::awt::Rectangle &rBox, const sal_Int32 nXOffset, const sal_Int32 nYOffset)
css::uno::Reference< css::uno::XComponentContext > mxComponentContext
virtual void SAL_CALL windowPaint(const css::awt::PaintEvent &rEvent) override
css::geometry::RealRectangle2D LayoutToolBar()
Layout the tool bar and return its outer bounding box.
void SetParentPane(const css::uno::Reference< css::drawing::framework::XPane > &rxPane)
static constexpr OUStringLiteral msNotesPaneURL
void SetPaneBorderPainter(const ::rtl::Reference< PresenterPaneBorderPainter > &rPainter)
static constexpr OUStringLiteral msNextSlidePreviewPaneURL
void AddLayoutListener(const css::uno::Reference< css::document::XEventListener > &rxListener)
css::uno::Any GetConfigurationNode(const OUString &rsPathToNode)
Return a configuration node below the root of the called object.
static bool GetLayoutRTL()
css::uno::Reference< css::rendering::XPolyPolygon2D > mxClipPolygon
const ::rtl::Reference< PresenterToolBar > & GetPresenterToolBar() const
virtual void SAL_CALL windowShown(const css::lang::EventObject &rEvent) override
static css::uno::Reference< css::rendering::XPolyPolygon2D > CreatePolygon(const css::awt::Rectangle &rBox, const css::uno::Reference< css::rendering::XGraphicDevice > &rxDevice)
css::awt::Size CalculatePaneSize(const double nOuterWidth, const OUString &rsPaneURL)
::rtl::Reference< PresenterPaneContainer > mpPaneContainer
virtual void SAL_CALL mouseReleased(const css::awt::MouseEvent &rEvent) override
static css::awt::Rectangle Intersection(const css::awt::Rectangle &rBox1, const css::awt::Rectangle &rBox2)
rtl::Reference< PresenterController > mpPresenterController
void PaintBackground(const css::awt::Rectangle &rUpdateBox)
void SetPanePosSizeAbsolute(const OUString &rsPaneURL, const double nX, const double nY, const double nWidth, const double nHeight)
std::shared_ptr< PaneDescriptor > SharedPaneDescriptor
void UpdateWindowSize(const css::uno::Reference< css::awt::XWindow > &rxBorderWindow)
bool GoToChild(const OUString &rsPathToNode)
Move the focused node to the (possibly indirect) child specified by the given path.
virtual void SAL_CALL focusLost(const css::awt::FocusEvent &rEvent) override
css::uno::Reference< css::awt::XWindow > mxParentWindow
static constexpr OUStringLiteral msHelpViewURL
static constexpr OUStringLiteral msSlideSorterURL
void NotifyLayoutModeChange()
Notify changes of the layout mode and of the slide sorter state.
virtual void SAL_CALL windowMoved(const css::awt::WindowEvent &rEvent) override
css::uno::Reference< css::rendering::XPolyPolygon2D > CreateClipPolyPolygon() const
css::uno::Reference< css::uno::XComponentContext > mxComponentContext
void NotifyViewCreation(const css::uno::Reference< css::drawing::framework::XView > &rxView)
AnyEventRef aEvent