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  maLayoutListeners(),
71  mbIsMouseClickPending(false)
72 {
73 
74 }
75 
77 {
78 }
79 
81 {
83 
84  SetParentPane(nullptr);
85 
87  if (xComponent.is())
88  xComponent->dispose();
89  mxPaneBorderManager = nullptr;
90 
91  for (const auto& rxPane : mpPaneContainer->maPanes)
92  {
93  if (rxPane->mxBorderWindow.is())
94  {
95  rxPane->mxBorderWindow->removeWindowListener(this);
96  rxPane->mxBorderWindow->removeFocusListener(this);
97  rxPane->mxBorderWindow->removeMouseListener(this);
98  }
99  }
100 }
101 
103  const Reference<drawing::framework::XPane>& rxPane)
104 {
105  if (mxParentWindow.is())
106  {
107  mxParentWindow->removeWindowListener(this);
108  mxParentWindow->removePaintListener(this);
109  mxParentWindow->removeMouseListener(this);
110  mxParentWindow->removeFocusListener(this);
111  }
112  mxParentWindow = nullptr;
113  mxParentCanvas = nullptr;
114 
115  if (rxPane.is())
116  {
117  mxParentWindow = rxPane->getWindow();
118  mxParentCanvas = rxPane->getCanvas();
119  }
120  else
121  {
122  mxParentWindow = nullptr;
123  }
124 
125  if (mxParentWindow.is())
126  {
127  mxParentWindow->addWindowListener(this);
128  mxParentWindow->addPaintListener(this);
129  mxParentWindow->addMouseListener(this);
130  mxParentWindow->addFocusListener(this);
131 
132  // We paint our own background, make that of the parent window transparent.
133  Reference<awt::XWindowPeer> xPeer (mxParentWindow, UNO_QUERY);
134  if (xPeer.is())
135  xPeer->setBackground(util::Color(0xff000000));
136  }
137 }
138 
139 void PresenterWindowManager::SetTheme (const std::shared_ptr<PresenterTheme>& rpTheme)
140 {
141  mpTheme = rpTheme;
142 
143  // Get background bitmap or background color from the theme.
144 
145  if (mpTheme != nullptr)
146  {
147  mpBackgroundBitmap = mpTheme->GetBitmap(OUString(), "Background");
148  }
149 }
150 
151 void PresenterWindowManager::NotifyViewCreation (const Reference<XView>& rxView)
152 {
154  mpPaneContainer->FindPaneId(rxView->getResourceId()->getAnchor()));
155  OSL_ASSERT(pDescriptor.get() != nullptr);
156  if (pDescriptor.get() != nullptr)
157  {
158  Layout();
159 
160  mpPresenterController->GetPaintManager()->Invalidate(
161  pDescriptor->mxContentWindow,
162  sal_Int16(awt::InvalidateStyle::TRANSPARENT
163  | awt::InvalidateStyle::CHILDREN));
164  }
165 }
166 
168  const OUString& rsPaneURL,
169  const double nX,
170  const double nY,
171  const double nWidth,
172  const double nHeight)
173 {
175  mpPaneContainer->FindPaneURL(rsPaneURL));
176  if (pDescriptor.get() != nullptr)
177  {
178  if (pDescriptor->mxBorderWindow.is())
179  pDescriptor->mxBorderWindow->setPosSize(
180  ::sal::static_int_cast<sal_Int32>(nX),
181  ::sal::static_int_cast<sal_Int32>(nY),
182  ::sal::static_int_cast<sal_Int32>(nWidth),
183  ::sal::static_int_cast<sal_Int32>(nHeight),
184  awt::PosSize::POSSIZE);
185  }
186 }
187 
189  const ::rtl::Reference<PresenterPaneBorderPainter>& rPainter)
190 {
191  mpPaneBorderPainter = rPainter;
192 }
193 
194 //----- XWindowListener -------------------------------------------------------
195 
196 void SAL_CALL PresenterWindowManager::windowResized (const awt::WindowEvent& rEvent)
197 {
198  ThrowIfDisposed();
199  if (rEvent.Source == mxParentWindow)
200  {
201  Layout();
202  }
203  else
204  {
205  Reference<awt::XWindow> xWindow (rEvent.Source,UNO_QUERY);
206  if (xWindow.is())
207  {
208  UpdateWindowSize(xWindow);
209 
210  // Make sure the background of a transparent window is painted.
211  mpPresenterController->GetPaintManager()->Invalidate(mxParentWindow);
212  }
213  }
214 }
215 
216 void SAL_CALL PresenterWindowManager::windowMoved (const awt::WindowEvent& rEvent)
217 {
218  ThrowIfDisposed();
219  if (rEvent.Source != mxParentWindow)
220  {
221  Reference<awt::XWindow> xWindow (rEvent.Source,UNO_QUERY);
222  UpdateWindowSize(xWindow);
223 
224  // Make sure the background of a transparent window is painted.
225  mpPresenterController->GetPaintManager()->Invalidate(xWindow);
226  }
227 }
228 
229 void SAL_CALL PresenterWindowManager::windowShown (const lang::EventObject&) {}
230 
231 void SAL_CALL PresenterWindowManager::windowHidden (const lang::EventObject&) {}
232 
233 //----- XPaintListener --------------------------------------------------------
234 
235 void SAL_CALL PresenterWindowManager::windowPaint (const awt::PaintEvent& rEvent)
236 {
237  ThrowIfDisposed();
238 
239  if ( ! mxParentWindow.is())
240  return;
241  if ( ! mxParentCanvas.is())
242  return;
243 
244  if (mpTheme == nullptr)
245  return;
246 
247  try
248  {
249  if (mbIsLayoutPending)
250  Layout();
251  PaintBackground(rEvent.UpdateRect);
252  PaintChildren(rEvent);
253  }
254  catch (RuntimeException&)
255  {
256  OSL_FAIL("paint failed!");
257  }
258 }
259 
260 //----- XMouseListener --------------------------------------------------------
261 
262 void SAL_CALL PresenterWindowManager::mousePressed (const css::awt::MouseEvent&)
263 {
264  if (!mbIsSlideSorterActive) // tdf#127921
265  mbIsMouseClickPending = true;
266 }
267 
268 void SAL_CALL PresenterWindowManager::mouseReleased (const css::awt::MouseEvent& rEvent)
269 {
271  {
272  mbIsMouseClickPending = false;
273  mpPresenterController->HandleMouseClick(rEvent);
274  }
275 }
276 
277 void SAL_CALL PresenterWindowManager::mouseEntered (const css::awt::MouseEvent&)
278 {
279  mbIsMouseClickPending = false;
280 }
281 
282 void SAL_CALL PresenterWindowManager::mouseExited (const css::awt::MouseEvent&)
283 {
284  mbIsMouseClickPending = false;
285 }
286 
287 //----- XFocusListener --------------------------------------------------------
288 
289 void SAL_CALL PresenterWindowManager::focusGained (const css::awt::FocusEvent& /*rEvent*/)
290 {
291  ThrowIfDisposed();
292 }
293 
294 void SAL_CALL PresenterWindowManager::focusLost (const css::awt::FocusEvent&)
295 {
296  ThrowIfDisposed();
297 }
298 
299 //----- XEventListener --------------------------------------------------------
300 
301 void SAL_CALL PresenterWindowManager::disposing (const lang::EventObject& rEvent)
302 {
303  if (rEvent.Source == mxParentWindow)
304  mxParentWindow = nullptr;
305 }
306 
307 
308 void PresenterWindowManager::PaintChildren (const awt::PaintEvent& rEvent) const
309 {
310  // Call windowPaint on all children that lie in or touch the
311  // update rectangle.
312  for (const auto& rxPane : mpPaneContainer->maPanes)
313  {
314  try
315  {
316  // Make sure that the pane shall and can be painted.
317  if ( ! rxPane->mbIsActive)
318  continue;
319  if (rxPane->mbIsSprite)
320  continue;
321  if ( ! rxPane->mxPane.is())
322  continue;
323  if ( ! rxPane->mxBorderWindow.is())
324  continue;
325  Reference<awt::XWindow> xBorderWindow (rxPane->mxBorderWindow);
326  if ( ! xBorderWindow.is())
327  continue;
328 
329  // Get the area in which the border of the pane has to be painted.
330  const awt::Rectangle aBorderBox (xBorderWindow->getPosSize());
331  const awt::Rectangle aBorderUpdateBox(
333  rEvent.UpdateRect,
334  aBorderBox));
335  if (aBorderUpdateBox.Width<=0 || aBorderUpdateBox.Height<=0)
336  continue;
337 
338  const awt::Rectangle aLocalBorderUpdateBox(
340  aBorderUpdateBox,
341  -aBorderBox.X,
342  -aBorderBox.Y));
343 
344  // Invalidate the area of the content window.
345  mpPresenterController->GetPaintManager()->Invalidate(
346  xBorderWindow,
347  aLocalBorderUpdateBox,
348  sal_Int16(awt::InvalidateStyle::CHILDREN
349  | awt::InvalidateStyle::NOTRANSPARENT));
350  }
351  catch (RuntimeException&)
352  {
353  OSL_FAIL("paint children failed!");
354  }
355  }
356 }
357 
359 {
360  OSL_ASSERT(mpPresenterController.get() != nullptr);
361 
362  if (meLayoutMode == eMode
364  && !mbIsHelpViewActive)
365  return;
366 
367  meLayoutMode = eMode;
368  mbIsSlideSorterActive = false;
369  mbIsHelpViewActive = false;
370 
371  mpPresenterController->RequestViews(
375  Layout();
377 }
378 
380 {
381  if (mbIsSlideSorterActive == bIsActive)
382  return;
383 
384  mbIsSlideSorterActive = bIsActive;
386  mbIsHelpViewActive = false;
388 
389  mpPresenterController->RequestViews(
393  Layout();
395 }
396 
398 {
399  if (mbIsHelpViewActive == bIsActive)
400  return;
401 
402  mbIsHelpViewActive = bIsActive;
403  if (mbIsHelpViewActive)
404  mbIsSlideSorterActive = false;
406 
407  mpPresenterController->RequestViews(
411  Layout();
413 }
414 
416 {
417  switch (eMode)
418  {
419  case VM_Standard:
420  SetSlideSorterState(false);
421  SetHelpViewState(false);
423  break;
424 
425  case VM_Notes:
426  SetSlideSorterState(false);
427  SetHelpViewState(false);
429  break;
430 
431  case VM_SlideOverview:
432  SetHelpViewState(false);
433  SetSlideSorterState(true);
434  break;
435 
436  case VM_Help:
437  SetHelpViewState(true);
438  SetSlideSorterState(false);
439  break;
440  }
441 
442  StoreViewMode(eMode);
443 }
444 
446 {
447  if (mbIsHelpViewActive)
448  return VM_Help;
449  else if (mbIsSlideSorterActive)
450  return VM_SlideOverview;
451  else if (meLayoutMode == LM_Notes)
452  return VM_Notes;
453  else
454  return VM_Standard;
455 }
456 
458 {
459  sal_Int32 nMode (0);
460  PresenterConfigurationAccess aConfiguration (
462  "/org.openoffice.Office.PresenterScreen/",
464  aConfiguration.GetConfigurationNode("Presenter/InitialViewMode") >>= nMode;
465  switch (nMode)
466  {
467  default:
468  case 0:
470  break;
471 
472  case 1:
474  break;
475 
476  case 2:
478  break;
479  }
480 }
481 
483 {
484  try
485  {
486  PresenterConfigurationAccess aConfiguration (
488  "/org.openoffice.Office.PresenterScreen/",
490  aConfiguration.GoToChild("Presenter");
491  Any aValue;
492  switch (eViewMode)
493  {
494  default:
495  case VM_Standard:
496  aValue <<= sal_Int32(0);
497  break;
498 
499  case VM_Notes:
500  aValue <<= sal_Int32(1);
501  break;
502 
503  case VM_SlideOverview:
504  aValue <<= sal_Int32(2);
505  break;
506  }
507 
508  aConfiguration.SetProperty ("InitialViewMode", aValue);
509  aConfiguration.CommitChanges();
510  }
511  catch (Exception&)
512  {
513  }
514 }
515 
517  const Reference<document::XEventListener>& rxListener)
518 {
519  maLayoutListeners.push_back(rxListener);
520 }
521 
523  const Reference<document::XEventListener>& rxListener)
524 {
525  // Assume that there are no multiple entries.
526  auto iListener = std::find(maLayoutListeners.begin(), maLayoutListeners.end(), rxListener);
527  if (iListener != maLayoutListeners.end())
528  maLayoutListeners.erase(iListener);
529 }
530 
532 {
533  if (!mxParentWindow.is() || mbIsLayouting)
534  return;
535 
536  mbIsLayoutPending = false;
537  mbIsLayouting = true;
538  mxScaledBackgroundBitmap = nullptr;
539  mxClipPolygon = nullptr;
540 
541  try
542  {
545  else if (mbIsHelpViewActive)
546  LayoutHelpMode();
547  else
548  switch (meLayoutMode)
549  {
550  case LM_Standard:
551  default:
553  break;
554 
555  case LM_Notes:
556  LayoutNotesMode();
557  break;
558  }
559  }
560  catch (Exception&)
561  {
562  OSL_ASSERT(false);
563  throw;
564  }
565 
566  mbIsLayouting = false;
567 }
568 
570 {
571  awt::Rectangle aBox = mxParentWindow->getPosSize();
572 
573  const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
574  const double nGap (20);
575  const double nHorizontalSlideDivide (aBox.Width / nGoldenRatio);
576  double nSlidePreviewTop (0);
577 
578 
579  // For the current slide view calculate the outer height from the outer
580  // width. This takes into account the slide aspect ratio and thus has to
581  // go over the inner pane size.
584  if (pPane.get() != nullptr)
585  {
586  const awt::Size aCurrentSlideOuterBox(CalculatePaneSize(
587  nHorizontalSlideDivide - 1.5*nGap,
589  nSlidePreviewTop = (aBox.Height - aCurrentSlideOuterBox.Height) / 2;
590  double Temp=nGap;
593  Temp=aBox.Width - aCurrentSlideOuterBox.Width - nGap;
596  Temp,
597  nSlidePreviewTop,
598  aCurrentSlideOuterBox.Width,
599  aCurrentSlideOuterBox.Height);
600  }
601 
602  // For the next slide view calculate the outer height from the outer
603  // width. This takes into account the slide aspect ratio and thus has to
604  // go over the inner pane size.
606  if (pPane.get() != nullptr)
607  {
608  const awt::Size aNextSlideOuterBox (CalculatePaneSize(
609  aBox.Width - nHorizontalSlideDivide - 1.5*nGap,
611  double Temp=aBox.Width - aNextSlideOuterBox.Width - nGap;
614  Temp=nGap;
617  Temp,
618  nSlidePreviewTop,
619  aNextSlideOuterBox.Width,
620  aNextSlideOuterBox.Height);
621  }
622 
623  LayoutToolBar();
624 }
625 
627 {
628  awt::Rectangle aBox = mxParentWindow->getPosSize();
629 
630  const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());
631 
632  const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
633  const double nGap (20);
634  const double nPrimaryWidth (aBox.Width / nGoldenRatio);
635  const double nSecondaryWidth (aBox.Width - nPrimaryWidth);
636  const double nTertiaryWidth (nSecondaryWidth / nGoldenRatio);
637  double nSlidePreviewTop (0);
638  double nNotesViewBottom (aToolBarBox.Y1 - nGap);
640 
641 
642  // The notes view has no fixed aspect ratio.
645  if (pPane.get() != nullptr)
646  {
647  const geometry::RealSize2D aNotesViewOuterSize(
648  nPrimaryWidth - 1.5*nGap + 0.5,
649  nNotesViewBottom);
650  nSlidePreviewTop = (aBox.Height
651  - aToolBarBox.Y2 + aToolBarBox.Y1 - aNotesViewOuterSize.Height) / 2;
653  double Temp=aBox.Width - aNotesViewOuterSize.Width - nGap;
655  Temp=nGap;
658  Temp,
659  nSlidePreviewTop,
660  aNotesViewOuterSize.Width,
661  aNotesViewOuterSize.Height);
662  nNotesViewBottom = nSlidePreviewTop + aNotesViewOuterSize.Height;
663  }
664 
665  // For the current slide view calculate the outer height from the outer
666  // width. This takes into account the slide aspect ratio and thus has to
667  // go over the inner pane size.
669  if (pPane.get() != nullptr)
670  {
671  const awt::Size aCurrentSlideOuterBox(CalculatePaneSize(
672  nSecondaryWidth - 1.5*nGap,
675  double Temp=nGap;
677  Temp=aBox.Width - aCurrentSlideOuterBox.Width - nGap;
680  Temp,
681  nSlidePreviewTop,
682  aCurrentSlideOuterBox.Width,
683  aCurrentSlideOuterBox.Height);
684  }
685 
686  // For the next slide view calculate the outer height from the outer
687  // width. This takes into account the slide aspect ratio and thus has to
688  // go over the inner pane size.
690  if (pPane.get() == nullptr)
691  return;
692 
693  const awt::Size aNextSlideOuterBox (CalculatePaneSize(
694  nTertiaryWidth,
697  double Temp=nGap;
699  Temp=aBox.Width - aNextSlideOuterBox.Width - nGap;
702  Temp,
703  nNotesViewBottom - aNextSlideOuterBox.Height,
704  aNextSlideOuterBox.Width,
705  aNextSlideOuterBox.Height);
706 
707 
708 }
709 
711 {
712  const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());
713 
714  awt::Rectangle aWindowBox = mxParentWindow->getPosSize();
715  const double nGap (20);
718  nGap,
719  nGap,
720  aWindowBox.Width - 2*nGap,
721  aToolBarBox.Y1 - 2*nGap);
722 }
723 
725 {
726  const geometry::RealRectangle2D aToolBarBox (LayoutToolBar());
727 
728  awt::Rectangle aWindowBox = mxParentWindow->getPosSize();
729  const double nGap (20);
730  const double nGoldenRatio ((1 + sqrt(5.0)) / 2);
731  const double nWidth = ::std::min(aWindowBox.Width - 2*nGap, aWindowBox.Width/nGoldenRatio);
734  (aWindowBox.Width - nWidth)/2,
735  nGap,
736  nWidth,
737  aToolBarBox.Y1 - 2*nGap);
738 }
739 
740 geometry::RealRectangle2D PresenterWindowManager::LayoutToolBar()
741 {
742  double nToolBarWidth (400);
743  double nToolBarHeight (80);
744 
745  // Get access to the tool bar.
748  if (pDescriptor.get() != nullptr)
749  {
750  PresenterToolBarView* pToolBarView
751  = dynamic_cast<PresenterToolBarView*>(pDescriptor->mxView.get());
752  if (pToolBarView != nullptr && pToolBarView->GetPresenterToolBar().is())
753  {
754  geometry::RealSize2D aSize (pToolBarView->GetPresenterToolBar()->GetMinimalSize());
755 
756  if (mpPaneBorderPainter.is())
757  {
758  const awt::Rectangle aBox (mpPaneBorderPainter->addBorder (
760  awt::Rectangle(
761  0,
762  0,
763  PresenterGeometryHelper::Round(aSize.Width),
764  PresenterGeometryHelper::Round(aSize.Height)),
765  css::drawing::framework::BorderType_TOTAL_BORDER));
766 
767  nToolBarWidth = aBox.Width;
768  nToolBarHeight = aBox.Height;
769  }
770  else
771  {
772  nToolBarWidth = aSize.Width + 20;
773  nToolBarHeight = aSize.Height + 10;
774  }
775  }
776  }
777 
778  const awt::Rectangle aBox = mxParentWindow->getPosSize();
779  const double nToolBarX ((aBox.Width - nToolBarWidth) / 2);
780  const double nToolBarY (aBox.Height - nToolBarHeight);
783  nToolBarX,
784  nToolBarY,
785  nToolBarWidth,
786  nToolBarHeight);
787 
788  return geometry::RealRectangle2D(
789  nToolBarX,
790  nToolBarY,
791  nToolBarX + nToolBarWidth - 1,
792  nToolBarY + nToolBarHeight - 1);
793 }
794 
796  const double nOuterWidth,
797  const OUString& rsPaneURL)
798 {
799  // Calculate the inner width by removing the pane border.
800  awt::Rectangle aInnerBox (mpPaneBorderPainter->RemoveBorder (
801  rsPaneURL,
802  awt::Rectangle(0,0,
803  sal_Int32(nOuterWidth+0.5),sal_Int32(nOuterWidth)),
804  drawing::framework::BorderType_TOTAL_BORDER));
805 
806  // Calculate the inner height with the help of the slide aspect ratio.
807  const double nCurrentSlideInnerHeight (
808  aInnerBox.Width / mpPresenterController->GetSlideAspectRatio());
809 
810  // Add the pane border to get the outer box.
811  awt::Rectangle aOuterBox (mpPaneBorderPainter->AddBorder (
812  rsPaneURL,
813  awt::Rectangle(0,0,
814  aInnerBox.Width,sal_Int32(nCurrentSlideInnerHeight+0.5)),
815  drawing::framework::BorderType_TOTAL_BORDER));
816 
817  return awt::Size(aOuterBox.Width, aOuterBox.Height);
818 }
819 
821 {
822  document::EventObject aEvent;
823  aEvent.Source = Reference<XInterface>(static_cast<XWeak*>(this));
824 
826  for (const auto& rxListener : aContainerCopy)
827  {
828  if (rxListener.is())
829  {
830  try
831  {
832  rxListener->notifyEvent(aEvent);
833  }
834  catch (lang::DisposedException&)
835  {
836  RemoveLayoutListener(rxListener);
837  }
838  catch (RuntimeException&)
839  {
840  }
841  }
842  }
843 }
844 
846 {
847  lang::EventObject aEvent;
848  aEvent.Source = static_cast<XWeak*>(this);
849 
850  LayoutListenerContainer aContainer;
851  aContainer.swap(maLayoutListeners);
852  for (auto& rxListener : aContainer)
853  {
854  if (rxListener.is())
855  {
856  try
857  {
858  rxListener->disposing(aEvent);
859  }
860  catch (lang::DisposedException&)
861  {
862  }
863  catch (RuntimeException&)
864  {
865  }
866  }
867  }
868 }
869 
870 void PresenterWindowManager::UpdateWindowSize (const Reference<awt::XWindow>& rxBorderWindow)
871 {
873  mpPaneContainer->FindBorderWindow(rxBorderWindow));
874  if (pDescriptor.get() != nullptr)
875  {
876  mxClipPolygon = nullptr;
877 
878  // ToTop is called last because it may invalidate the iterator.
879  if ( ! mbIsLayouting)
880  mpPaneContainer->ToTop(pDescriptor);
881  }
882 }
883 
884 void PresenterWindowManager::PaintBackground (const awt::Rectangle& rUpdateBox)
885 {
886  if ( ! mxParentWindow.is())
887  return;
888 
889  Reference<rendering::XGraphicDevice> xDevice (mxParentCanvas->getDevice());
890  if ( ! xDevice.is())
891  return;
892 
893  // Create a polygon for the background and for clipping.
894  Reference<rendering::XPolyPolygon2D> xBackgroundPolygon (
896  if ( ! mxClipPolygon.is())
898 
899  // Create View- and RenderState structs.
900  const rendering::ViewState aViewState(
901  geometry::AffineMatrix2D(1,0,0, 0,1,0),
902  PresenterGeometryHelper::CreatePolygon(rUpdateBox, xDevice));
903  rendering::RenderState aRenderState (
904  geometry::AffineMatrix2D(1,0,0, 0,1,0),
906  Sequence<double>(4),
907  rendering::CompositeOperation::SOURCE);
908 
909  // Paint the background.
910  if (mpBackgroundBitmap.get() == nullptr)
911  return;
912 
914 
915  if (mxScaledBackgroundBitmap.is())
916  {
917  Sequence<rendering::Texture> aTextures (1);
918  const geometry::IntegerSize2D aBitmapSize(mxScaledBackgroundBitmap->getSize());
919  aTextures[0] = rendering::Texture (
920  geometry::AffineMatrix2D(
921  aBitmapSize.Width,0,0,
922  0,aBitmapSize.Height,0),
923  1,
924  0,
926  nullptr,
927  nullptr,
928  rendering::StrokeAttributes(),
929  rendering::TexturingMode::REPEAT,
930  rendering::TexturingMode::REPEAT);
931 
932  mxParentCanvas->fillTexturedPolyPolygon(
933  xBackgroundPolygon,
934  aViewState,
935  aRenderState,
936  aTextures);
937  }
938  else
939  {
940  const util::Color aBackgroundColor (mpBackgroundBitmap->maReplacementColor);
941  aRenderState.DeviceColor[0] = ((aBackgroundColor >> 16) & 0x0ff) / 255.0;
942  aRenderState.DeviceColor[1] = ((aBackgroundColor >> 8) & 0x0ff) / 255.0;
943  aRenderState.DeviceColor[2] = ((aBackgroundColor >> 0) & 0x0ff) / 255.0;
944  aRenderState.DeviceColor[3] = ((aBackgroundColor >> 24) & 0x0ff) / 255.0;
945  mxParentCanvas->fillPolyPolygon(
946  xBackgroundPolygon,
947  aViewState,
948  aRenderState);
949  }
950 }
951 
953 {
954  if ( mxScaledBackgroundBitmap.is())
955  return;
956 
957  Reference<rendering::XBitmap> xBitmap (mpBackgroundBitmap->GetNormalBitmap());
958  if (!xBitmap.is())
959  return;
960 
961  const bool bStretchVertical (mpBackgroundBitmap->meVerticalTexturingMode
963  const bool bStretchHorizontal (mpBackgroundBitmap->meHorizontalTexturingMode
965  if (bStretchHorizontal || bStretchVertical)
966  {
967  geometry::RealSize2D aSize;
968  if (bStretchVertical)
969  aSize.Height = mxParentWindow->getPosSize().Height;
970  else
971  aSize.Height = xBitmap->getSize().Height;
972  if (bStretchHorizontal)
973  aSize.Width = mxParentWindow->getPosSize().Width;
974  else
975  aSize.Width = xBitmap->getSize().Width;
976  mxScaledBackgroundBitmap = xBitmap->getScaledBitmap(aSize, false);
977  }
978  else
979  {
980  mxScaledBackgroundBitmap = xBitmap;
981  }
982 }
983 
984 Reference<rendering::XPolyPolygon2D> PresenterWindowManager::CreateClipPolyPolygon() const
985 {
986  // Create a clip polygon that includes the whole update area but has the
987  // content windows as holes.
988  const sal_Int32 nPaneCount (mpPaneContainer->maPanes.size());
989  ::std::vector<awt::Rectangle> aRectangles;
990  aRectangles.reserve(1+nPaneCount);
991  aRectangles.push_back(mxParentWindow->getPosSize());
992  for (const auto& pDescriptor : mpPaneContainer->maPanes)
993  {
994  if ( ! pDescriptor->mbIsActive)
995  continue;
996  if ( ! pDescriptor->mbIsOpaque)
997  continue;
998  if ( ! pDescriptor->mxBorderWindow.is() || ! pDescriptor->mxContentWindow.is())
999  continue;
1000  Reference<awt::XWindow2> xWindow (pDescriptor->mxBorderWindow, UNO_QUERY);
1001  if (xWindow.is() && ! xWindow->isVisible())
1002  continue;
1003 
1004  const awt::Rectangle aOuterBorderBox (pDescriptor->mxBorderWindow->getPosSize());
1005  awt::Rectangle aInnerBorderBox (pDescriptor->mxContentWindow->getPosSize());
1006  aInnerBorderBox.X += aOuterBorderBox.X;
1007  aInnerBorderBox.Y += aOuterBorderBox.Y;
1008  aRectangles.push_back(aInnerBorderBox);
1009  }
1010  Reference<rendering::XPolyPolygon2D> xPolyPolygon (
1012  aRectangles,
1013  mxParentCanvas->getDevice()));
1014  if (xPolyPolygon.is())
1015  xPolyPolygon->setFillRule(rendering::FillRule_EVEN_ODD);
1016  return xPolyPolygon;
1017 }
1018 
1020 {
1021  mxClipPolygon = nullptr;
1022  mbIsLayoutPending = true;
1023 
1024  mpPresenterController->GetPaintManager()->Invalidate(mxParentWindow);
1025 }
1026 
1028 {
1029  if (rBHelper.bDisposed || rBHelper.bInDispose)
1030  {
1031  throw lang::DisposedException (
1032  "PresenterWindowManager has already been disposed",
1033  const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1034  }
1035 }
1036 
1037 } // end of namespace ::sdext::presenter
1038 
1039 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::rtl::Reference< PresenterController > mpPresenterController
static sal_Int32 Round(const double nValue)
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
::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)
css::uno::Reference< css::lang::XComponent > xComponent
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)
void SetPaneBorderPainter(const ::rtl::Reference< PresenterPaneBorderPainter > &rPainter)
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
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