LibreOffice Module sdext (master)  1
PresenterToolBar.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>
21 #include "PresenterToolBar.hxx"
22 
27 #include "PresenterTimer.hxx"
29 
30 #include <cppuhelper/compbase.hxx>
31 #include <com/sun/star/awt/XWindowPeer.hpp>
32 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
33 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
34 #include <com/sun/star/drawing/framework/XPane.hpp>
35 #include <com/sun/star/geometry/AffineMatrix2D.hpp>
36 #include <com/sun/star/rendering/CompositeOperation.hpp>
37 #include <com/sun/star/rendering/RenderState.hpp>
38 #include <com/sun/star/rendering/TextDirection.hpp>
39 #include <com/sun/star/rendering/ViewState.hpp>
40 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
41 #include <com/sun/star/util/Color.hpp>
42 #include <rtl/ustrbuf.hxx>
43 
44 using namespace ::com::sun::star;
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::drawing::framework;
47 
48 namespace sdext::presenter {
49 
50 static const sal_Int32 gnGapSize (20);
51 
52 namespace {
53 
54  class Text
55  {
56  public:
57  Text();
58  Text (
59  const OUString& rsText,
61 
62  void SetText (const OUString& rsText);
63  const OUString& GetText() const;
64  const PresenterTheme::SharedFontDescriptor& GetFont() const;
65 
66  void Paint (
67  const Reference<rendering::XCanvas>& rxCanvas,
68  const rendering::ViewState& rViewState,
69  const awt::Rectangle& rBoundingBox);
70 
71  geometry::RealRectangle2D GetBoundingBox (
72  const Reference<rendering::XCanvas>& rxCanvas);
73 
74  private:
75  OUString msText;
77  };
78 
79  class ElementMode
80  {
81  public:
82  ElementMode();
83  ElementMode(const ElementMode&) = delete;
84  ElementMode& operator=(const ElementMode&) = delete;
85 
87  OUString msAction;
89 
90  void ReadElementMode (
91  const Reference<beans::XPropertySet>& rxProperties,
92  const OUString& rsModeName,
93  std::shared_ptr<ElementMode> const & rpDefaultMode,
95  };
96  typedef std::shared_ptr<ElementMode> SharedElementMode;
97 
98 } // end of anonymous namespace
99 
101 {
102 public:
103  Context() = default;
104  Context(const Context&) = delete;
105  Context& operator=(const Context&) = delete;
106  Reference<drawing::XPresenterHelper> mxPresenterHelper;
107  css::uno::Reference<css::rendering::XCanvas> mxCanvas;
108 };
109 
110 //===== PresenterToolBar::Element =============================================
111 
112 namespace {
113  typedef cppu::WeakComponentImplHelper<
114  css::document::XEventListener,
115  css::frame::XStatusListener
116  > ElementInterfaceBase;
117 
118  class Element
119  : private ::cppu::BaseMutex,
120  public ElementInterfaceBase
121  {
122  public:
123  explicit Element (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
124  Element(const Element&) = delete;
125  Element& operator=(const Element&) = delete;
126 
127  virtual void SAL_CALL disposing() override;
128 
129  virtual void SetModes (
130  const SharedElementMode& rpNormalMode,
131  const SharedElementMode& rpMouseOverMode,
132  const SharedElementMode& rpSelectedMode,
133  const SharedElementMode& rpDisabledMode);
134  void CurrentSlideHasChanged();
135  void SetLocation (const awt::Point& rLocation);
136  void SetSize (const geometry::RealSize2D& rSize);
137  virtual void Paint (
138  const Reference<rendering::XCanvas>& rxCanvas,
139  const rendering::ViewState& rViewState) = 0;
140  awt::Size const & GetBoundingSize (
141  const Reference<rendering::XCanvas>& rxCanvas);
142  awt::Rectangle GetBoundingBox() const;
143  virtual bool SetState (const bool bIsOver, const bool bIsPressed);
144  void Invalidate (const bool bSynchronous);
145  bool IsOutside (const awt::Rectangle& rBox);
146  virtual bool IsFilling() const;
147  void UpdateState();
148 
149  // lang::XEventListener
150 
151  virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) override;
152 
153  // document::XEventListener
154 
155  virtual void SAL_CALL notifyEvent (const css::document::EventObject& rEvent) override;
156 
157  // frame::XStatusListener
158 
159  virtual void SAL_CALL statusChanged (const css::frame::FeatureStateEvent& rEvent) override;
160 
161  protected:
163  awt::Point maLocation;
164  awt::Size maSize;
165  SharedElementMode mpNormal;
166  SharedElementMode mpMouseOver;
167  SharedElementMode mpSelected;
168  SharedElementMode mpDisabled;
169  SharedElementMode mpMode;
170  bool mbIsOver;
173 
174  virtual awt::Size CreateBoundingSize (
175  const Reference<rendering::XCanvas>& rxCanvas) = 0;
176 
177  bool IsEnabled() const { return mbIsEnabled;}
178  private:
180  };
181 
182 } // end of anonymous namespace
183 
185  : public ::std::vector<rtl::Reference<Element> >
186 {
187 };
188 
189 //===== Button ================================================================
190 
191 namespace {
192 
193  class Button : public Element
194  {
195  public:
196  static ::rtl::Reference<Element> Create (
197  const ::rtl::Reference<PresenterToolBar>& rpToolBar);
198 
199  virtual void SAL_CALL disposing() override;
200 
201  virtual void Paint (
202  const Reference<rendering::XCanvas>& rxCanvas,
203  const rendering::ViewState& rViewState) override;
204 
205  // lang::XEventListener
206 
207  virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) override;
208 
209  protected:
210  virtual awt::Size CreateBoundingSize (
211  const Reference<rendering::XCanvas>& rxCanvas) override;
212 
213  private:
215 
216  Button (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
217  void Initialize();
218  void PaintIcon (
219  const Reference<rendering::XCanvas>& rxCanvas,
220  const sal_Int32 nTextHeight,
221  const rendering::ViewState& rViewState);
222  PresenterBitmapDescriptor::Mode GetMode() const;
223  };
224 
225 //===== Label =================================================================
226 
227  class Label : public Element
228  {
229  public:
230  explicit Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
231 
232  void SetText (const OUString& rsText);
233  virtual void Paint (
234  const Reference<rendering::XCanvas>& rxCanvas,
235  const rendering::ViewState& rViewState) override;
236  virtual bool SetState (const bool bIsOver, const bool bIsPressed) override;
237 
238  protected:
239  virtual awt::Size CreateBoundingSize (
240  const Reference<rendering::XCanvas>& rxCanvas) override;
241  };
242 
243 // Some specialized controls.
244 
245  class TimeFormatter
246  {
247  public:
248  static OUString FormatTime (const oslDateTime& rTime);
249  };
250 
251  class TimeLabel : public Label
252  {
253  public:
254  void ConnectToTimer();
255  virtual void TimeHasChanged (const oslDateTime& rCurrentTime) = 0;
256  protected:
257  explicit TimeLabel(const ::rtl::Reference<PresenterToolBar>& rpToolBar);
258  using Element::disposing;
259  virtual void SAL_CALL disposing() override;
260  private:
261  class Listener : public PresenterClockTimer::Listener
262  {
263  public:
264  explicit Listener (const ::rtl::Reference<TimeLabel>& rxLabel)
265  : mxLabel(rxLabel) {}
266  virtual ~Listener() {}
267  virtual void TimeHasChanged (const oslDateTime& rCurrentTime) override
268  { if (mxLabel.is()) mxLabel->TimeHasChanged(rCurrentTime); }
269  private:
271  };
272  std::shared_ptr<PresenterClockTimer::Listener> mpListener;
273  };
274 
275  class CurrentTimeLabel : public TimeLabel
276  {
277  public:
278  static ::rtl::Reference<Element> Create (
279  const ::rtl::Reference<PresenterToolBar>& rpToolBar);
280  virtual void SetModes (
281  const SharedElementMode& rpNormalMode,
282  const SharedElementMode& rpMouseOverMode,
283  const SharedElementMode& rpSelectedMode,
284  const SharedElementMode& rpDisabledMode) override;
285  private:
286  CurrentTimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
287  virtual ~CurrentTimeLabel() override;
288  virtual void TimeHasChanged (const oslDateTime& rCurrentTime) override;
289  };
290 
291  class PresentationTimeLabel : public TimeLabel, public IPresentationTime
292  {
293  public:
294  static ::rtl::Reference<Element> Create (
295  const ::rtl::Reference<PresenterToolBar>& rpToolBar);
296  virtual void SetModes (
297  const SharedElementMode& rpNormalMode,
298  const SharedElementMode& rpMouseOverMode,
299  const SharedElementMode& rpSelectedMode,
300  const SharedElementMode& rpDisabledMode) override;
301  virtual void restart() override;
302  private:
303  TimeValue maStartTimeValue;
304  PresentationTimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
305  virtual ~PresentationTimeLabel() override;
306  virtual void TimeHasChanged (const oslDateTime& rCurrentTime) override;
307  };
308 
309  class VerticalSeparator : public Element
310  {
311  public:
312  explicit VerticalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
313  virtual void Paint (
314  const Reference<rendering::XCanvas>& rxCanvas,
315  const rendering::ViewState& rViewState) override;
316  virtual bool IsFilling() const override;
317 
318  protected:
319  virtual awt::Size CreateBoundingSize (
320  const Reference<rendering::XCanvas>& rxCanvas) override;
321  };
322 
323  class HorizontalSeparator : public Element
324  {
325  public:
326  explicit HorizontalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
327  virtual void Paint (
328  const Reference<rendering::XCanvas>& rxCanvas,
329  const rendering::ViewState& rViewState) override;
330  virtual bool IsFilling() const override;
331 
332  protected:
333  virtual awt::Size CreateBoundingSize (
334  const Reference<rendering::XCanvas>& rxCanvas) override;
335  };
336 } // end of anonymous namespace
337 
338 //===== PresenterToolBar ======================================================
339 
341  const Reference<XComponentContext>& rxContext,
342  const css::uno::Reference<css::awt::XWindow>& rxWindow,
343  const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
344  const ::rtl::Reference<PresenterController>& rpPresenterController,
345  const Anchor eAnchor)
347  mxComponentContext(rxContext),
348  maElementContainer(),
349  mpCurrentContainerPart(),
350  mxWindow(rxWindow),
351  mxCanvas(rxCanvas),
352  mxSlideShowController(),
353  mxCurrentSlide(),
354  mpPresenterController(rpPresenterController),
355  mbIsLayoutPending(false),
356  meAnchor(eAnchor),
357  maMinimalSize()
358 {
359 }
360 
361 void PresenterToolBar::Initialize (
362  const OUString& rsConfigurationPath)
363 {
364  try
365  {
366  CreateControls(rsConfigurationPath);
367 
368  if (mxWindow.is())
369  {
370  mxWindow->addWindowListener(this);
371  mxWindow->addPaintListener(this);
372  mxWindow->addMouseListener(this);
373  mxWindow->addMouseMotionListener(this);
374 
375  Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
376  if (xPeer.is())
377  xPeer->setBackground(util::Color(0xff000000));
378 
379  mxWindow->setVisible(true);
380  }
381 
382  mxSlideShowController = mpPresenterController->GetSlideShowController();
383  UpdateSlideNumber();
384  mbIsLayoutPending = true;
385  }
386  catch (RuntimeException&)
387  {
388  mpCurrentContainerPart.reset();
389  maElementContainer.clear();
390  throw;
391  }
392 }
393 
394 PresenterToolBar::~PresenterToolBar()
395 {
396 }
397 
398 void SAL_CALL PresenterToolBar::disposing()
399 {
400  if (mxWindow.is())
401  {
402  mxWindow->removeWindowListener(this);
403  mxWindow->removePaintListener(this);
404  mxWindow->removeMouseListener(this);
405  mxWindow->removeMouseMotionListener(this);
406  mxWindow = nullptr;
407  }
408 
409  // Dispose tool bar elements.
410  for (const auto& rxPart : maElementContainer)
411  {
412  OSL_ASSERT(rxPart != nullptr);
413  for (rtl::Reference<Element>& pElement : *rxPart)
414  {
415  if (pElement.get() != nullptr)
416  {
418  static_cast<XWeak*>(pElement.get()), UNO_QUERY);
419  if (xComponent.is())
420  xComponent->dispose();
421  }
422  }
423  }
424 
425  mpCurrentContainerPart.reset();
426  maElementContainer.clear();
427 }
428 
429 void PresenterToolBar::InvalidateArea (
430  const awt::Rectangle& rRepaintBox,
431  const bool bSynchronous)
432 {
433  std::shared_ptr<PresenterPaintManager> xManager(mpPresenterController->GetPaintManager());
434  if (!xManager)
435  return;
436  xManager->Invalidate(
437  mxWindow,
438  rRepaintBox,
439  bSynchronous);
440 }
441 
442 void PresenterToolBar::RequestLayout()
443 {
444  mbIsLayoutPending = true;
445 
446  std::shared_ptr<PresenterPaintManager> xManager(mpPresenterController->GetPaintManager());
447  if (!xManager)
448  return;
449 
450  xManager->Invalidate(mxWindow);
451 }
452 
453 geometry::RealSize2D const & PresenterToolBar::GetMinimalSize()
454 {
455  if (mbIsLayoutPending)
456  Layout(mxCanvas);
457  return maMinimalSize;
458 }
459 
460 const ::rtl::Reference<PresenterController>& PresenterToolBar::GetPresenterController() const
461 {
462  return mpPresenterController;
463 }
464 
465 const Reference<XComponentContext>& PresenterToolBar::GetComponentContext() const
466 {
467  return mxComponentContext;
468 }
469 
470 //----- lang::XEventListener -------------------------------------------------
471 
472 void SAL_CALL PresenterToolBar::disposing (const lang::EventObject& rEventObject)
473 {
474  if (rEventObject.Source == mxWindow)
475  mxWindow = nullptr;
476 }
477 
478 //----- XWindowListener -------------------------------------------------------
479 
480 void SAL_CALL PresenterToolBar::windowResized (const awt::WindowEvent&)
481 {
482  mbIsLayoutPending = true;
483 }
484 
485 void SAL_CALL PresenterToolBar::windowMoved (const awt::WindowEvent&) {}
486 
487 void SAL_CALL PresenterToolBar::windowShown (const lang::EventObject&)
488 {
489  mbIsLayoutPending = true;
490 }
491 
492 void SAL_CALL PresenterToolBar::windowHidden (const lang::EventObject&) {}
493 
494 //----- XPaintListener --------------------------------------------------------
495 void SAL_CALL PresenterToolBar::windowPaint (const css::awt::PaintEvent& rEvent)
496 {
497  if ( ! mxCanvas.is())
498  return;
499 
500  if ( ! mbIsPresenterViewActive)
501  return;
502 
503  const rendering::ViewState aViewState (
504  geometry::AffineMatrix2D(1,0,0, 0,1,0),
505  PresenterGeometryHelper::CreatePolygon(rEvent.UpdateRect, mxCanvas->getDevice()));
506 
507  if (mbIsLayoutPending)
508  Layout(mxCanvas);
509 
510  Paint(rEvent.UpdateRect, aViewState);
511 
512  // Make the back buffer visible.
513  Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
514  if (xSpriteCanvas.is())
515  xSpriteCanvas->updateScreen(false);
516 }
517 
518 //----- XMouseListener --------------------------------------------------------
519 void SAL_CALL PresenterToolBar::mousePressed (const css::awt::MouseEvent& rEvent)
520 {
521  ThrowIfDisposed();
522  CheckMouseOver(rEvent, true, true);
523 }
524 
525 void SAL_CALL PresenterToolBar::mouseReleased (const css::awt::MouseEvent& rEvent)
526 {
527  ThrowIfDisposed();
528  CheckMouseOver(rEvent, true);
529 }
530 
531 void SAL_CALL PresenterToolBar::mouseEntered (const css::awt::MouseEvent& rEvent)
532 {
533  ThrowIfDisposed();
534  CheckMouseOver(rEvent, true);
535 }
536 
537 void SAL_CALL PresenterToolBar::mouseExited (const css::awt::MouseEvent& rEvent)
538 {
539  ThrowIfDisposed();
540  CheckMouseOver(rEvent, false);
541  }
542 
543 //----- XMouseMotionListener --------------------------------------------------
544 
545 void SAL_CALL PresenterToolBar::mouseMoved (const css::awt::MouseEvent& rEvent)
546 {
547  ThrowIfDisposed();
548  CheckMouseOver(rEvent, true);
549  }
550 
551 void SAL_CALL PresenterToolBar::mouseDragged (const css::awt::MouseEvent&)
552 {
553  ThrowIfDisposed();
554 }
555 
556 //----- XDrawView -------------------------------------------------------------
557 
558 void SAL_CALL PresenterToolBar::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
559 {
560  if (rxSlide != mxCurrentSlide)
561  {
562  mxCurrentSlide = rxSlide;
563  UpdateSlideNumber();
564  }
565 }
566 
567 Reference<drawing::XDrawPage> SAL_CALL PresenterToolBar::getCurrentPage()
568 {
569  return mxCurrentSlide;
570 }
571 
572 
573 void PresenterToolBar::CreateControls (
574  const OUString& rsConfigurationPath)
575 {
576  if ( ! mxWindow.is())
577  return;
578 
579  // Expand the macro in the bitmap file names.
580  PresenterConfigurationAccess aConfiguration (
582  "/org.openoffice.Office.PresenterScreen/",
583  PresenterConfigurationAccess::READ_ONLY);
584 
585  mpCurrentContainerPart = std::make_shared<ElementContainerPart>();
586  maElementContainer.clear();
587  maElementContainer.push_back(mpCurrentContainerPart);
588 
589  Reference<container::XHierarchicalNameAccess> xToolBarNode (
590  aConfiguration.GetConfigurationNode(rsConfigurationPath),
591  UNO_QUERY);
592  if (!xToolBarNode.is())
593  return;
594 
596  PresenterConfigurationAccess::GetConfigurationNode(xToolBarNode, "Entries"),
597  UNO_QUERY);
598  Context aContext;
599  aContext.mxPresenterHelper = mpPresenterController->GetPresenterHelper();
600  aContext.mxCanvas = mxCanvas;
601  if (xEntries.is()
602  && aContext.mxPresenterHelper.is()
603  && aContext.mxCanvas.is())
604  {
605  PresenterConfigurationAccess::ForAll(
606  xEntries,
607  [this, &aContext] (OUString const&, uno::Reference<beans::XPropertySet> const& xProps)
608  {
609  return this->ProcessEntry(xProps, aContext);
610  });
611  }
612 }
613 
614 void PresenterToolBar::ProcessEntry (
615  const Reference<beans::XPropertySet>& rxProperties,
616  Context const & rContext)
617 {
618  if ( ! rxProperties.is())
619  return;
620 
621  // Type has to be present.
622  OUString sType;
623  if ( ! (PresenterConfigurationAccess::GetProperty(rxProperties, "Type") >>= sType))
624  return;
625 
626  // Read mode specific values.
627  SharedElementMode pNormalMode = std::make_shared<ElementMode>();
628  SharedElementMode pMouseOverMode = std::make_shared<ElementMode>();
629  SharedElementMode pSelectedMode = std::make_shared<ElementMode>();
630  SharedElementMode pDisabledMode = std::make_shared<ElementMode>();
631  pNormalMode->ReadElementMode(rxProperties, "Normal", pNormalMode, rContext);
632  pMouseOverMode->ReadElementMode(rxProperties, "MouseOver", pNormalMode, rContext);
633  pSelectedMode->ReadElementMode(rxProperties, "Selected", pNormalMode, rContext);
634  pDisabledMode->ReadElementMode(rxProperties, "Disabled", pNormalMode, rContext);
635 
636  // Create new element.
637  ::rtl::Reference<Element> pElement;
638  if ( sType == "Button" )
639  pElement = Button::Create(this);
640  else if ( sType == "CurrentTimeLabel" )
641  pElement = CurrentTimeLabel::Create(this);
642  else if ( sType == "PresentationTimeLabel" )
643  pElement = PresentationTimeLabel::Create(this);
644  else if ( sType == "VerticalSeparator" )
645  pElement.set(new VerticalSeparator(this));
646  else if ( sType == "HorizontalSeparator" )
647  pElement.set(new HorizontalSeparator(this));
648  else if ( sType == "Label" )
649  pElement.set(new Label(this));
650  else if ( sType == "ChangeOrientation" )
651  {
652  mpCurrentContainerPart = std::make_shared<ElementContainerPart>();
653  maElementContainer.push_back(mpCurrentContainerPart);
654  return;
655  }
656  if (pElement.is())
657  {
658  pElement->SetModes( pNormalMode, pMouseOverMode, pSelectedMode, pDisabledMode);
659  pElement->UpdateState();
660  if (mpCurrentContainerPart.get() != nullptr)
661  mpCurrentContainerPart->push_back(pElement);
662  }
663 }
664 
665 void PresenterToolBar::Layout (
666  const Reference<rendering::XCanvas>& rxCanvas)
667 {
668  if (maElementContainer.empty())
669  return;
670 
671  mbIsLayoutPending = false;
672 
673  const awt::Rectangle aWindowBox (mxWindow->getPosSize());
674  ::std::vector<geometry::RealSize2D> aPartSizes (maElementContainer.size());
675  geometry::RealSize2D aTotalSize (0,0);
676  bool bIsHorizontal (true);
677  sal_Int32 nIndex (0);
678  double nTotalHorizontalGap (0);
679  sal_Int32 nGapCount (0);
680  for (const auto& rxPart : maElementContainer)
681  {
682  geometry::RealSize2D aSize (CalculatePartSize(rxCanvas, rxPart, bIsHorizontal));
683 
684  // Remember the size of each part for later.
685  aPartSizes[nIndex] = aSize;
686 
687  // Add gaps between elements.
688  if (rxPart->size()>1 && bIsHorizontal)
689  {
690  nTotalHorizontalGap += (rxPart->size() - 1) * gnGapSize;
691  nGapCount += rxPart->size() - 1;
692  }
693 
694  // Orientation changes for each part.
695  bIsHorizontal = !bIsHorizontal;
696  // Width is accumulated.
697  aTotalSize.Width += aSize.Width;
698  // Height is the maximum height of all parts.
699  aTotalSize.Height = ::std::max(aTotalSize.Height, aSize.Height);
700  ++nIndex;
701  }
702  // Add gaps between parts.
703  if (maElementContainer.size() > 1)
704  {
705  nTotalHorizontalGap += (maElementContainer.size() - 1) * gnGapSize;
706  nGapCount += maElementContainer.size()-1;
707  }
708 
709  // Calculate the minimal size so that the window size of the tool bar
710  // can be adapted accordingly.
711  maMinimalSize = aTotalSize;
712  maMinimalSize.Width += nTotalHorizontalGap;
713 
714  // Calculate the gaps between elements.
715  double nGapWidth (0);
716  if (nGapCount > 0)
717  {
718  if (aTotalSize.Width + nTotalHorizontalGap > aWindowBox.Width)
719  nTotalHorizontalGap = aWindowBox.Width - aTotalSize.Width;
720  nGapWidth = nTotalHorizontalGap / nGapCount;
721  }
722 
723  // Determine the location of the left edge.
724  double nX (0);
725  switch (meAnchor)
726  {
727  case Left : nX = 0; break;
728  case Center: nX = (aWindowBox.Width - aTotalSize.Width - nTotalHorizontalGap) / 2; break;
729  }
730 
731  // Place the parts.
732  double nY ((aWindowBox.Height - aTotalSize.Height) / 2);
733  bIsHorizontal = true;
734 
735  /* push front or back ? ... */
738  nIndex = 0;
739  for (const auto& rxPart : maElementContainer)
740  {
741  geometry::RealRectangle2D aBoundingBox(
742  nX, nY,
743  nX+aPartSizes[nIndex].Width, nY+aTotalSize.Height);
744 
745  // Add space for gaps between elements.
746  if (rxPart->size() > 1 && bIsHorizontal)
747  aBoundingBox.X2 += (rxPart->size() - 1) * nGapWidth;
748 
749  LayoutPart(rxCanvas, rxPart, aBoundingBox, aPartSizes[nIndex], bIsHorizontal);
750  bIsHorizontal = !bIsHorizontal;
751  nX += aBoundingBox.X2 - aBoundingBox.X1 + nGapWidth;
752  ++nIndex;
753  }
754  }
755  else {
756  ElementContainer::iterator iPart;
757  ElementContainer::iterator iBegin (maElementContainer.begin());
758  for (iPart=maElementContainer.end()-1, nIndex=2; iPart!=iBegin-1; --iPart, --nIndex)
759  {
760  geometry::RealRectangle2D aBoundingBox(
761  nX, nY,
762  nX+aPartSizes[nIndex].Width, nY+aTotalSize.Height);
763 
764  // Add space for gaps between elements.
765  if ((*iPart)->size() > 1)
766  if (bIsHorizontal)
767  aBoundingBox.X2 += ((*iPart)->size()-1) * nGapWidth;
768 
769  LayoutPart(rxCanvas, *iPart, aBoundingBox, aPartSizes[nIndex], bIsHorizontal);
770  bIsHorizontal = !bIsHorizontal;
771  nX += aBoundingBox.X2 - aBoundingBox.X1 + nGapWidth;
772  }
773  }
774 
775  // The whole window has to be repainted.
776  std::shared_ptr<PresenterPaintManager> xManager(mpPresenterController->GetPaintManager());
777  if (!xManager)
778  return;
779  xManager->Invalidate(mxWindow);
780 }
781 
782 geometry::RealSize2D PresenterToolBar::CalculatePartSize (
783  const Reference<rendering::XCanvas>& rxCanvas,
784  const SharedElementContainerPart& rpPart,
785  const bool bIsHorizontal)
786 {
787  geometry::RealSize2D aTotalSize (0,0);
788 
789  if (mxWindow.is())
790  {
791  // Calculate the summed width of all elements.
792  for (const auto& rxElement : *rpPart)
793  {
794  if (rxElement.get() == nullptr)
795  continue;
796 
797  const awt::Size aBSize (rxElement->GetBoundingSize(rxCanvas));
798  if (bIsHorizontal)
799  {
800  aTotalSize.Width += aBSize.Width;
801  if (aBSize.Height > aTotalSize.Height)
802  aTotalSize.Height = aBSize.Height;
803  }
804  else
805  {
806  aTotalSize.Height += aBSize.Height;
807  if (aBSize.Width > aTotalSize.Width)
808  aTotalSize.Width = aBSize.Width;
809  }
810  }
811  }
812  return aTotalSize;
813 }
814 
815 void PresenterToolBar::LayoutPart (
816  const Reference<rendering::XCanvas>& rxCanvas,
817  const SharedElementContainerPart& rpPart,
818  const geometry::RealRectangle2D& rBoundingBox,
819  const geometry::RealSize2D& rPartSize,
820  const bool bIsHorizontal)
821 {
822  double nGap (0);
823  if (rpPart->size() > 1)
824  {
825  if (bIsHorizontal)
826  nGap = (rBoundingBox.X2 - rBoundingBox.X1 - rPartSize.Width) / (rpPart->size()-1);
827  else
828  nGap = (rBoundingBox.Y2 - rBoundingBox.Y1 - rPartSize.Height) / (rpPart->size()-1);
829  }
830 
831  // Place the elements.
832  double nX (rBoundingBox.X1);
833  double nY (rBoundingBox.Y1);
834 
837  for (auto& rxElement : *rpPart)
838  {
839  if (rxElement.get() == nullptr)
840  continue;
841 
842  const awt::Size aElementSize (rxElement->GetBoundingSize(rxCanvas));
843  if (bIsHorizontal)
844  {
845  if (rxElement->IsFilling())
846  {
847  nY = rBoundingBox.Y1;
848  rxElement->SetSize(geometry::RealSize2D(aElementSize.Width, rBoundingBox.Y2 - rBoundingBox.Y1));
849  }
850  else
851  nY = rBoundingBox.Y1 + (rBoundingBox.Y2-rBoundingBox.Y1 - aElementSize.Height) / 2;
852  rxElement->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
853  nX += aElementSize.Width + nGap;
854  }
855  else
856  {
857  if (rxElement->IsFilling())
858  {
859  nX = rBoundingBox.X1;
860  rxElement->SetSize(geometry::RealSize2D(rBoundingBox.X2 - rBoundingBox.X1, aElementSize.Height));
861  }
862  else
863  nX = rBoundingBox.X1 + (rBoundingBox.X2-rBoundingBox.X1 - aElementSize.Width) / 2;
864  rxElement->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
865  nY += aElementSize.Height + nGap;
866  }
867  }
868  }
869  else {
870  ElementContainerPart::const_iterator iElement;
871  ElementContainerPart::const_iterator iBegin (rpPart->begin());
872 
873  for (iElement=rpPart->end()-1; iElement!=iBegin-1; --iElement)
874  {
875  if (iElement->get() == nullptr)
876  continue;
877 
878  const awt::Size aElementSize ((*iElement)->GetBoundingSize(rxCanvas));
879  if (bIsHorizontal)
880  {
881  if ((*iElement)->IsFilling())
882  {
883  nY = rBoundingBox.Y1;
884  (*iElement)->SetSize(geometry::RealSize2D(aElementSize.Width, rBoundingBox.Y2 - rBoundingBox.Y1));
885  }
886  else
887  nY = rBoundingBox.Y1 + (rBoundingBox.Y2-rBoundingBox.Y1 - aElementSize.Height) / 2;
888  (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
889  nX += aElementSize.Width + nGap;
890  }
891  else
892  {
893  // reverse presentation time with current time
894  if (iElement==iBegin){
895  iElement=iBegin+2;
896  }
897  else if (iElement==iBegin+2){
898  iElement=iBegin;
899  }
900  const awt::Size aNewElementSize ((*iElement)->GetBoundingSize(rxCanvas));
901  if ((*iElement)->IsFilling())
902  {
903  nX = rBoundingBox.X1;
904  (*iElement)->SetSize(geometry::RealSize2D(rBoundingBox.X2 - rBoundingBox.X1, aNewElementSize.Height));
905  }
906  else
907  nX = rBoundingBox.X1 + (rBoundingBox.X2-rBoundingBox.X1 - aNewElementSize.Width) / 2;
908  (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
909  nY += aNewElementSize.Height + nGap;
910 
911  // return the index as it was before the reversing
912  if (iElement==iBegin)
913  iElement=iBegin+2;
914  else if (iElement==iBegin+2)
915  iElement=iBegin;
916  }
917  }
918  }
919 }
920 
921 void PresenterToolBar::Paint (
922  const awt::Rectangle& rUpdateBox,
923  const rendering::ViewState& rViewState)
924 {
925  OSL_ASSERT(mxCanvas.is());
926 
927  for (const auto& rxPart : maElementContainer)
928  {
929  for (auto& rxElement : *rxPart)
930  {
931  if (rxElement.get() != nullptr)
932  {
933  if ( ! rxElement->IsOutside(rUpdateBox))
934  rxElement->Paint(mxCanvas, rViewState);
935  }
936  }
937  }
938 }
939 
940 void PresenterToolBar::UpdateSlideNumber()
941 {
942  if( mxSlideShowController.is() )
943  {
944  for (const auto& rxPart : maElementContainer)
945  {
946  for (auto& rxElement : *rxPart)
947  {
948  if (rxElement.get() != nullptr)
949  rxElement->CurrentSlideHasChanged();
950  }
951  }
952  }
953 }
954 
955 void PresenterToolBar::CheckMouseOver (
956  const css::awt::MouseEvent& rEvent,
957  const bool bOverWindow,
958  const bool bMouseDown)
959 {
960  css::awt::MouseEvent rTemp =rEvent;
962  awt::Rectangle aWindowBox = mxWindow->getPosSize();
963  rTemp.X=aWindowBox.Width-rTemp.X;
964  }
965  for (const auto& rxPart : maElementContainer)
966  {
967  for (auto& rxElement : *rxPart)
968  {
969  if (rxElement.get() == nullptr)
970  continue;
971 
972  awt::Rectangle aBox (rxElement->GetBoundingBox());
973  const bool bIsOver = bOverWindow
974  && aBox.X <= rTemp.X
975  && aBox.Width+aBox.X-1 >= rTemp.X
976  && aBox.Y <= rTemp.Y
977  && aBox.Height+aBox.Y-1 >= rTemp.Y;
978  rxElement->SetState(
979  bIsOver,
980  bIsOver && rTemp.Buttons!=0 && bMouseDown && rTemp.ClickCount>0);
981  }
982  }
983 }
984 
985 void PresenterToolBar::ThrowIfDisposed() const
986 {
987  if (rBHelper.bDisposed || rBHelper.bInDispose)
988  {
989  throw lang::DisposedException (
990  "PresenterToolBar has already been disposed",
991  const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
992  }
993 }
994 
995 //===== PresenterToolBarView ==================================================
996 
997 PresenterToolBarView::PresenterToolBarView (
998  const Reference<XComponentContext>& rxContext,
999  const Reference<XResourceId>& rxViewId,
1000  const Reference<frame::XController>& rxController,
1001  const ::rtl::Reference<PresenterController>& rpPresenterController)
1003  mxPane(),
1004  mxViewId(rxViewId),
1005  mxWindow(),
1006  mxCanvas(),
1007  mpPresenterController(rpPresenterController),
1008  mpToolBar()
1009 {
1010  try
1011  {
1012  Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW);
1013  Reference<XConfigurationController> xCC(xCM->getConfigurationController(),UNO_SET_THROW);
1014  mxPane.set(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW);
1015 
1016  mxWindow = mxPane->getWindow();
1017  mxCanvas = mxPane->getCanvas();
1018 
1020  rxContext,
1021  mxWindow,
1022  mxCanvas,
1023  rpPresenterController,
1025  mpToolBar->Initialize("PresenterScreenSettings/ToolBars/ToolBar");
1026 
1027  if (mxWindow.is())
1028  {
1029  mxWindow->addPaintListener(this);
1030 
1031  Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
1032  if (xPeer.is())
1033  xPeer->setBackground(util::Color(0xff000000));
1034 
1035  mxWindow->setVisible(true);
1036  }
1037  }
1038  catch (RuntimeException&)
1039  {
1040  mxViewId = nullptr;
1041  throw;
1042  }
1043 }
1044 
1046 {
1047 }
1048 
1050 {
1051  Reference<lang::XComponent> xComponent (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY);
1052  mpToolBar = nullptr;
1053  if (xComponent.is())
1054  xComponent->dispose();
1055 
1056  if (mxWindow.is())
1057  {
1058  mxWindow->removePaintListener(this);
1059  mxWindow = nullptr;
1060  }
1061  mxCanvas = nullptr;
1062  mxViewId = nullptr;
1063  mxPane = nullptr;
1064  mpPresenterController = nullptr;
1065 }
1066 
1067 const ::rtl::Reference<PresenterToolBar>& PresenterToolBarView::GetPresenterToolBar() const
1068 {
1069  return mpToolBar;
1070 }
1071 
1072 //----- XPaintListener --------------------------------------------------------
1073 
1074 void SAL_CALL PresenterToolBarView::windowPaint (const css::awt::PaintEvent& rEvent)
1075 {
1076  awt::Rectangle aWindowBox (mxWindow->getPosSize());
1077  mpPresenterController->GetCanvasHelper()->Paint(
1078  mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
1079  mxCanvas,
1080  rEvent.UpdateRect,
1081  awt::Rectangle(0,0,aWindowBox.Width, aWindowBox.Height),
1082  awt::Rectangle());
1083 }
1084 
1085 //----- lang::XEventListener -------------------------------------------------
1086 
1087 void SAL_CALL PresenterToolBarView::disposing (const lang::EventObject& rEventObject)
1088 {
1089  if (rEventObject.Source == mxWindow)
1090  mxWindow = nullptr;
1091 }
1092 
1093 //----- XResourceId -----------------------------------------------------------
1094 
1095 Reference<XResourceId> SAL_CALL PresenterToolBarView::getResourceId()
1096 {
1097  return mxViewId;
1098 }
1099 
1101 {
1102  return false;
1103 }
1104 
1105 //----- XDrawView -------------------------------------------------------------
1106 
1108 {
1109  Reference<drawing::XDrawView> xToolBar (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY);
1110  if (xToolBar.is())
1111  xToolBar->setCurrentPage(rxSlide);
1112 }
1113 
1115 {
1116  return nullptr;
1117 }
1118 
1119 //===== PresenterToolBar::Element =============================================
1120 
1121 namespace {
1122 
1123 Element::Element (
1124  const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1125  : ElementInterfaceBase(m_aMutex),
1126  mpToolBar(rpToolBar),
1127  maLocation(),
1128  maSize(),
1129  mpNormal(),
1130  mpMouseOver(),
1131  mpSelected(),
1132  mpDisabled(),
1133  mpMode(),
1134  mbIsOver(false),
1135  mbIsPressed(false),
1136  mbIsSelected(false),
1137  mbIsEnabled(true)
1138 {
1139  if (mpToolBar.get() != nullptr)
1140  {
1141  OSL_ASSERT(mpToolBar->GetPresenterController().is());
1142  OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
1143  }
1144 }
1145 
1146 void Element::SetModes (
1147  const SharedElementMode& rpNormalMode,
1148  const SharedElementMode& rpMouseOverMode,
1149  const SharedElementMode& rpSelectedMode,
1150  const SharedElementMode& rpDisabledMode)
1151 {
1152  mpNormal = rpNormalMode;
1153  mpMouseOver = rpMouseOverMode;
1154  mpSelected = rpSelectedMode;
1155  mpDisabled = rpDisabledMode;
1156  mpMode = rpNormalMode;
1157 }
1158 
1159 void Element::disposing()
1160 {
1161 }
1162 
1163 awt::Size const & Element::GetBoundingSize (
1164  const Reference<rendering::XCanvas>& rxCanvas)
1165 {
1166  maSize = CreateBoundingSize(rxCanvas);
1167  return maSize;
1168 }
1169 
1170 awt::Rectangle Element::GetBoundingBox() const
1171 {
1172  return awt::Rectangle(maLocation.X,maLocation.Y, maSize.Width, maSize.Height);
1173 }
1174 
1175 void Element::CurrentSlideHasChanged()
1176 {
1177  UpdateState();
1178 }
1179 
1180 void Element::SetLocation (const awt::Point& rLocation)
1181 {
1182  maLocation = rLocation;
1183 }
1184 
1185 void Element::SetSize (const geometry::RealSize2D& rSize)
1186 {
1187  maSize = awt::Size(sal_Int32(0.5+rSize.Width), sal_Int32(0.5+rSize.Height));
1188 }
1189 
1190 bool Element::SetState (
1191  const bool bIsOver,
1192  const bool bIsPressed)
1193 {
1194  bool bModified (mbIsOver != bIsOver || mbIsPressed != bIsPressed);
1195  bool bClicked (mbIsPressed && bIsOver && ! bIsPressed);
1196 
1197  mbIsOver = bIsOver;
1198  mbIsPressed = bIsPressed;
1199 
1200  // When the element is disabled then ignore mouse over or selection.
1201  // When the element is selected then ignore mouse over.
1202  if ( ! mbIsEnabled)
1203  mpMode = mpDisabled;
1204  else if (mbIsSelected)
1205  mpMode = mpSelected;
1206  else if (mbIsOver)
1207  mpMode = mpMouseOver;
1208  else
1209  mpMode = mpNormal;
1210 
1211  if (bClicked && mbIsEnabled)
1212  {
1213  if (mpMode.get() != nullptr)
1214  {
1215  do
1216  {
1217  if (mpMode->msAction.isEmpty())
1218  break;
1219 
1220  if (mpToolBar.get() == nullptr)
1221  break;
1222 
1223  if (mpToolBar->GetPresenterController().get() == nullptr)
1224  break;
1225 
1226  mpToolBar->GetPresenterController()->DispatchUnoCommand(mpMode->msAction);
1227  mpToolBar->RequestLayout();
1228  }
1229  while (false);
1230  }
1231 
1232  }
1233  else if (bModified)
1234  {
1235  Invalidate(true);
1236  }
1237 
1238  return bModified;
1239 }
1240 
1241 void Element::Invalidate (const bool bSynchronous)
1242 {
1243  OSL_ASSERT(mpToolBar.is());
1244  mpToolBar->InvalidateArea(GetBoundingBox(), bSynchronous);
1245 }
1246 
1247 bool Element::IsOutside (const awt::Rectangle& rBox)
1248 {
1249  if (rBox.X >= maLocation.X+maSize.Width)
1250  return true;
1251  else if (rBox.Y >= maLocation.Y+maSize.Height)
1252  return true;
1253  else if (maLocation.X >= rBox.X+rBox.Width)
1254  return true;
1255  else if (maLocation.Y >= rBox.Y+rBox.Height)
1256  return true;
1257  else
1258  return false;
1259 }
1260 
1261 
1262 bool Element::IsFilling() const
1263 {
1264  return false;
1265 }
1266 
1267 void Element::UpdateState()
1268 {
1269  OSL_ASSERT(mpToolBar.get() != nullptr);
1270  OSL_ASSERT(mpToolBar->GetPresenterController().get() != nullptr);
1271 
1272  if (mpMode.get() == nullptr)
1273  return;
1274 
1275  util::URL aURL (mpToolBar->GetPresenterController()->CreateURLFromString(mpMode->msAction));
1276  Reference<frame::XDispatch> xDispatch (mpToolBar->GetPresenterController()->GetDispatch(aURL));
1277  if (xDispatch.is())
1278  {
1279  xDispatch->addStatusListener(this, aURL);
1280  xDispatch->removeStatusListener(this, aURL);
1281  }
1282 }
1283 
1284 //----- lang::XEventListener --------------------------------------------------
1285 
1286 void SAL_CALL Element::disposing (const css::lang::EventObject&) {}
1287 
1288 //----- document::XEventListener ----------------------------------------------
1289 
1290 void SAL_CALL Element::notifyEvent (const css::document::EventObject&)
1291 {
1292  UpdateState();
1293 }
1294 
1295 //----- frame::XStatusListener ------------------------------------------------
1296 
1297 void SAL_CALL Element::statusChanged (const css::frame::FeatureStateEvent& rEvent)
1298 {
1299  bool bIsSelected (mbIsSelected);
1300  bool bIsEnabled (rEvent.IsEnabled);
1301  rEvent.State >>= bIsSelected;
1302 
1303  if (bIsSelected != mbIsSelected || bIsEnabled != mbIsEnabled)
1304  {
1306  mbIsSelected = bIsSelected;
1307  SetState(mbIsOver, mbIsPressed);
1308  mpToolBar->RequestLayout();
1309  }
1310 }
1311 
1312 } // end of anonymous namespace
1313 
1314 //===== ElementMode ===========================================================
1315 
1316 namespace {
1317 
1318 ElementMode::ElementMode()
1319  : mpIcon(),
1320  msAction(),
1321  maText()
1322 {
1323 }
1324 
1325 void ElementMode::ReadElementMode (
1326  const Reference<beans::XPropertySet>& rxElementProperties,
1327  const OUString& rsModeName,
1328  std::shared_ptr<ElementMode> const & rpDefaultMode,
1330 {
1331  try
1332  {
1333  Reference<container::XHierarchicalNameAccess> xNode (
1334  PresenterConfigurationAccess::GetProperty(rxElementProperties, rsModeName),
1335  UNO_QUERY);
1336  Reference<beans::XPropertySet> xProperties (
1338  if (!xProperties.is() && rpDefaultMode != nullptr)
1339  {
1340  // The mode is not specified. Use the given, possibly empty,
1341  // default mode instead.
1342  mpIcon = rpDefaultMode->mpIcon;
1343  msAction = rpDefaultMode->msAction;
1344  maText = rpDefaultMode->maText;
1345  }
1346 
1347  // Read action.
1348  if ( ! (PresenterConfigurationAccess::GetProperty(xProperties, "Action") >>= msAction))
1349  if (rpDefaultMode != nullptr)
1350  msAction = rpDefaultMode->msAction;
1351 
1352  // Read text and font
1353  OUString sText(rpDefaultMode != nullptr ? rpDefaultMode->maText.GetText() : OUString());
1354  PresenterConfigurationAccess::GetProperty(xProperties, "Text") >>= sText;
1355  Reference<container::XHierarchicalNameAccess> xFontNode (
1356  PresenterConfigurationAccess::GetProperty(xProperties, "Font"), UNO_QUERY);
1358  xFontNode, rpDefaultMode != nullptr ? rpDefaultMode->maText.GetFont()
1360  maText = Text(sText,pFont);
1361 
1362  // Read bitmaps to display as icons.
1363  Reference<container::XHierarchicalNameAccess> xIconNode (
1364  PresenterConfigurationAccess::GetProperty(xProperties, "Icon"), UNO_QUERY);
1366  xIconNode, "", rContext.mxPresenterHelper, rContext.mxCanvas,
1367  rpDefaultMode != nullptr ? rpDefaultMode->mpIcon : SharedBitmapDescriptor());
1368  }
1369  catch(Exception&)
1370  {
1371  OSL_ASSERT(false);
1372  }
1373 }
1374 
1375 } // end of anonymous namespace
1376 
1377 //===== Button ================================================================
1378 
1379 namespace {
1380 
1381 ::rtl::Reference<Element> Button::Create (
1382  const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1383 {
1384  ::rtl::Reference<Button> pElement (new Button(rpToolBar));
1385  pElement->Initialize();
1386  return ::rtl::Reference<Element>(pElement.get());
1387 }
1388 
1390  const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1391  : Element(rpToolBar),
1392  mbIsListenerRegistered(false)
1393 {
1394  OSL_ASSERT(mpToolBar.get() != nullptr);
1395  OSL_ASSERT(mpToolBar->GetPresenterController().is());
1396  OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
1397 }
1398 
1399 void Button::Initialize()
1400 {
1401  mpToolBar->GetPresenterController()->GetWindowManager()->AddLayoutListener(this);
1402  mbIsListenerRegistered = true;
1403 }
1404 
1405 void Button::disposing()
1406 {
1407  OSL_ASSERT(mpToolBar.get() != nullptr);
1408  if (mpToolBar.get() != nullptr
1410  {
1411  OSL_ASSERT(mpToolBar->GetPresenterController().is());
1412  OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
1413 
1414  mbIsListenerRegistered = false;
1415  mpToolBar->GetPresenterController()->GetWindowManager()->RemoveLayoutListener(this);
1416  }
1417  Element::disposing();
1418 }
1419 
1420 void Button::Paint (
1421  const Reference<rendering::XCanvas>& rxCanvas,
1422  const rendering::ViewState& rViewState)
1423 {
1424  OSL_ASSERT(rxCanvas.is());
1425 
1426  if (mpMode.get() == nullptr)
1427  return;
1428 
1429  if (mpMode->mpIcon.get() == nullptr)
1430  return;
1431 
1432  geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
1433  sal_Int32 nTextHeight (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
1434 
1435  PaintIcon(rxCanvas, nTextHeight, rViewState);
1436  mpMode->maText.Paint(rxCanvas, rViewState, GetBoundingBox());
1437 }
1438 
1439 awt::Size Button::CreateBoundingSize (
1440  const Reference<rendering::XCanvas>& rxCanvas)
1441 {
1442  if (mpMode.get() == nullptr)
1443  return awt::Size();
1444 
1445  geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
1446  const sal_Int32 nGap (5);
1447  sal_Int32 nTextHeight (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
1448  sal_Int32 nTextWidth (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.X2 - aTextBBox.X1));
1449  Reference<rendering::XBitmap> xBitmap;
1450  if (mpMode->mpIcon.get() != nullptr)
1451  xBitmap = mpMode->mpIcon->GetNormalBitmap();
1452  if (xBitmap.is())
1453  {
1454  geometry::IntegerSize2D aSize (xBitmap->getSize());
1455  return awt::Size(
1456  ::std::max(aSize.Width, sal_Int32(0.5 + aTextBBox.X2 - aTextBBox.X1)),
1457  aSize.Height+ nGap + nTextHeight);
1458  }
1459  else
1460  return awt::Size(nTextWidth,nTextHeight);
1461 }
1462 
1463 void Button::PaintIcon (
1464  const Reference<rendering::XCanvas>& rxCanvas,
1465  const sal_Int32 nTextHeight,
1466  const rendering::ViewState& rViewState)
1467 {
1468  if (mpMode.get() == nullptr)
1469  return;
1470 
1471  Reference<rendering::XBitmap> xBitmap (mpMode->mpIcon->GetBitmap(GetMode()));
1472  if (!xBitmap.is())
1473  return;
1474 
1477  const sal_Int32 nX (maLocation.X
1478  + (maSize.Width-xBitmap->getSize().Width) / 2);
1479  const sal_Int32 nY (maLocation.Y
1480  + (maSize.Height - nTextHeight - xBitmap->getSize().Height) / 2);
1481  const rendering::RenderState aRenderState(
1482  geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
1483  nullptr,
1484  Sequence<double>(4),
1485  rendering::CompositeOperation::OVER);
1486  rxCanvas->drawBitmap(xBitmap, rViewState, aRenderState);
1487  }
1488  else {
1489  const sal_Int32 nX (maLocation.X
1490  + (maSize.Width+xBitmap->getSize().Width) / 2);
1491  const sal_Int32 nY (maLocation.Y
1492  + (maSize.Height - nTextHeight - xBitmap->getSize().Height) / 2);
1493  const rendering::RenderState aRenderState(
1494  geometry::AffineMatrix2D(-1,0,nX, 0,1,nY),
1495  nullptr,
1496  Sequence<double>(4),
1497  rendering::CompositeOperation::OVER);
1498  rxCanvas->drawBitmap(xBitmap, rViewState, aRenderState);
1499  }
1500 }
1501 
1502 PresenterBitmapDescriptor::Mode Button::GetMode() const
1503 {
1504  if ( ! IsEnabled())
1506  else if (mbIsPressed)
1508  else if (mbIsOver)
1510  else
1512 }
1513 
1514 //----- lang::XEventListener --------------------------------------------------
1515 
1516 void SAL_CALL Button::disposing (const css::lang::EventObject& rEvent)
1517 {
1518  mbIsListenerRegistered = false;
1519  Element::disposing(rEvent);
1520 }
1521 
1522 } // end of anonymous namespace
1523 
1524 //===== PresenterToolBar::Label ===============================================
1525 
1526 namespace {
1527 
1528 Label::Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1529  : Element(rpToolBar)
1530 {
1531 }
1532 
1533 awt::Size Label::CreateBoundingSize (
1534  const Reference<rendering::XCanvas>& rxCanvas)
1535 {
1536  if (mpMode.get() == nullptr)
1537  return awt::Size(0,0);
1538 
1539  geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
1540  return awt::Size(
1541  sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.X2 - aTextBBox.X1),
1542  sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
1543 }
1544 
1545 void Label::SetText (const OUString& rsText)
1546 {
1547  OSL_ASSERT(mpToolBar.get() != nullptr);
1548  if (mpMode.get() == nullptr)
1549  return;
1550 
1551  const bool bRequestLayout (mpMode->maText.GetText().getLength() != rsText.getLength());
1552 
1553  mpMode->maText.SetText(rsText);
1554  // Just use the character count for determining whether a layout is
1555  // necessary. This is an optimization to avoid layouts every time a new
1556  // time value is set on some labels.
1557  if (bRequestLayout)
1558  mpToolBar->RequestLayout();
1559  else
1560  Invalidate(false);
1561 }
1562 
1563 void Label::Paint (
1564  const Reference<rendering::XCanvas>& rxCanvas,
1565  const rendering::ViewState& rViewState)
1566 {
1567  OSL_ASSERT(rxCanvas.is());
1568  if (mpMode.get() == nullptr)
1569  return;
1570 
1571  mpMode->maText.Paint(rxCanvas, rViewState, GetBoundingBox());
1572 }
1573 
1574 bool Label::SetState (const bool, const bool)
1575 {
1576  // For labels there is no mouse over effect.
1577  return Element::SetState(false, false);
1578 }
1579 
1580 } // end of anonymous namespace
1581 
1582 //===== Text ==================================================================
1583 
1584 namespace {
1585 
1586 Text::Text()
1587  : msText(),
1588  mpFont()
1589 {
1590 }
1591 
1592 Text::Text (
1593  const OUString& rsText,
1595  : msText(rsText),
1596  mpFont(rpFont)
1597 {
1598 }
1599 
1600 void Text::SetText (const OUString& rsText)
1601 {
1602  msText = rsText;
1603 }
1604 
1605 const OUString& Text::GetText() const
1606 {
1607  return msText;
1608 }
1609 
1610 const PresenterTheme::SharedFontDescriptor& Text::GetFont() const
1611 {
1612  return mpFont;
1613 }
1614 
1615 void Text::Paint (
1616  const Reference<rendering::XCanvas>& rxCanvas,
1617  const rendering::ViewState& rViewState,
1618  const awt::Rectangle& rBoundingBox)
1619 {
1620  OSL_ASSERT(rxCanvas.is());
1621 
1622  if (msText.isEmpty())
1623  return;
1624  if (mpFont.get() == nullptr)
1625  return;
1626 
1627  if ( ! mpFont->mxFont.is())
1628  mpFont->PrepareFont(rxCanvas);
1629  if ( ! mpFont->mxFont.is())
1630  return;
1631 
1632  rendering::StringContext aContext (msText, 0, msText.getLength());
1633 
1634  Reference<rendering::XTextLayout> xLayout (
1635  mpFont->mxFont->createTextLayout(
1636  aContext,
1637  rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
1638  0));
1639  geometry::RealRectangle2D aBox (xLayout->queryTextBounds());
1640  const double nTextWidth = aBox.X2 - aBox.X1;
1641  const double nY = rBoundingBox.Y + rBoundingBox.Height - aBox.Y2;
1642  const double nX = rBoundingBox.X + (rBoundingBox.Width - nTextWidth)/2;
1643 
1644  rendering::RenderState aRenderState(
1645  geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
1646  nullptr,
1647  Sequence<double>(4),
1648  rendering::CompositeOperation::SOURCE);
1649  PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);
1650  rxCanvas->drawTextLayout(
1651  xLayout,
1652  rViewState,
1653  aRenderState);
1654 }
1655 
1656 geometry::RealRectangle2D Text::GetBoundingBox (const Reference<rendering::XCanvas>& rxCanvas)
1657 {
1658  if (mpFont.get() != nullptr && !msText.isEmpty())
1659  {
1660  if ( ! mpFont->mxFont.is())
1661  mpFont->PrepareFont(rxCanvas);
1662  if (mpFont->mxFont.is())
1663  {
1664  rendering::StringContext aContext (msText, 0, msText.getLength());
1665  Reference<rendering::XTextLayout> xLayout (
1666  mpFont->mxFont->createTextLayout(
1667  aContext,
1668  rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
1669  0));
1670  return xLayout->queryTextBounds();
1671  }
1672  }
1673  return geometry::RealRectangle2D(0,0,0,0);
1674 }
1675 
1676 //===== TimeFormatter =========================================================
1677 
1678 OUString TimeFormatter::FormatTime (const oslDateTime& rTime)
1679 {
1680  OUStringBuffer sText;
1681 
1682  const sal_Int32 nHours (sal::static_int_cast<sal_Int32>(rTime.Hours));
1683  const sal_Int32 nMinutes (sal::static_int_cast<sal_Int32>(rTime.Minutes));
1684  const sal_Int32 nSeconds(sal::static_int_cast<sal_Int32>(rTime.Seconds));
1685  // Hours
1686  sText.append(OUString::number(nHours));
1687 
1688  sText.append(":");
1689 
1690  // Minutes
1691  const OUString sMinutes (OUString::number(nMinutes));
1692  if (sMinutes.getLength() == 1)
1693  sText.append("0");
1694  sText.append(sMinutes);
1695 
1696  // Seconds
1697  sText.append(":");
1698  const OUString sSeconds (OUString::number(nSeconds));
1699  if (sSeconds.getLength() == 1)
1700  sText.append("0");
1701  sText.append(sSeconds);
1702  return sText.makeStringAndClear();
1703 }
1704 
1705 //===== TimeLabel =============================================================
1706 
1707 TimeLabel::TimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1708  : Label(rpToolBar),
1709  mpListener()
1710 {
1711 }
1712 
1713 void SAL_CALL TimeLabel::disposing()
1714 {
1715  PresenterClockTimer::Instance(mpToolBar->GetComponentContext())->RemoveListener(mpListener);
1716  mpListener.reset();
1717 }
1718 
1719 void TimeLabel::ConnectToTimer()
1720 {
1721  mpListener = std::make_shared<Listener>(this);
1722  PresenterClockTimer::Instance(mpToolBar->GetComponentContext())->AddListener(mpListener);
1723 }
1724 
1725 //===== CurrentTimeLabel ======================================================
1726 
1727 ::rtl::Reference<Element> CurrentTimeLabel::Create (
1728  const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1729 {
1730  ::rtl::Reference<TimeLabel> pElement(new CurrentTimeLabel(rpToolBar));
1731  pElement->ConnectToTimer();
1732  return ::rtl::Reference<Element>(pElement.get());
1733 }
1734 
1735 CurrentTimeLabel::~CurrentTimeLabel()
1736 {
1737 }
1738 
1739 CurrentTimeLabel::CurrentTimeLabel (
1740  const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1741  : TimeLabel(rpToolBar)
1742 {
1743 }
1744 
1745 void CurrentTimeLabel::TimeHasChanged (const oslDateTime& rCurrentTime)
1746 {
1747  SetText(TimeFormatter::FormatTime(rCurrentTime));
1748  Invalidate(false);
1749 }
1750 
1751 void CurrentTimeLabel::SetModes (
1752  const SharedElementMode& rpNormalMode,
1753  const SharedElementMode& rpMouseOverMode,
1754  const SharedElementMode& rpSelectedMode,
1755  const SharedElementMode& rpDisabledMode)
1756 {
1757  TimeLabel::SetModes(rpNormalMode, rpMouseOverMode, rpSelectedMode, rpDisabledMode);
1759 }
1760 
1761 //===== PresentationTimeLabel =================================================
1762 
1763 ::rtl::Reference<Element> PresentationTimeLabel::Create (
1764  const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1765 {
1766  ::rtl::Reference<TimeLabel> pElement(new PresentationTimeLabel(rpToolBar));
1767  pElement->ConnectToTimer();
1768  return ::rtl::Reference<Element>(pElement.get());
1769 }
1770 
1771 PresentationTimeLabel::~PresentationTimeLabel()
1772 {
1773  mpToolBar->GetPresenterController()->SetPresentationTime(nullptr);
1774 }
1775 
1776 PresentationTimeLabel::PresentationTimeLabel (
1777  const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1778  : TimeLabel(rpToolBar),
1780 {
1781  restart();
1782  mpToolBar->GetPresenterController()->SetPresentationTime(this);
1783 }
1784 
1785 void PresentationTimeLabel::restart()
1786 {
1787  maStartTimeValue.Seconds = 0;
1788  maStartTimeValue.Nanosec = 0;
1789 }
1790 
1791 void PresentationTimeLabel::TimeHasChanged (const oslDateTime& rCurrentTime)
1792 {
1793  TimeValue aCurrentTimeValue;
1794  if (!osl_getTimeValueFromDateTime(&rCurrentTime, &aCurrentTimeValue))
1795  return;
1796 
1797  if (maStartTimeValue.Seconds==0 && maStartTimeValue.Nanosec==0)
1798  {
1799  // This method is called for the first time. Initialize the
1800  // start time. The start time is rounded to nearest second to
1801  // keep the time updates synchronized with the current time label.
1802  maStartTimeValue = aCurrentTimeValue;
1803  if (maStartTimeValue.Nanosec >= 500000000)
1804  maStartTimeValue.Seconds += 1;
1805  maStartTimeValue.Nanosec = 0;
1806  }
1807 
1808  TimeValue aElapsedTimeValue;
1809  aElapsedTimeValue.Seconds = aCurrentTimeValue.Seconds - maStartTimeValue.Seconds;
1810  aElapsedTimeValue.Nanosec = aCurrentTimeValue.Nanosec - maStartTimeValue.Nanosec;
1811 
1812  oslDateTime aElapsedDateTime;
1813  if (osl_getDateTimeFromTimeValue(&aElapsedTimeValue, &aElapsedDateTime))
1814  {
1815  SetText(TimeFormatter::FormatTime(aElapsedDateTime));
1816  Invalidate(false);
1817  }
1818 }
1819 
1820 void PresentationTimeLabel::SetModes (
1821  const SharedElementMode& rpNormalMode,
1822  const SharedElementMode& rpMouseOverMode,
1823  const SharedElementMode& rpSelectedMode,
1824  const SharedElementMode& rpDisabledMode)
1825 {
1826  TimeLabel::SetModes(rpNormalMode, rpMouseOverMode, rpSelectedMode, rpDisabledMode);
1827 
1828  oslDateTime aStartDateTime;
1829  if (osl_getDateTimeFromTimeValue(&maStartTimeValue, &aStartDateTime))
1830  {
1831  SetText(TimeFormatter::FormatTime(aStartDateTime));
1832  }
1833 }
1834 
1835 //===== VerticalSeparator =====================================================
1836 
1837 VerticalSeparator::VerticalSeparator (
1838  const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1839  : Element(rpToolBar)
1840 {
1841 }
1842 
1843 void VerticalSeparator::Paint (
1844  const Reference<rendering::XCanvas>& rxCanvas,
1845  const rendering::ViewState& rViewState)
1846 {
1847  OSL_ASSERT(rxCanvas.is());
1848 
1849  awt::Rectangle aBBox (GetBoundingBox());
1850 
1851  rendering::RenderState aRenderState(
1852  geometry::AffineMatrix2D(1,0,0, 0,1,0),
1853  nullptr,
1854  Sequence<double>(4),
1855  rendering::CompositeOperation::OVER);
1856  if (mpMode.get() != nullptr)
1857  {
1858  PresenterTheme::SharedFontDescriptor pFont (mpMode->maText.GetFont());
1859  if (pFont.get() != nullptr)
1860  PresenterCanvasHelper::SetDeviceColor(aRenderState, pFont->mnColor);
1861  }
1862 
1863  rxCanvas->fillPolyPolygon(
1864  PresenterGeometryHelper::CreatePolygon(aBBox, rxCanvas->getDevice()),
1865  rViewState,
1866  aRenderState);
1867 }
1868 
1869 awt::Size VerticalSeparator::CreateBoundingSize (
1870  const Reference<rendering::XCanvas>&)
1871 {
1872  return awt::Size(1,20);
1873 }
1874 
1875 bool VerticalSeparator::IsFilling() const
1876 {
1877  return true;
1878 }
1879 
1880 //===== HorizontalSeparator ===================================================
1881 
1882 HorizontalSeparator::HorizontalSeparator (
1883  const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1884  : Element(rpToolBar)
1885 {
1886 }
1887 
1888 void HorizontalSeparator::Paint (
1889  const Reference<rendering::XCanvas>& rxCanvas,
1890  const rendering::ViewState& rViewState)
1891 {
1892  OSL_ASSERT(rxCanvas.is());
1893 
1894  awt::Rectangle aBBox (GetBoundingBox());
1895 
1896  rendering::RenderState aRenderState(
1897  geometry::AffineMatrix2D(1,0,0, 0,1,0),
1898  nullptr,
1899  Sequence<double>(4),
1900  rendering::CompositeOperation::OVER);
1901  if (mpMode.get() != nullptr)
1902  {
1903  PresenterTheme::SharedFontDescriptor pFont (mpMode->maText.GetFont());
1904  if (pFont.get() != nullptr)
1905  PresenterCanvasHelper::SetDeviceColor(aRenderState, pFont->mnColor);
1906  }
1907 
1908  rxCanvas->fillPolyPolygon(
1909  PresenterGeometryHelper::CreatePolygon(aBBox, rxCanvas->getDevice()),
1910  rViewState,
1911  aRenderState);
1912 }
1913 
1914 awt::Size HorizontalSeparator::CreateBoundingSize (
1915  const Reference<rendering::XCanvas>&)
1916 {
1917  return awt::Size(20,1);
1918 }
1919 
1920 bool HorizontalSeparator::IsFilling() const
1921 {
1922  return true;
1923 }
1924 
1925 } // end of anonymous namespace
1926 
1927 } // end of namespace ::sdext::presenter
1928 
1929 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< rendering::XCanvas > mxCanvas
::rtl::Reference< PresenterController > mpPresenterController
URL aURL
std::shared_ptr< FontDescriptor > SharedFontDescriptor
sal_Int32 nIndex
static css::uno::Any GetProperty(const css::uno::Reference< css::beans::XPropertySet > &rxProperties, const OUString &rsKey)
This method wraps a call to getPropertyValue() and returns an empty Any instead of throwing an except...
osl::Mutex m_aMutex
bool mbIsPressed
Button(WindowType nType)
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
std::shared_ptr< ElementContainerPart > SharedElementContainerPart
SharedElementMode mpMouseOver
SharedElementMode mpDisabled
awt::Point maLocation
awt::Size maSize
::rtl::Reference< PresenterToolBar > mpToolBar
SharedElementMode mpSelected
static css::uno::Reference< css::beans::XPropertySet > GetNodeProperties(const css::uno::Reference< css::container::XHierarchicalNameAccess > &rxNode, const OUString &rsPathToNode)
Center
SharedBitmapDescriptor mpIcon
css::uno::Reference< css::awt::XWindow > mxWindow
SharedElementMode mpMode
std::shared_ptr< PresenterBitmapContainer::BitmapDescriptor > SharedBitmapDescriptor
This class gives access to the configuration.
css::uno::Reference< css::rendering::XCanvas > mxCanvas
static::rtl::Reference< PresenterClockTimer > Instance(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
Reference< drawing::XPresenterHelper > mxPresenterHelper
OUString msText
css::uno::Reference< css::lang::XComponent > xComponent
css::uno::Reference< css::uno::XComponentContext > mxComponentContext
OptionalString sType
bool mbIsEnabled
static SharedFontDescriptor ReadFont(const css::uno::Reference< css::container::XHierarchicalNameAccess > &rxNode, const SharedFontDescriptor &rDefaultFount)
virtual sal_Bool SAL_CALL isAnchorOnly() override
virtual void SAL_CALL setCurrentPage(const css::uno::Reference< css::drawing::XDrawPage > &rxSlide) override
css::uno::Any GetConfigurationNode(const OUString &rsPathToNode)
Return a configuration node below the root of the called object.
unsigned char sal_Bool
static bool GetLayoutRTL()
PresenterTheme::SharedFontDescriptor mpFont
css::uno::Reference< css::awt::XWindow > mxWindow
const ::rtl::Reference< PresenterToolBar > & GetPresenterToolBar() const
css::uno::Reference< css::drawing::framework::XResourceId > mxViewId
std::shared_ptr< PresenterClockTimer::Listener > mpListener
::rtl::Reference< PresenterToolBar > mpToolBar
SharedElementMode mpNormal
static css::uno::Reference< css::rendering::XPolyPolygon2D > CreatePolygon(const css::awt::Rectangle &rBox, const css::uno::Reference< css::rendering::XGraphicDevice > &rxDevice)
virtual void SAL_CALL disposing() override
::rtl::Reference< TimeLabel > mxLabel
bool mbIsListenerRegistered
css::uno::Reference< css::rendering::XCanvas > mxCanvas
Context & operator=(const Context &)=delete
Reference< XDispatch > xDispatch
rtl::Reference< PresenterController > mpPresenterController
css::uno::Reference< css::rendering::XCanvas > mxCanvas
Text maText
OUString msAction
css::uno::Reference< css::drawing::framework::XPane > mxPane
static std::shared_ptr< BitmapDescriptor > LoadBitmap(const css::uno::Reference< css::container::XHierarchicalNameAccess > &rxNode, const OUString &rsPathToBitmapNode, const css::uno::Reference< css::drawing::XPresenterHelper > &rxPresenterHelper, const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const std::shared_ptr< BitmapDescriptor > &rpDefaultBitmap)
cppu::WeakComponentImplHelper< css::awt::XWindowListener, css::awt::XPaintListener, css::awt::XMouseListener, css::awt::XMouseMotionListener, css::drawing::XDrawView > PresenterToolBarInterfaceBase
bool bIsEnabled
PresenterToolBar(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const css::uno::Reference< css::awt::XWindow > &rxWindow, const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const ::rtl::Reference< PresenterController > &rpPresenterController, const Anchor eAnchor)
static void SetDeviceColor(css::rendering::RenderState &rRenderState, const css::util::Color aColor)
virtual css::uno::Reference< css::drawing::framework::XResourceId > SAL_CALL getResourceId() override
TimeValue maStartTimeValue
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect)
virtual void SAL_CALL windowPaint(const css::awt::PaintEvent &rEvent) override
cppu::WeakComponentImplHelper< css::awt::XPaintListener, css::drawing::framework::XView, css::drawing::XDrawView > PresenterToolBarViewInterfaceBase
static OUString FormatTime(const tools::Time &rNewTime, TimeFieldFormat eFormat, TimeFormat eHourFormat, bool bDuration, const LocaleDataWrapper &rLocaleData)
static const sal_Int32 gnGapSize(20)
bool mbIsSelected
Layout
UpdateState
Left
virtual css::uno::Reference< css::drawing::XDrawPage > SAL_CALL getCurrentPage() override
bool mbIsOver