Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sdext / source / presenter / PresenterToolBar.cxx
blob553ce220ca0d32bfd92bdb308f041862c4ca2dff
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <vcl/svapp.hxx>
21 #include <vcl/settings.hxx>
22 #include "PresenterToolBar.hxx"
24 #include "PresenterBitmapContainer.hxx"
25 #include "PresenterCanvasHelper.hxx"
26 #include "PresenterGeometryHelper.hxx"
27 #include "PresenterPaintManager.hxx"
28 #include "PresenterPaneBase.hxx"
29 #include "PresenterPaneFactory.hxx"
30 #include "PresenterTimer.hxx"
31 #include "PresenterWindowManager.hxx"
33 #include <cppuhelper/compbase.hxx>
34 #include <com/sun/star/awt/FontDescriptor.hpp>
35 #include <com/sun/star/awt/PosSize.hpp>
36 #include <com/sun/star/awt/XWindowPeer.hpp>
37 #include <com/sun/star/deployment/XPackageInformationProvider.hpp>
38 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
39 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
40 #include <com/sun/star/drawing/framework/XPane.hpp>
41 #include <com/sun/star/geometry/AffineMatrix2D.hpp>
42 #include <com/sun/star/lang/XServiceName.hpp>
43 #include <com/sun/star/rendering/CompositeOperation.hpp>
44 #include <com/sun/star/rendering/RenderState.hpp>
45 #include <com/sun/star/rendering/TextDirection.hpp>
46 #include <com/sun/star/rendering/ViewState.hpp>
47 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
48 #include <com/sun/star/text/XTextRange.hpp>
49 #include <com/sun/star/util/Color.hpp>
50 #include <com/sun/star/util/XURLTransformer.hpp>
51 #include <rtl/ustrbuf.hxx>
53 using namespace ::com::sun::star;
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::drawing::framework;
57 namespace sdext { namespace presenter {
59 static const sal_Int32 gnGapSize (20);
61 namespace {
63 class Text
65 public:
66 Text();
67 Text (
68 const OUString& rsText,
69 const PresenterTheme::SharedFontDescriptor& rpFont);
71 void SetText (const OUString& rsText);
72 const OUString& GetText() const;
73 const PresenterTheme::SharedFontDescriptor& GetFont() const;
75 void Paint (
76 const Reference<rendering::XCanvas>& rxCanvas,
77 const rendering::ViewState& rViewState,
78 const awt::Rectangle& rBoundingBox);
80 geometry::RealRectangle2D GetBoundingBox (
81 const Reference<rendering::XCanvas>& rxCanvas);
83 private:
84 OUString msText;
85 PresenterTheme::SharedFontDescriptor mpFont;
88 class ElementMode
90 public:
91 ElementMode();
92 ElementMode(const ElementMode&) = delete;
93 ElementMode& operator=(const ElementMode&) = delete;
95 SharedBitmapDescriptor mpIcon;
96 OUString msAction;
97 Text maText;
99 void ReadElementMode (
100 const Reference<beans::XPropertySet>& rxProperties,
101 const OUString& rsModeName,
102 std::shared_ptr<ElementMode> const & rpDefaultMode,
103 ::sdext::presenter::PresenterToolBar::Context const & rContext);
105 typedef std::shared_ptr<ElementMode> SharedElementMode;
107 } // end of anonymous namespace
109 class PresenterToolBar::Context
111 public:
112 Context() = default;
113 Context(const Context&) = delete;
114 Context& operator=(const Context&) = delete;
115 Reference<drawing::XPresenterHelper> mxPresenterHelper;
116 css::uno::Reference<css::rendering::XCanvas> mxCanvas;
119 //===== PresenterToolBar::Element =============================================
121 namespace {
122 typedef cppu::WeakComponentImplHelper<
123 css::document::XEventListener,
124 css::frame::XStatusListener
125 > ElementInterfaceBase;
127 class Element
128 : private ::cppu::BaseMutex,
129 public ElementInterfaceBase
131 public:
132 explicit Element (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
133 Element(const Element&) = delete;
134 Element& operator=(const Element&) = delete;
136 virtual void SAL_CALL disposing() override;
138 virtual void SetModes (
139 const SharedElementMode& rpNormalMode,
140 const SharedElementMode& rpMouseOverMode,
141 const SharedElementMode& rpSelectedMode,
142 const SharedElementMode& rpDisabledMode);
143 void CurrentSlideHasChanged();
144 void SetLocation (const awt::Point& rLocation);
145 void SetSize (const geometry::RealSize2D& rSize);
146 virtual void Paint (
147 const Reference<rendering::XCanvas>& rxCanvas,
148 const rendering::ViewState& rViewState) = 0;
149 awt::Size const & GetBoundingSize (
150 const Reference<rendering::XCanvas>& rxCanvas);
151 awt::Rectangle GetBoundingBox() const;
152 virtual bool SetState (const bool bIsOver, const bool bIsPressed);
153 void Invalidate (const bool bSynchronous);
154 bool IsOutside (const awt::Rectangle& rBox);
155 virtual bool IsFilling() const;
156 void UpdateState();
158 // lang::XEventListener
160 virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) override;
162 // document::XEventListener
164 virtual void SAL_CALL notifyEvent (const css::document::EventObject& rEvent) override;
166 // frame::XStatusListener
168 virtual void SAL_CALL statusChanged (const css::frame::FeatureStateEvent& rEvent) override;
170 protected:
171 ::rtl::Reference<PresenterToolBar> mpToolBar;
172 awt::Point maLocation;
173 awt::Size maSize;
174 SharedElementMode mpNormal;
175 SharedElementMode mpMouseOver;
176 SharedElementMode mpSelected;
177 SharedElementMode mpDisabled;
178 SharedElementMode mpMode;
179 bool mbIsOver;
180 bool mbIsPressed;
181 bool mbIsSelected;
183 virtual awt::Size CreateBoundingSize (
184 const Reference<rendering::XCanvas>& rxCanvas) = 0;
186 bool IsEnabled() const { return mbIsEnabled;}
187 private:
188 bool mbIsEnabled;
191 } // end of anonymous namespace
193 class PresenterToolBar::ElementContainerPart
194 : public ::std::vector<rtl::Reference<Element> >
198 //===== Button ================================================================
200 namespace {
202 class Button : public Element
204 public:
205 static ::rtl::Reference<Element> Create (
206 const ::rtl::Reference<PresenterToolBar>& rpToolBar);
208 virtual void SAL_CALL disposing() override;
210 virtual void Paint (
211 const Reference<rendering::XCanvas>& rxCanvas,
212 const rendering::ViewState& rViewState) override;
214 // lang::XEventListener
216 virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) override;
218 protected:
219 virtual awt::Size CreateBoundingSize (
220 const Reference<rendering::XCanvas>& rxCanvas) override;
222 private:
223 bool mbIsListenerRegistered;
225 Button (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
226 void Initialize();
227 void PaintIcon (
228 const Reference<rendering::XCanvas>& rxCanvas,
229 const sal_Int32 nTextHeight,
230 const rendering::ViewState& rViewState);
231 PresenterBitmapDescriptor::Mode GetMode() const;
234 //===== Label =================================================================
236 class Label : public Element
238 public:
239 explicit Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
241 void SetText (const OUString& rsText);
242 virtual void Paint (
243 const Reference<rendering::XCanvas>& rxCanvas,
244 const rendering::ViewState& rViewState) override;
245 virtual bool SetState (const bool bIsOver, const bool bIsPressed) override;
247 protected:
248 virtual awt::Size CreateBoundingSize (
249 const Reference<rendering::XCanvas>& rxCanvas) override;
252 // Some specialized controls.
254 class TimeFormatter
256 public:
257 static OUString FormatTime (const oslDateTime& rTime);
260 class TimeLabel : public Label
262 public:
263 void ConnectToTimer();
264 virtual void TimeHasChanged (const oslDateTime& rCurrentTime) = 0;
265 protected:
266 explicit TimeLabel(const ::rtl::Reference<PresenterToolBar>& rpToolBar);
267 using Element::disposing;
268 virtual void SAL_CALL disposing() override;
269 private:
270 class Listener : public PresenterClockTimer::Listener
272 public:
273 explicit Listener (const ::rtl::Reference<TimeLabel>& rxLabel)
274 : mxLabel(rxLabel) {}
275 virtual ~Listener() {}
276 virtual void TimeHasChanged (const oslDateTime& rCurrentTime) override
277 { if (mxLabel.is()) mxLabel->TimeHasChanged(rCurrentTime); }
278 private:
279 ::rtl::Reference<TimeLabel> mxLabel;
281 std::shared_ptr<PresenterClockTimer::Listener> mpListener;
284 class CurrentTimeLabel : public TimeLabel
286 public:
287 static ::rtl::Reference<Element> Create (
288 const ::rtl::Reference<PresenterToolBar>& rpToolBar);
289 virtual void SetModes (
290 const SharedElementMode& rpNormalMode,
291 const SharedElementMode& rpMouseOverMode,
292 const SharedElementMode& rpSelectedMode,
293 const SharedElementMode& rpDisabledMode) override;
294 private:
295 CurrentTimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
296 virtual ~CurrentTimeLabel() override;
297 virtual void TimeHasChanged (const oslDateTime& rCurrentTime) override;
300 class PresentationTimeLabel : public TimeLabel, public IPresentationTime
302 public:
303 static ::rtl::Reference<Element> Create (
304 const ::rtl::Reference<PresenterToolBar>& rpToolBar);
305 virtual void SetModes (
306 const SharedElementMode& rpNormalMode,
307 const SharedElementMode& rpMouseOverMode,
308 const SharedElementMode& rpSelectedMode,
309 const SharedElementMode& rpDisabledMode) override;
310 virtual void restart() override;
311 private:
312 TimeValue maStartTimeValue;
313 PresentationTimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
314 virtual ~PresentationTimeLabel() override;
315 virtual void TimeHasChanged (const oslDateTime& rCurrentTime) override;
318 class VerticalSeparator : public Element
320 public:
321 explicit VerticalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
322 virtual void Paint (
323 const Reference<rendering::XCanvas>& rxCanvas,
324 const rendering::ViewState& rViewState) override;
325 virtual bool IsFilling() const override;
327 protected:
328 virtual awt::Size CreateBoundingSize (
329 const Reference<rendering::XCanvas>& rxCanvas) override;
332 class HorizontalSeparator : public Element
334 public:
335 explicit HorizontalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
336 virtual void Paint (
337 const Reference<rendering::XCanvas>& rxCanvas,
338 const rendering::ViewState& rViewState) override;
339 virtual bool IsFilling() const override;
341 protected:
342 virtual awt::Size CreateBoundingSize (
343 const Reference<rendering::XCanvas>& rxCanvas) override;
345 } // end of anonymous namespace
347 //===== PresenterToolBar ======================================================
349 PresenterToolBar::PresenterToolBar (
350 const Reference<XComponentContext>& rxContext,
351 const css::uno::Reference<css::awt::XWindow>& rxWindow,
352 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
353 const ::rtl::Reference<PresenterController>& rpPresenterController,
354 const Anchor eAnchor)
355 : PresenterToolBarInterfaceBase(m_aMutex),
356 mxComponentContext(rxContext),
357 maElementContainer(),
358 mpCurrentContainerPart(),
359 mxWindow(rxWindow),
360 mxCanvas(rxCanvas),
361 mxSlideShowController(),
362 mxCurrentSlide(),
363 mpPresenterController(rpPresenterController),
364 mbIsLayoutPending(false),
365 meAnchor(eAnchor),
366 maMinimalSize()
370 void PresenterToolBar::Initialize (
371 const OUString& rsConfigurationPath)
375 CreateControls(rsConfigurationPath);
377 if (mxWindow.is())
379 mxWindow->addWindowListener(this);
380 mxWindow->addPaintListener(this);
381 mxWindow->addMouseListener(this);
382 mxWindow->addMouseMotionListener(this);
384 Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
385 if (xPeer.is())
386 xPeer->setBackground(util::Color(0xff000000));
388 mxWindow->setVisible(true);
391 mxSlideShowController = mpPresenterController->GetSlideShowController();
392 UpdateSlideNumber();
393 mbIsLayoutPending = true;
395 catch (RuntimeException&)
397 mpCurrentContainerPart.reset();
398 maElementContainer.clear();
399 throw;
403 PresenterToolBar::~PresenterToolBar()
407 void SAL_CALL PresenterToolBar::disposing()
409 if (mxWindow.is())
411 mxWindow->removeWindowListener(this);
412 mxWindow->removePaintListener(this);
413 mxWindow->removeMouseListener(this);
414 mxWindow->removeMouseMotionListener(this);
415 mxWindow = nullptr;
418 // Dispose tool bar elements.
419 ElementContainer::iterator iPart (maElementContainer.begin());
420 ElementContainer::const_iterator iEnd (maElementContainer.end());
421 for ( ; iPart!=iEnd; ++iPart)
423 OSL_ASSERT(iPart->get()!=nullptr);
424 ElementContainerPart::iterator iElement ((*iPart)->begin());
425 ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
426 for ( ; iElement!=iPartEnd; ++iElement)
428 if (iElement->get() != nullptr)
430 ::rtl::Reference<Element> pElement (*iElement);
431 Reference<lang::XComponent> xComponent (
432 static_cast<XWeak*>(pElement.get()), UNO_QUERY);
433 if (xComponent.is())
434 xComponent->dispose();
439 mpCurrentContainerPart.reset();
440 maElementContainer.clear();
443 void PresenterToolBar::InvalidateArea (
444 const awt::Rectangle& rRepaintBox,
445 const bool bSynchronous)
447 std::shared_ptr<PresenterPaintManager> xManager(mpPresenterController->GetPaintManager());
448 if (!xManager)
449 return;
450 xManager->Invalidate(
451 mxWindow,
452 rRepaintBox,
453 bSynchronous);
456 void PresenterToolBar::RequestLayout()
458 mbIsLayoutPending = true;
460 std::shared_ptr<PresenterPaintManager> xManager(mpPresenterController->GetPaintManager());
461 if (!xManager)
462 return;
464 xManager->Invalidate(mxWindow);
467 geometry::RealSize2D const & PresenterToolBar::GetMinimalSize()
469 if (mbIsLayoutPending)
470 Layout(mxCanvas);
471 return maMinimalSize;
474 const ::rtl::Reference<PresenterController>& PresenterToolBar::GetPresenterController() const
476 return mpPresenterController;
479 const Reference<XComponentContext>& PresenterToolBar::GetComponentContext() const
481 return mxComponentContext;
484 //----- lang::XEventListener -------------------------------------------------
486 void SAL_CALL PresenterToolBar::disposing (const lang::EventObject& rEventObject)
488 if (rEventObject.Source == mxWindow)
489 mxWindow = nullptr;
492 //----- XWindowListener -------------------------------------------------------
494 void SAL_CALL PresenterToolBar::windowResized (const awt::WindowEvent&)
496 mbIsLayoutPending = true;
499 void SAL_CALL PresenterToolBar::windowMoved (const awt::WindowEvent&) {}
501 void SAL_CALL PresenterToolBar::windowShown (const lang::EventObject&)
503 mbIsLayoutPending = true;
506 void SAL_CALL PresenterToolBar::windowHidden (const lang::EventObject&) {}
508 //----- XPaintListener --------------------------------------------------------
509 void SAL_CALL PresenterToolBar::windowPaint (const css::awt::PaintEvent& rEvent)
511 if ( ! mxCanvas.is())
512 return;
514 if ( ! mbIsPresenterViewActive)
515 return;
517 const rendering::ViewState aViewState (
518 geometry::AffineMatrix2D(1,0,0, 0,1,0),
519 PresenterGeometryHelper::CreatePolygon(rEvent.UpdateRect, mxCanvas->getDevice()));
521 if (mbIsLayoutPending)
522 Layout(mxCanvas);
524 Paint(rEvent.UpdateRect, aViewState);
526 // Make the back buffer visible.
527 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
528 if (xSpriteCanvas.is())
529 xSpriteCanvas->updateScreen(false);
532 //----- XMouseListener --------------------------------------------------------
533 void SAL_CALL PresenterToolBar::mousePressed (const css::awt::MouseEvent& rEvent)
535 ThrowIfDisposed();
536 CheckMouseOver(rEvent, true, true);
539 void SAL_CALL PresenterToolBar::mouseReleased (const css::awt::MouseEvent& rEvent)
541 ThrowIfDisposed();
542 CheckMouseOver(rEvent, true);
545 void SAL_CALL PresenterToolBar::mouseEntered (const css::awt::MouseEvent& rEvent)
547 ThrowIfDisposed();
548 CheckMouseOver(rEvent, true);
551 void SAL_CALL PresenterToolBar::mouseExited (const css::awt::MouseEvent& rEvent)
553 ThrowIfDisposed();
554 CheckMouseOver(rEvent, false);
557 //----- XMouseMotionListener --------------------------------------------------
559 void SAL_CALL PresenterToolBar::mouseMoved (const css::awt::MouseEvent& rEvent)
561 ThrowIfDisposed();
562 CheckMouseOver(rEvent, true);
565 void SAL_CALL PresenterToolBar::mouseDragged (const css::awt::MouseEvent&)
567 ThrowIfDisposed();
570 //----- XDrawView -------------------------------------------------------------
572 void SAL_CALL PresenterToolBar::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
574 if (rxSlide != mxCurrentSlide)
576 mxCurrentSlide = rxSlide;
577 UpdateSlideNumber();
581 Reference<drawing::XDrawPage> SAL_CALL PresenterToolBar::getCurrentPage()
583 return mxCurrentSlide;
587 void PresenterToolBar::CreateControls (
588 const OUString& rsConfigurationPath)
590 if ( ! mxWindow.is())
591 return;
593 // Expand the macro in the bitmap file names.
594 PresenterConfigurationAccess aConfiguration (
595 mxComponentContext,
596 "/org.openoffice.Office.PresenterScreen/",
597 PresenterConfigurationAccess::READ_ONLY);
599 mpCurrentContainerPart.reset(new ElementContainerPart);
600 maElementContainer.clear();
601 maElementContainer.push_back(mpCurrentContainerPart);
603 Reference<container::XHierarchicalNameAccess> xToolBarNode (
604 aConfiguration.GetConfigurationNode(rsConfigurationPath),
605 UNO_QUERY);
606 if (xToolBarNode.is())
608 Reference<container::XNameAccess> xEntries (
609 PresenterConfigurationAccess::GetConfigurationNode(xToolBarNode, "Entries"),
610 UNO_QUERY);
611 Context aContext;
612 aContext.mxPresenterHelper = mpPresenterController->GetPresenterHelper();
613 aContext.mxCanvas = mxCanvas;
614 if (xEntries.is()
615 && aContext.mxPresenterHelper.is()
616 && aContext.mxCanvas.is())
618 PresenterConfigurationAccess::ForAll(
619 xEntries,
620 [this, &aContext] (OUString const&, uno::Reference<beans::XPropertySet> const& xProps)
622 return this->ProcessEntry(xProps, aContext);
628 void PresenterToolBar::ProcessEntry (
629 const Reference<beans::XPropertySet>& rxProperties,
630 Context const & rContext)
632 if ( ! rxProperties.is())
633 return;
635 // Type has to be present.
636 OUString sType;
637 if ( ! (PresenterConfigurationAccess::GetProperty(rxProperties, "Type") >>= sType))
638 return;
640 OUString sName;
641 PresenterConfigurationAccess::GetProperty(rxProperties, "Name") >>= sName;
643 // Read mode specific values.
644 SharedElementMode pNormalMode (new ElementMode());
645 SharedElementMode pMouseOverMode (new ElementMode());
646 SharedElementMode pSelectedMode (new ElementMode());
647 SharedElementMode pDisabledMode (new ElementMode());
648 pNormalMode->ReadElementMode(rxProperties, "Normal", pNormalMode, rContext);
649 pMouseOverMode->ReadElementMode(rxProperties, "MouseOver", pNormalMode, rContext);
650 pSelectedMode->ReadElementMode(rxProperties, "Selected", pNormalMode, rContext);
651 pDisabledMode->ReadElementMode(rxProperties, "Disabled", pNormalMode, rContext);
653 // Create new element.
654 ::rtl::Reference<Element> pElement;
655 if ( sType == "Button" )
656 pElement = Button::Create(this);
657 else if ( sType == "CurrentTimeLabel" )
658 pElement = CurrentTimeLabel::Create(this);
659 else if ( sType == "PresentationTimeLabel" )
660 pElement = PresentationTimeLabel::Create(this);
661 else if ( sType == "VerticalSeparator" )
662 pElement.set(new VerticalSeparator(this));
663 else if ( sType == "HorizontalSeparator" )
664 pElement.set(new HorizontalSeparator(this));
665 else if ( sType == "Label" )
666 pElement.set(new Label(this));
667 else if ( sType == "ChangeOrientation" )
669 mpCurrentContainerPart.reset(new ElementContainerPart);
670 maElementContainer.push_back(mpCurrentContainerPart);
671 return;
673 if (pElement.is())
675 pElement->SetModes( pNormalMode, pMouseOverMode, pSelectedMode, pDisabledMode);
676 pElement->UpdateState();
677 if (mpCurrentContainerPart.get() != nullptr)
678 mpCurrentContainerPart->push_back(pElement);
682 void PresenterToolBar::Layout (
683 const Reference<rendering::XCanvas>& rxCanvas)
685 if (maElementContainer.empty())
686 return;
688 mbIsLayoutPending = false;
690 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
691 ElementContainer::iterator iPart;
692 ElementContainer::iterator iEnd (maElementContainer.end());
693 ElementContainer::iterator iBegin (maElementContainer.begin());
694 ::std::vector<geometry::RealSize2D> aPartSizes (maElementContainer.size());
695 geometry::RealSize2D aTotalSize (0,0);
696 bool bIsHorizontal (true);
697 sal_Int32 nIndex;
698 double nTotalHorizontalGap (0);
699 sal_Int32 nGapCount (0);
700 for (iPart=maElementContainer.begin(),nIndex=0; iPart!=iEnd; ++iPart,++nIndex)
702 geometry::RealSize2D aSize (CalculatePartSize(rxCanvas, *iPart, bIsHorizontal));
704 // Remember the size of each part for later.
705 aPartSizes[nIndex] = aSize;
707 // Add gaps between elements.
708 if ((*iPart)->size()>1 && bIsHorizontal)
710 nTotalHorizontalGap += ((*iPart)->size() - 1) * gnGapSize;
711 nGapCount += (*iPart)->size()-1;
714 // Orientation changes for each part.
715 bIsHorizontal = !bIsHorizontal;
716 // Width is accumulated.
717 aTotalSize.Width += aSize.Width;
718 // Height is the maximum height of all parts.
719 aTotalSize.Height = ::std::max(aTotalSize.Height, aSize.Height);
721 // Add gaps between parts.
722 if (maElementContainer.size() > 1)
724 nTotalHorizontalGap += (maElementContainer.size() - 1) * gnGapSize;
725 nGapCount += maElementContainer.size()-1;
728 // Calculate the minimal size so that the window size of the tool bar
729 // can be adapted accordingly.
730 maMinimalSize = aTotalSize;
731 maMinimalSize.Width += nTotalHorizontalGap;
733 // Calculate the gaps between elements.
734 double nGapWidth (0);
735 if (nGapCount > 0)
737 if (aTotalSize.Width + nTotalHorizontalGap > aWindowBox.Width)
738 nTotalHorizontalGap = aWindowBox.Width - aTotalSize.Width;
739 nGapWidth = nTotalHorizontalGap / nGapCount;
742 // Determine the location of the left edge.
743 double nX (0);
744 switch (meAnchor)
746 case Left : nX = 0; break;
747 case Center: nX = (aWindowBox.Width - aTotalSize.Width - nTotalHorizontalGap) / 2; break;
750 // Place the parts.
751 double nY ((aWindowBox.Height - aTotalSize.Height) / 2);
752 bIsHorizontal = true;
754 /* push front or back ? ... */
755 /// check whether RTL interface or not
756 if(!AllSettings::GetLayoutRTL()){
757 for (iPart=maElementContainer.begin(), nIndex=0; iPart!=iEnd; ++iPart,++nIndex)
759 geometry::RealRectangle2D aBoundingBox(
760 nX, nY,
761 nX+aPartSizes[nIndex].Width, nY+aTotalSize.Height);
763 // Add space for gaps between elements.
764 if ((*iPart)->size() > 1)
765 if (bIsHorizontal)
766 aBoundingBox.X2 += ((*iPart)->size()-1) * nGapWidth;
768 LayoutPart(rxCanvas, *iPart, aBoundingBox, aPartSizes[nIndex], bIsHorizontal);
769 bIsHorizontal = !bIsHorizontal;
770 nX += aBoundingBox.X2 - aBoundingBox.X1 + nGapWidth;
773 else {
774 for (iPart=maElementContainer.end()-1, nIndex=2; iPart!=iBegin-1; --iPart, --nIndex)
776 geometry::RealRectangle2D aBoundingBox(
777 nX, nY,
778 nX+aPartSizes[nIndex].Width, nY+aTotalSize.Height);
780 // Add space for gaps between elements.
781 if ((*iPart)->size() > 1)
782 if (bIsHorizontal)
783 aBoundingBox.X2 += ((*iPart)->size()-1) * nGapWidth;
785 LayoutPart(rxCanvas, *iPart, aBoundingBox, aPartSizes[nIndex], bIsHorizontal);
786 bIsHorizontal = !bIsHorizontal;
787 nX += aBoundingBox.X2 - aBoundingBox.X1 + nGapWidth;
791 // The whole window has to be repainted.
792 std::shared_ptr<PresenterPaintManager> xManager(mpPresenterController->GetPaintManager());
793 if (!xManager)
794 return;
795 xManager->Invalidate(mxWindow);
798 geometry::RealSize2D PresenterToolBar::CalculatePartSize (
799 const Reference<rendering::XCanvas>& rxCanvas,
800 const SharedElementContainerPart& rpPart,
801 const bool bIsHorizontal)
803 geometry::RealSize2D aTotalSize (0,0);
805 if (mxWindow.is())
807 // Calculate the summed width of all elements.
808 ElementContainerPart::const_iterator iElement;
809 for (iElement=rpPart->begin(); iElement!=rpPart->end(); ++iElement)
811 if (iElement->get() == nullptr)
812 continue;
814 const awt::Size aBSize ((*iElement)->GetBoundingSize(rxCanvas));
815 if (bIsHorizontal)
817 aTotalSize.Width += aBSize.Width;
818 if (aBSize.Height > aTotalSize.Height)
819 aTotalSize.Height = aBSize.Height;
821 else
823 aTotalSize.Height += aBSize.Height;
824 if (aBSize.Width > aTotalSize.Width)
825 aTotalSize.Width = aBSize.Width;
829 return aTotalSize;
832 void PresenterToolBar::LayoutPart (
833 const Reference<rendering::XCanvas>& rxCanvas,
834 const SharedElementContainerPart& rpPart,
835 const geometry::RealRectangle2D& rBoundingBox,
836 const geometry::RealSize2D& rPartSize,
837 const bool bIsHorizontal)
839 double nGap (0);
840 if (rpPart->size() > 1)
842 if (bIsHorizontal)
843 nGap = (rBoundingBox.X2 - rBoundingBox.X1 - rPartSize.Width) / (rpPart->size()-1);
844 else
845 nGap = (rBoundingBox.Y2 - rBoundingBox.Y1 - rPartSize.Height) / (rpPart->size()-1);
848 // Place the elements.
849 double nX (rBoundingBox.X1);
850 double nY (rBoundingBox.Y1);
852 ElementContainerPart::const_iterator iElement;
853 ElementContainerPart::const_iterator iEnd (rpPart->end());
854 ElementContainerPart::const_iterator iBegin (rpPart->begin());
856 /// check whether RTL interface or not
857 if(!AllSettings::GetLayoutRTL()){
858 for (iElement=rpPart->begin(); iElement!=iEnd; ++iElement)
860 if (iElement->get() == nullptr)
861 continue;
863 const awt::Size aElementSize ((*iElement)->GetBoundingSize(rxCanvas));
864 if (bIsHorizontal)
866 if ((*iElement)->IsFilling())
868 nY = rBoundingBox.Y1;
869 (*iElement)->SetSize(geometry::RealSize2D(aElementSize.Width, rBoundingBox.Y2 - rBoundingBox.Y1));
871 else
872 nY = rBoundingBox.Y1 + (rBoundingBox.Y2-rBoundingBox.Y1 - aElementSize.Height) / 2;
873 (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
874 nX += aElementSize.Width + nGap;
876 else
878 if ((*iElement)->IsFilling())
880 nX = rBoundingBox.X1;
881 (*iElement)->SetSize(geometry::RealSize2D(rBoundingBox.X2 - rBoundingBox.X1, aElementSize.Height));
883 else
884 nX = rBoundingBox.X1 + (rBoundingBox.X2-rBoundingBox.X1 - aElementSize.Width) / 2;
885 (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
886 nY += aElementSize.Height + nGap;
890 else {
891 for (iElement=rpPart->end()-1; iElement!=iBegin-1; --iElement)
893 if (iElement->get() == nullptr)
894 continue;
896 const awt::Size aElementSize ((*iElement)->GetBoundingSize(rxCanvas));
897 if (bIsHorizontal)
899 if ((*iElement)->IsFilling())
901 nY = rBoundingBox.Y1;
902 (*iElement)->SetSize(geometry::RealSize2D(aElementSize.Width, rBoundingBox.Y2 - rBoundingBox.Y1));
904 else
905 nY = rBoundingBox.Y1 + (rBoundingBox.Y2-rBoundingBox.Y1 - aElementSize.Height) / 2;
906 (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
907 nX += aElementSize.Width + nGap;
909 else
911 // reverse presentation time with current time
912 if (iElement==iBegin){
913 iElement=iBegin+2;
915 else if (iElement==iBegin+2){
916 iElement=iBegin;
918 const awt::Size aNewElementSize ((*iElement)->GetBoundingSize(rxCanvas));
919 if ((*iElement)->IsFilling())
921 nX = rBoundingBox.X1;
922 (*iElement)->SetSize(geometry::RealSize2D(rBoundingBox.X2 - rBoundingBox.X1, aNewElementSize.Height));
924 else
925 nX = rBoundingBox.X1 + (rBoundingBox.X2-rBoundingBox.X1 - aNewElementSize.Width) / 2;
926 (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
927 nY += aNewElementSize.Height + nGap;
929 // return the index as it was before the reversing
930 if (iElement==iBegin)
931 iElement=iBegin+2;
932 else if (iElement==iBegin+2)
933 iElement=iBegin;
940 void PresenterToolBar::Paint (
941 const awt::Rectangle& rUpdateBox,
942 const rendering::ViewState& rViewState)
944 OSL_ASSERT(mxCanvas.is());
946 ElementContainer::iterator iPart;
947 ElementContainer::const_iterator iEnd (maElementContainer.end());
948 for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart)
950 ElementContainerPart::iterator iElement;
951 ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
952 for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement)
954 if (iElement->get() != nullptr)
956 if ( ! (*iElement)->IsOutside(rUpdateBox))
957 (*iElement)->Paint(mxCanvas, rViewState);
963 void PresenterToolBar::UpdateSlideNumber()
965 if( mxSlideShowController.is() )
967 ElementContainer::iterator iPart;
968 ElementContainer::const_iterator iEnd (maElementContainer.end());
969 for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart)
971 ElementContainerPart::iterator iElement;
972 ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
973 for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement)
975 if (iElement->get() != nullptr)
976 (*iElement)->CurrentSlideHasChanged();
982 void PresenterToolBar::CheckMouseOver (
983 const css::awt::MouseEvent& rEvent,
984 const bool bOverWindow,
985 const bool bMouseDown)
987 css::awt::MouseEvent rTemp =rEvent;
988 if(AllSettings::GetLayoutRTL()){
989 awt::Rectangle aWindowBox = mxWindow->getPosSize();
990 rTemp.X=aWindowBox.Width-rTemp.X;
992 ElementContainer::iterator iPart;
993 ElementContainer::const_iterator iEnd (maElementContainer.end());
994 for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart)
996 ElementContainerPart::iterator iElement;
997 ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
998 for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement)
1000 if (iElement->get() == nullptr)
1001 continue;
1003 awt::Rectangle aBox ((*iElement)->GetBoundingBox());
1004 const bool bIsOver = bOverWindow
1005 && aBox.X <= rTemp.X
1006 && aBox.Width+aBox.X-1 >= rTemp.X
1007 && aBox.Y <= rTemp.Y
1008 && aBox.Height+aBox.Y-1 >= rTemp.Y;
1009 (*iElement)->SetState(
1010 bIsOver,
1011 bIsOver && rTemp.Buttons!=0 && bMouseDown && rTemp.ClickCount>0);
1016 void PresenterToolBar::ThrowIfDisposed() const
1018 if (rBHelper.bDisposed || rBHelper.bInDispose)
1020 throw lang::DisposedException (
1021 "PresenterToolBar has already been disposed",
1022 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1026 //===== PresenterToolBarView ==================================================
1028 PresenterToolBarView::PresenterToolBarView (
1029 const Reference<XComponentContext>& rxContext,
1030 const Reference<XResourceId>& rxViewId,
1031 const Reference<frame::XController>& rxController,
1032 const ::rtl::Reference<PresenterController>& rpPresenterController)
1033 : PresenterToolBarViewInterfaceBase(m_aMutex),
1034 mxPane(),
1035 mxViewId(rxViewId),
1036 mxWindow(),
1037 mxCanvas(),
1038 mpPresenterController(rpPresenterController),
1039 mxSlideShowController(rpPresenterController->GetSlideShowController()),
1040 mpToolBar()
1044 Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW);
1045 Reference<XConfigurationController> xCC(xCM->getConfigurationController(),UNO_QUERY_THROW);
1046 mxPane.set(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW);
1048 mxWindow = mxPane->getWindow();
1049 mxCanvas = mxPane->getCanvas();
1051 mpToolBar = new PresenterToolBar(
1052 rxContext,
1053 mxWindow,
1054 mxCanvas,
1055 rpPresenterController,
1056 PresenterToolBar::Center);
1057 mpToolBar->Initialize("PresenterScreenSettings/ToolBars/ToolBar");
1059 if (mxWindow.is())
1061 mxWindow->addPaintListener(this);
1063 Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
1064 if (xPeer.is())
1065 xPeer->setBackground(util::Color(0xff000000));
1067 mxWindow->setVisible(true);
1070 catch (RuntimeException&)
1072 mxViewId = nullptr;
1073 throw;
1077 PresenterToolBarView::~PresenterToolBarView()
1081 void SAL_CALL PresenterToolBarView::disposing()
1083 Reference<lang::XComponent> xComponent (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY);
1084 mpToolBar = nullptr;
1085 if (xComponent.is())
1086 xComponent->dispose();
1088 if (mxWindow.is())
1090 mxWindow->removePaintListener(this);
1091 mxWindow = nullptr;
1093 mxCanvas = nullptr;
1094 mxViewId = nullptr;
1095 mxPane = nullptr;
1096 mpPresenterController = nullptr;
1097 mxSlideShowController = nullptr;
1101 const ::rtl::Reference<PresenterToolBar>& PresenterToolBarView::GetPresenterToolBar() const
1103 return mpToolBar;
1106 //----- XPaintListener --------------------------------------------------------
1108 void SAL_CALL PresenterToolBarView::windowPaint (const css::awt::PaintEvent& rEvent)
1110 awt::Rectangle aWindowBox (mxWindow->getPosSize());
1111 mpPresenterController->GetCanvasHelper()->Paint(
1112 mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
1113 mxCanvas,
1114 rEvent.UpdateRect,
1115 awt::Rectangle(0,0,aWindowBox.Width, aWindowBox.Height),
1116 awt::Rectangle());
1119 //----- lang::XEventListener -------------------------------------------------
1121 void SAL_CALL PresenterToolBarView::disposing (const lang::EventObject& rEventObject)
1123 if (rEventObject.Source == mxWindow)
1124 mxWindow = nullptr;
1127 //----- XResourceId -----------------------------------------------------------
1129 Reference<XResourceId> SAL_CALL PresenterToolBarView::getResourceId()
1131 return mxViewId;
1134 sal_Bool SAL_CALL PresenterToolBarView::isAnchorOnly()
1136 return false;
1139 //----- XDrawView -------------------------------------------------------------
1141 void SAL_CALL PresenterToolBarView::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
1143 Reference<drawing::XDrawView> xToolBar (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY);
1144 if (xToolBar.is())
1145 xToolBar->setCurrentPage(rxSlide);
1148 Reference<drawing::XDrawPage> SAL_CALL PresenterToolBarView::getCurrentPage()
1150 return nullptr;
1153 //===== PresenterToolBar::Element =============================================
1155 namespace {
1157 Element::Element (
1158 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1159 : ElementInterfaceBase(m_aMutex),
1160 mpToolBar(rpToolBar),
1161 maLocation(),
1162 maSize(),
1163 mpNormal(),
1164 mpMouseOver(),
1165 mpSelected(),
1166 mpDisabled(),
1167 mpMode(),
1168 mbIsOver(false),
1169 mbIsPressed(false),
1170 mbIsSelected(false),
1171 mbIsEnabled(true)
1173 if (mpToolBar.get() != nullptr)
1175 OSL_ASSERT(mpToolBar->GetPresenterController().is());
1176 OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
1180 void Element::SetModes (
1181 const SharedElementMode& rpNormalMode,
1182 const SharedElementMode& rpMouseOverMode,
1183 const SharedElementMode& rpSelectedMode,
1184 const SharedElementMode& rpDisabledMode)
1186 mpNormal = rpNormalMode;
1187 mpMouseOver = rpMouseOverMode;
1188 mpSelected = rpSelectedMode;
1189 mpDisabled = rpDisabledMode;
1190 mpMode = rpNormalMode;
1193 void Element::disposing()
1197 awt::Size const & Element::GetBoundingSize (
1198 const Reference<rendering::XCanvas>& rxCanvas)
1200 maSize = CreateBoundingSize(rxCanvas);
1201 return maSize;
1204 awt::Rectangle Element::GetBoundingBox() const
1206 return awt::Rectangle(maLocation.X,maLocation.Y, maSize.Width, maSize.Height);
1209 void Element::CurrentSlideHasChanged()
1211 UpdateState();
1214 void Element::SetLocation (const awt::Point& rLocation)
1216 maLocation = rLocation;
1219 void Element::SetSize (const geometry::RealSize2D& rSize)
1221 maSize = awt::Size(sal_Int32(0.5+rSize.Width), sal_Int32(0.5+rSize.Height));
1224 bool Element::SetState (
1225 const bool bIsOver,
1226 const bool bIsPressed)
1228 bool bModified (mbIsOver != bIsOver || mbIsPressed != bIsPressed);
1229 bool bClicked (mbIsPressed && bIsOver && ! bIsPressed);
1231 mbIsOver = bIsOver;
1232 mbIsPressed = bIsPressed;
1234 // When the element is disabled then ignore mouse over or selection.
1235 // When the element is selected then ignore mouse over.
1236 if ( ! mbIsEnabled)
1237 mpMode = mpDisabled;
1238 else if (mbIsSelected)
1239 mpMode = mpSelected;
1240 else if (mbIsOver)
1241 mpMode = mpMouseOver;
1242 else
1243 mpMode = mpNormal;
1245 if (bClicked && mbIsEnabled)
1247 if (mpMode.get() != nullptr)
1251 if (mpMode->msAction.isEmpty())
1252 break;
1254 if (mpToolBar.get() == nullptr)
1255 break;
1257 if (mpToolBar->GetPresenterController().get() == nullptr)
1258 break;
1260 mpToolBar->GetPresenterController()->DispatchUnoCommand(mpMode->msAction);
1261 mpToolBar->RequestLayout();
1263 while (false);
1267 else if (bModified)
1269 Invalidate(true);
1272 return bModified;
1275 void Element::Invalidate (const bool bSynchronous)
1277 OSL_ASSERT(mpToolBar.is());
1278 mpToolBar->InvalidateArea(GetBoundingBox(), bSynchronous);
1281 bool Element::IsOutside (const awt::Rectangle& rBox)
1283 if (rBox.X >= maLocation.X+maSize.Width)
1284 return true;
1285 else if (rBox.Y >= maLocation.Y+maSize.Height)
1286 return true;
1287 else if (maLocation.X >= rBox.X+rBox.Width)
1288 return true;
1289 else if (maLocation.Y >= rBox.Y+rBox.Height)
1290 return true;
1291 else
1292 return false;
1296 bool Element::IsFilling() const
1298 return false;
1301 void Element::UpdateState()
1303 OSL_ASSERT(mpToolBar.get() != nullptr);
1304 OSL_ASSERT(mpToolBar->GetPresenterController().get() != nullptr);
1306 if (mpMode.get() == nullptr)
1307 return;
1309 util::URL aURL (mpToolBar->GetPresenterController()->CreateURLFromString(mpMode->msAction));
1310 Reference<frame::XDispatch> xDispatch (mpToolBar->GetPresenterController()->GetDispatch(aURL));
1311 if (xDispatch.is())
1313 xDispatch->addStatusListener(this, aURL);
1314 xDispatch->removeStatusListener(this, aURL);
1318 //----- lang::XEventListener --------------------------------------------------
1320 void SAL_CALL Element::disposing (const css::lang::EventObject&) {}
1322 //----- document::XEventListener ----------------------------------------------
1324 void SAL_CALL Element::notifyEvent (const css::document::EventObject&)
1326 UpdateState();
1329 //----- frame::XStatusListener ------------------------------------------------
1331 void SAL_CALL Element::statusChanged (const css::frame::FeatureStateEvent& rEvent)
1333 bool bIsSelected (mbIsSelected);
1334 bool bIsEnabled (rEvent.IsEnabled);
1335 rEvent.State >>= bIsSelected;
1337 if (bIsSelected != mbIsSelected || bIsEnabled != mbIsEnabled)
1339 mbIsEnabled = bIsEnabled;
1340 mbIsSelected = bIsSelected;
1341 SetState(mbIsOver, mbIsPressed);
1342 mpToolBar->RequestLayout();
1346 } // end of anonymous namespace
1348 //===== ElementMode ===========================================================
1350 namespace {
1352 ElementMode::ElementMode()
1353 : mpIcon(),
1354 msAction(),
1355 maText()
1359 void ElementMode::ReadElementMode (
1360 const Reference<beans::XPropertySet>& rxElementProperties,
1361 const OUString& rsModeName,
1362 std::shared_ptr<ElementMode> const & rpDefaultMode,
1363 ::sdext::presenter::PresenterToolBar::Context const & rContext)
1367 Reference<container::XHierarchicalNameAccess> xNode (
1368 PresenterConfigurationAccess::GetProperty(rxElementProperties, rsModeName),
1369 UNO_QUERY);
1370 Reference<beans::XPropertySet> xProperties (
1371 PresenterConfigurationAccess::GetNodeProperties(xNode, OUString()));
1372 if ( ! xProperties.is() && rpDefaultMode.get()!=nullptr)
1374 // The mode is not specified. Use the given, possibly empty,
1375 // default mode instead.
1376 mpIcon = rpDefaultMode->mpIcon;
1377 msAction = rpDefaultMode->msAction;
1378 maText = rpDefaultMode->maText;
1381 // Read action.
1382 if ( ! (PresenterConfigurationAccess::GetProperty(xProperties, "Action") >>= msAction))
1383 if (rpDefaultMode.get()!=nullptr)
1384 msAction = rpDefaultMode->msAction;
1386 // Read text and font
1387 OUString sText (rpDefaultMode.get()!=nullptr ? rpDefaultMode->maText.GetText() : OUString());
1388 PresenterConfigurationAccess::GetProperty(xProperties, "Text") >>= sText;
1389 Reference<container::XHierarchicalNameAccess> xFontNode (
1390 PresenterConfigurationAccess::GetProperty(xProperties, "Font"), UNO_QUERY);
1391 PresenterTheme::SharedFontDescriptor pFont (PresenterTheme::ReadFont(
1392 xFontNode,
1393 rpDefaultMode.get()!=nullptr
1394 ? rpDefaultMode->maText.GetFont()
1395 : PresenterTheme::SharedFontDescriptor()));
1396 maText = Text(sText,pFont);
1398 // Read bitmaps to display as icons.
1399 Reference<container::XHierarchicalNameAccess> xIconNode (
1400 PresenterConfigurationAccess::GetProperty(xProperties, "Icon"), UNO_QUERY);
1401 mpIcon = PresenterBitmapContainer::LoadBitmap(
1402 xIconNode,
1404 rContext.mxPresenterHelper,
1405 rContext.mxCanvas,
1406 rpDefaultMode.get()!=nullptr ? rpDefaultMode->mpIcon : SharedBitmapDescriptor());
1408 catch(Exception&)
1410 OSL_ASSERT(false);
1414 } // end of anonymous namespace
1416 //===== Button ================================================================
1418 namespace {
1420 ::rtl::Reference<Element> Button::Create (
1421 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1423 ::rtl::Reference<Button> pElement (new Button(rpToolBar));
1424 pElement->Initialize();
1425 return ::rtl::Reference<Element>(pElement.get());
1428 Button::Button (
1429 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1430 : Element(rpToolBar),
1431 mbIsListenerRegistered(false)
1433 OSL_ASSERT(mpToolBar.get() != nullptr);
1434 OSL_ASSERT(mpToolBar->GetPresenterController().is());
1435 OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
1438 void Button::Initialize()
1440 mpToolBar->GetPresenterController()->GetWindowManager()->AddLayoutListener(this);
1441 mbIsListenerRegistered = true;
1444 void Button::disposing()
1446 OSL_ASSERT(mpToolBar.get() != nullptr);
1447 if (mpToolBar.get() != nullptr
1448 && mbIsListenerRegistered)
1450 OSL_ASSERT(mpToolBar->GetPresenterController().is());
1451 OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
1453 mbIsListenerRegistered = false;
1454 mpToolBar->GetPresenterController()->GetWindowManager()->RemoveLayoutListener(this);
1456 Element::disposing();
1459 void Button::Paint (
1460 const Reference<rendering::XCanvas>& rxCanvas,
1461 const rendering::ViewState& rViewState)
1463 OSL_ASSERT(rxCanvas.is());
1465 if (mpMode.get() == nullptr)
1466 return;
1468 if (mpMode->mpIcon.get() == nullptr)
1469 return;
1471 geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
1472 sal_Int32 nTextHeight (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
1474 PaintIcon(rxCanvas, nTextHeight, rViewState);
1475 mpMode->maText.Paint(rxCanvas, rViewState, GetBoundingBox());
1478 awt::Size Button::CreateBoundingSize (
1479 const Reference<rendering::XCanvas>& rxCanvas)
1481 if (mpMode.get() == nullptr)
1482 return awt::Size();
1484 geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
1485 const sal_Int32 nGap (5);
1486 sal_Int32 nTextHeight (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
1487 sal_Int32 nTextWidth (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.X2 - aTextBBox.X1));
1488 Reference<rendering::XBitmap> xBitmap;
1489 if (mpMode->mpIcon.get() != nullptr)
1490 xBitmap = mpMode->mpIcon->GetNormalBitmap();
1491 if (xBitmap.is())
1493 geometry::IntegerSize2D aSize (xBitmap->getSize());
1494 return awt::Size(
1495 ::std::max(aSize.Width, sal_Int32(0.5 + aTextBBox.X2 - aTextBBox.X1)),
1496 aSize.Height+ nGap + nTextHeight);
1498 else
1499 return awt::Size(nTextWidth,nTextHeight);
1502 void Button::PaintIcon (
1503 const Reference<rendering::XCanvas>& rxCanvas,
1504 const sal_Int32 nTextHeight,
1505 const rendering::ViewState& rViewState)
1507 if (mpMode.get() == nullptr)
1508 return;
1510 Reference<rendering::XBitmap> xBitmap (mpMode->mpIcon->GetBitmap(GetMode()));
1511 if (xBitmap.is())
1513 /// check whether RTL interface or not
1514 if(!AllSettings::GetLayoutRTL()){
1515 const sal_Int32 nX (maLocation.X
1516 + (maSize.Width-xBitmap->getSize().Width) / 2);
1517 const sal_Int32 nY (maLocation.Y
1518 + (maSize.Height - nTextHeight - xBitmap->getSize().Height) / 2);
1519 const rendering::RenderState aRenderState(
1520 geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
1521 nullptr,
1522 Sequence<double>(4),
1523 rendering::CompositeOperation::OVER);
1524 rxCanvas->drawBitmap(xBitmap, rViewState, aRenderState);
1526 else {
1527 const sal_Int32 nX (maLocation.X
1528 + (maSize.Width+xBitmap->getSize().Width) / 2);
1529 const sal_Int32 nY (maLocation.Y
1530 + (maSize.Height - nTextHeight - xBitmap->getSize().Height) / 2);
1531 const rendering::RenderState aRenderState(
1532 geometry::AffineMatrix2D(-1,0,nX, 0,1,nY),
1533 nullptr,
1534 Sequence<double>(4),
1535 rendering::CompositeOperation::OVER);
1536 rxCanvas->drawBitmap(xBitmap, rViewState, aRenderState);
1541 PresenterBitmapDescriptor::Mode Button::GetMode() const
1543 if ( ! IsEnabled())
1544 return PresenterBitmapDescriptor::Disabled;
1545 else if (mbIsPressed)
1546 return PresenterBitmapDescriptor::ButtonDown;
1547 else if (mbIsOver)
1548 return PresenterBitmapDescriptor::MouseOver;
1549 else
1550 return PresenterBitmapDescriptor::Normal;
1553 //----- lang::XEventListener --------------------------------------------------
1555 void SAL_CALL Button::disposing (const css::lang::EventObject& rEvent)
1557 mbIsListenerRegistered = false;
1558 Element::disposing(rEvent);
1561 } // end of anonymous namespace
1563 //===== PresenterToolBar::Label ===============================================
1565 namespace {
1567 Label::Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1568 : Element(rpToolBar)
1572 awt::Size Label::CreateBoundingSize (
1573 const Reference<rendering::XCanvas>& rxCanvas)
1575 if (mpMode.get() == nullptr)
1576 return awt::Size(0,0);
1578 geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
1579 return awt::Size(
1580 sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.X2 - aTextBBox.X1),
1581 sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
1584 void Label::SetText (const OUString& rsText)
1586 OSL_ASSERT(mpToolBar.get() != nullptr);
1587 if (mpMode.get() == nullptr)
1588 return;
1590 const bool bRequestLayout (mpMode->maText.GetText().getLength() != rsText.getLength());
1592 mpMode->maText.SetText(rsText);
1593 // Just use the character count for determining whether a layout is
1594 // necessary. This is an optimization to avoid layouts every time a new
1595 // time value is set on some labels.
1596 if (bRequestLayout)
1597 mpToolBar->RequestLayout();
1598 else
1599 Invalidate(false);
1602 void Label::Paint (
1603 const Reference<rendering::XCanvas>& rxCanvas,
1604 const rendering::ViewState& rViewState)
1606 OSL_ASSERT(rxCanvas.is());
1607 if (mpMode.get() == nullptr)
1608 return;
1610 mpMode->maText.Paint(rxCanvas, rViewState, GetBoundingBox());
1613 bool Label::SetState (const bool, const bool)
1615 // For labels there is no mouse over effect.
1616 return Element::SetState(false, false);
1619 } // end of anonymous namespace
1621 //===== Text ==================================================================
1623 namespace {
1625 Text::Text()
1626 : msText(),
1627 mpFont()
1631 Text::Text (
1632 const OUString& rsText,
1633 const PresenterTheme::SharedFontDescriptor& rpFont)
1634 : msText(rsText),
1635 mpFont(rpFont)
1639 void Text::SetText (const OUString& rsText)
1641 msText = rsText;
1644 const OUString& Text::GetText() const
1646 return msText;
1649 const PresenterTheme::SharedFontDescriptor& Text::GetFont() const
1651 return mpFont;
1654 void Text::Paint (
1655 const Reference<rendering::XCanvas>& rxCanvas,
1656 const rendering::ViewState& rViewState,
1657 const awt::Rectangle& rBoundingBox)
1659 OSL_ASSERT(rxCanvas.is());
1661 if (msText.isEmpty())
1662 return;
1663 if (mpFont.get() == nullptr)
1664 return;
1666 if ( ! mpFont->mxFont.is())
1667 mpFont->PrepareFont(rxCanvas);
1668 if ( ! mpFont->mxFont.is())
1669 return;
1671 rendering::StringContext aContext (msText, 0, msText.getLength());
1673 Reference<rendering::XTextLayout> xLayout (
1674 mpFont->mxFont->createTextLayout(
1675 aContext,
1676 rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
1677 0));
1678 geometry::RealRectangle2D aBox (xLayout->queryTextBounds());
1679 const double nTextWidth = aBox.X2 - aBox.X1;
1680 const double nY = rBoundingBox.Y + rBoundingBox.Height - aBox.Y2;
1681 const double nX = rBoundingBox.X + (rBoundingBox.Width - nTextWidth)/2;
1683 rendering::RenderState aRenderState(
1684 geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
1685 nullptr,
1686 Sequence<double>(4),
1687 rendering::CompositeOperation::SOURCE);
1688 PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);
1689 rxCanvas->drawTextLayout(
1690 xLayout,
1691 rViewState,
1692 aRenderState);
1695 geometry::RealRectangle2D Text::GetBoundingBox (const Reference<rendering::XCanvas>& rxCanvas)
1697 if (mpFont.get() != nullptr && !msText.isEmpty())
1699 if ( ! mpFont->mxFont.is())
1700 mpFont->PrepareFont(rxCanvas);
1701 if (mpFont->mxFont.is())
1703 rendering::StringContext aContext (msText, 0, msText.getLength());
1704 Reference<rendering::XTextLayout> xLayout (
1705 mpFont->mxFont->createTextLayout(
1706 aContext,
1707 rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
1708 0));
1709 return xLayout->queryTextBounds();
1712 return geometry::RealRectangle2D(0,0,0,0);
1715 //===== TimeFormatter =========================================================
1717 OUString TimeFormatter::FormatTime (const oslDateTime& rTime)
1719 OUStringBuffer sText;
1721 const sal_Int32 nHours (sal::static_int_cast<sal_Int32>(rTime.Hours));
1722 const sal_Int32 nMinutes (sal::static_int_cast<sal_Int32>(rTime.Minutes));
1723 const sal_Int32 nSeconds(sal::static_int_cast<sal_Int32>(rTime.Seconds));
1724 // Hours
1725 sText.append(OUString::number(nHours));
1727 sText.append(":");
1729 // Minutes
1730 const OUString sMinutes (OUString::number(nMinutes));
1731 if (sMinutes.getLength() == 1)
1732 sText.append("0");
1733 sText.append(sMinutes);
1735 // Seconds
1736 sText.append(":");
1737 const OUString sSeconds (OUString::number(nSeconds));
1738 if (sSeconds.getLength() == 1)
1739 sText.append("0");
1740 sText.append(sSeconds);
1741 return sText.makeStringAndClear();
1744 //===== TimeLabel =============================================================
1746 TimeLabel::TimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1747 : Label(rpToolBar),
1748 mpListener()
1752 void SAL_CALL TimeLabel::disposing()
1754 PresenterClockTimer::Instance(mpToolBar->GetComponentContext())->RemoveListener(mpListener);
1755 mpListener.reset();
1758 void TimeLabel::ConnectToTimer()
1760 mpListener.reset(new Listener(this));
1761 PresenterClockTimer::Instance(mpToolBar->GetComponentContext())->AddListener(mpListener);
1764 //===== CurrentTimeLabel ======================================================
1766 ::rtl::Reference<Element> CurrentTimeLabel::Create (
1767 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1769 ::rtl::Reference<TimeLabel> pElement(new CurrentTimeLabel(rpToolBar));
1770 pElement->ConnectToTimer();
1771 return ::rtl::Reference<Element>(pElement.get());
1774 CurrentTimeLabel::~CurrentTimeLabel()
1778 CurrentTimeLabel::CurrentTimeLabel (
1779 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1780 : TimeLabel(rpToolBar)
1784 void CurrentTimeLabel::TimeHasChanged (const oslDateTime& rCurrentTime)
1786 SetText(TimeFormatter::FormatTime(rCurrentTime));
1787 Invalidate(false);
1790 void CurrentTimeLabel::SetModes (
1791 const SharedElementMode& rpNormalMode,
1792 const SharedElementMode& rpMouseOverMode,
1793 const SharedElementMode& rpSelectedMode,
1794 const SharedElementMode& rpDisabledMode)
1796 TimeLabel::SetModes(rpNormalMode, rpMouseOverMode, rpSelectedMode, rpDisabledMode);
1797 SetText(TimeFormatter::FormatTime(PresenterClockTimer::GetCurrentTime()));
1800 //===== PresentationTimeLabel =================================================
1802 ::rtl::Reference<Element> PresentationTimeLabel::Create (
1803 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1805 ::rtl::Reference<TimeLabel> pElement(new PresentationTimeLabel(rpToolBar));
1806 pElement->ConnectToTimer();
1807 return ::rtl::Reference<Element>(pElement.get());
1810 PresentationTimeLabel::~PresentationTimeLabel()
1812 mpToolBar->GetPresenterController()->SetPresentationTime(nullptr);
1815 PresentationTimeLabel::PresentationTimeLabel (
1816 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1817 : TimeLabel(rpToolBar),
1818 maStartTimeValue()
1820 restart();
1821 mpToolBar->GetPresenterController()->SetPresentationTime(this);
1824 void PresentationTimeLabel::restart()
1826 maStartTimeValue.Seconds = 0;
1827 maStartTimeValue.Nanosec = 0;
1830 void PresentationTimeLabel::TimeHasChanged (const oslDateTime& rCurrentTime)
1832 TimeValue aCurrentTimeValue;
1833 if (osl_getTimeValueFromDateTime(&rCurrentTime, &aCurrentTimeValue))
1835 if (maStartTimeValue.Seconds==0 && maStartTimeValue.Nanosec==0)
1837 // This method is called for the first time. Initialize the
1838 // start time. The start time is rounded to nearest second to
1839 // keep the time updates synchronized with the current time label.
1840 maStartTimeValue = aCurrentTimeValue;
1841 if (maStartTimeValue.Nanosec >= 500000000)
1842 maStartTimeValue.Seconds += 1;
1843 maStartTimeValue.Nanosec = 0;
1846 TimeValue aElapsedTimeValue;
1847 aElapsedTimeValue.Seconds = aCurrentTimeValue.Seconds - maStartTimeValue.Seconds;
1848 aElapsedTimeValue.Nanosec = aCurrentTimeValue.Nanosec - maStartTimeValue.Nanosec;
1850 oslDateTime aElapsedDateTime;
1851 if (osl_getDateTimeFromTimeValue(&aElapsedTimeValue, &aElapsedDateTime))
1853 SetText(TimeFormatter::FormatTime(aElapsedDateTime));
1854 Invalidate(false);
1859 void PresentationTimeLabel::SetModes (
1860 const SharedElementMode& rpNormalMode,
1861 const SharedElementMode& rpMouseOverMode,
1862 const SharedElementMode& rpSelectedMode,
1863 const SharedElementMode& rpDisabledMode)
1865 TimeLabel::SetModes(rpNormalMode, rpMouseOverMode, rpSelectedMode, rpDisabledMode);
1867 oslDateTime aStartDateTime;
1868 if (osl_getDateTimeFromTimeValue(&maStartTimeValue, &aStartDateTime))
1870 SetText(TimeFormatter::FormatTime(aStartDateTime));
1874 //===== VerticalSeparator =====================================================
1876 VerticalSeparator::VerticalSeparator (
1877 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1878 : Element(rpToolBar)
1882 void VerticalSeparator::Paint (
1883 const Reference<rendering::XCanvas>& rxCanvas,
1884 const rendering::ViewState& rViewState)
1886 OSL_ASSERT(rxCanvas.is());
1888 awt::Rectangle aBBox (GetBoundingBox());
1890 rendering::RenderState aRenderState(
1891 geometry::AffineMatrix2D(1,0,0, 0,1,0),
1892 nullptr,
1893 Sequence<double>(4),
1894 rendering::CompositeOperation::OVER);
1895 if (mpMode.get() != nullptr)
1897 PresenterTheme::SharedFontDescriptor pFont (mpMode->maText.GetFont());
1898 if (pFont.get() != nullptr)
1899 PresenterCanvasHelper::SetDeviceColor(aRenderState, pFont->mnColor);
1902 rxCanvas->fillPolyPolygon(
1903 PresenterGeometryHelper::CreatePolygon(aBBox, rxCanvas->getDevice()),
1904 rViewState,
1905 aRenderState);
1908 awt::Size VerticalSeparator::CreateBoundingSize (
1909 const Reference<rendering::XCanvas>&)
1911 return awt::Size(1,20);
1914 bool VerticalSeparator::IsFilling() const
1916 return true;
1919 //===== HorizontalSeparator ===================================================
1921 HorizontalSeparator::HorizontalSeparator (
1922 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1923 : Element(rpToolBar)
1927 void HorizontalSeparator::Paint (
1928 const Reference<rendering::XCanvas>& rxCanvas,
1929 const rendering::ViewState& rViewState)
1931 OSL_ASSERT(rxCanvas.is());
1933 awt::Rectangle aBBox (GetBoundingBox());
1935 rendering::RenderState aRenderState(
1936 geometry::AffineMatrix2D(1,0,0, 0,1,0),
1937 nullptr,
1938 Sequence<double>(4),
1939 rendering::CompositeOperation::OVER);
1940 if (mpMode.get() != nullptr)
1942 PresenterTheme::SharedFontDescriptor pFont (mpMode->maText.GetFont());
1943 if (pFont.get() != nullptr)
1944 PresenterCanvasHelper::SetDeviceColor(aRenderState, pFont->mnColor);
1947 rxCanvas->fillPolyPolygon(
1948 PresenterGeometryHelper::CreatePolygon(aBBox, rxCanvas->getDevice()),
1949 rViewState,
1950 aRenderState);
1953 awt::Size HorizontalSeparator::CreateBoundingSize (
1954 const Reference<rendering::XCanvas>&)
1956 return awt::Size(20,1);
1959 bool HorizontalSeparator::IsFilling() const
1961 return true;
1964 } // end of anonymous namespace
1966 } } // end of namespace ::sdext::presenter
1968 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */