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