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