bump product version to 5.0.4.1
[LibreOffice.git] / sdext / source / presenter / PresenterToolBar.cxx
bloba850602bebfe9669e6cc29c6da3523e41529033a
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/compbase2.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>
52 #include <boost/bind.hpp>
54 using namespace ::com::sun::star;
55 using namespace ::com::sun::star::uno;
56 using namespace ::com::sun::star::drawing::framework;
58 namespace sdext { namespace presenter {
60 static const sal_Int32 gnGapSize (20);
61 static const sal_Int32 gnMinimalSeparatorSize (20);
62 static const sal_Int32 gnSeparatorInset (0);
64 namespace {
66 class Text
68 public:
69 Text();
70 Text (
71 const OUString& rsText,
72 const PresenterTheme::SharedFontDescriptor& rpFont);
74 void SetText (const OUString& rsText);
75 OUString GetText() const;
76 PresenterTheme::SharedFontDescriptor GetFont() const;
78 void Paint (
79 const Reference<rendering::XCanvas>& rxCanvas,
80 const rendering::ViewState& rViewState,
81 const awt::Rectangle& rBoundingBox,
82 const awt::Point& rOffset);
84 geometry::RealRectangle2D GetBoundingBox (
85 const Reference<rendering::XCanvas>& rxCanvas);
87 private:
88 OUString msText;
89 PresenterTheme::SharedFontDescriptor mpFont;
92 class ElementMode
93 : private ::boost::noncopyable
95 public:
96 ElementMode();
98 SharedBitmapDescriptor mpIcon;
99 OUString msAction;
100 Text maText;
102 void ReadElementMode (
103 const Reference<beans::XPropertySet>& rxProperties,
104 const OUString& rsModeName,
105 ::boost::shared_ptr<ElementMode>& rpDefaultMode,
106 ::sdext::presenter::PresenterToolBar::Context& rContext);
108 typedef ::boost::shared_ptr<ElementMode> SharedElementMode;
110 } // end of anonymous namespace
112 class PresenterToolBar::Context
113 : private ::boost::noncopyable
115 public:
116 Reference<drawing::XPresenterHelper> mxPresenterHelper;
117 css::uno::Reference<css::rendering::XCanvas> mxCanvas;
120 //===== PresenterToolBar::Element =============================================
122 namespace {
123 typedef cppu::WeakComponentImplHelper2<
124 css::document::XEventListener,
125 css::frame::XStatusListener
126 > ElementInterfaceBase;
128 class Element
129 : private ::cppu::BaseMutex,
130 private ::boost::noncopyable,
131 public ElementInterfaceBase
133 public:
134 Element (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
135 virtual ~Element();
137 virtual void SAL_CALL disposing() SAL_OVERRIDE;
139 virtual void SetModes (
140 const SharedElementMode& rpNormalMode,
141 const SharedElementMode& rpMouseOverMode,
142 const SharedElementMode& rpSelectedMode,
143 const SharedElementMode& rpDisabledMode);
144 void CurrentSlideHasChanged();
145 void SetLocation (const awt::Point& rLocation);
146 void SetSize (const geometry::RealSize2D& rSize);
147 virtual void Paint (
148 const Reference<rendering::XCanvas>& rxCanvas,
149 const rendering::ViewState& rViewState) = 0;
150 awt::Size GetBoundingSize (
151 const Reference<rendering::XCanvas>& rxCanvas);
152 awt::Rectangle GetBoundingBox() const;
153 virtual bool SetState (const bool bIsOver, const bool bIsPressed);
154 void Invalidate (const bool bSynchronous = true);
155 bool IsOutside (const awt::Rectangle& rBox);
156 virtual bool IsFilling() const;
157 void UpdateState();
159 // lang::XEventListener
161 virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent)
162 throw(css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
164 // document::XEventListener
166 virtual void SAL_CALL notifyEvent (const css::document::EventObject& rEvent)
167 throw(css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
169 // frame::XStatusListener
171 virtual void SAL_CALL statusChanged (const css::frame::FeatureStateEvent& rEvent)
172 throw(css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
174 protected:
175 ::rtl::Reference<PresenterToolBar> mpToolBar;
176 awt::Point maLocation;
177 awt::Size maSize;
178 SharedElementMode mpNormal;
179 SharedElementMode mpMouseOver;
180 SharedElementMode mpSelected;
181 SharedElementMode mpDisabled;
182 SharedElementMode mpMode;
183 bool mbIsOver;
184 bool mbIsPressed;
185 bool mbIsSelected;
187 virtual awt::Size CreateBoundingSize (
188 const Reference<rendering::XCanvas>& rxCanvas) = 0;
190 bool IsEnabled() const { return mbIsEnabled;}
191 private:
192 bool mbIsEnabled;
195 } // end of anonymous namespace
197 class PresenterToolBar::ElementContainerPart
198 : public ::std::vector<rtl::Reference<Element> >
202 //===== Button ================================================================
204 namespace {
206 class Button : public Element
208 public:
209 static ::rtl::Reference<Element> Create (
210 const ::rtl::Reference<PresenterToolBar>& rpToolBar);
212 virtual ~Button();
213 virtual void SAL_CALL disposing() SAL_OVERRIDE;
215 virtual void Paint (
216 const Reference<rendering::XCanvas>& rxCanvas,
217 const rendering::ViewState& rViewState) SAL_OVERRIDE;
219 // lang::XEventListener
221 virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent)
222 throw(css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
224 protected:
225 virtual awt::Size CreateBoundingSize (
226 const Reference<rendering::XCanvas>& rxCanvas) SAL_OVERRIDE;
228 private:
229 bool mbIsListenerRegistered;
231 Button (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
232 void Initialize();
233 void PaintIcon (
234 const Reference<rendering::XCanvas>& rxCanvas,
235 const sal_Int32 nTextHeight,
236 const rendering::ViewState& rViewState);
237 PresenterBitmapDescriptor::Mode GetMode() const;
240 //===== Label =================================================================
242 class Label : public Element
244 public:
245 Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
247 void SetText (const OUString& rsText);
248 virtual void Paint (
249 const Reference<rendering::XCanvas>& rxCanvas,
250 const rendering::ViewState& rViewState) SAL_OVERRIDE;
251 virtual bool SetState (const bool bIsOver, const bool bIsPressed) SAL_OVERRIDE;
253 protected:
254 virtual awt::Size CreateBoundingSize (
255 const Reference<rendering::XCanvas>& rxCanvas) SAL_OVERRIDE;
258 // Some specialized controls.
260 class TimeFormatter
262 public:
263 TimeFormatter();
264 OUString FormatTime (const oslDateTime& rTime);
265 private:
266 bool mbIs24HourFormat;
267 bool mbIsAmPmFormat;
268 bool mbIsShowSeconds;
271 class TimeLabel : public Label
273 public:
274 void ConnectToTimer();
275 virtual void TimeHasChanged (const oslDateTime& rCurrentTime) = 0;
276 protected:
277 TimeLabel(const ::rtl::Reference<PresenterToolBar>& rpToolBar);
278 using Element::disposing;
279 virtual void SAL_CALL disposing() SAL_OVERRIDE;
280 private:
281 class Listener : public PresenterClockTimer::Listener
283 public:
284 Listener (const ::rtl::Reference<TimeLabel>& rxLabel)
285 : mxLabel(rxLabel) {}
286 virtual ~Listener() {}
287 virtual void TimeHasChanged (const oslDateTime& rCurrentTime) SAL_OVERRIDE
288 { if (mxLabel.is()) mxLabel->TimeHasChanged(rCurrentTime); }
289 private:
290 ::rtl::Reference<TimeLabel> mxLabel;
292 ::boost::shared_ptr<PresenterClockTimer::Listener> mpListener;
295 class CurrentTimeLabel : public TimeLabel
297 public:
298 static ::rtl::Reference<Element> Create (
299 const ::rtl::Reference<PresenterToolBar>& rpToolBar);
300 virtual void SetModes (
301 const SharedElementMode& rpNormalMode,
302 const SharedElementMode& rpMouseOverMode,
303 const SharedElementMode& rpSelectedMode,
304 const SharedElementMode& rpDisabledMode) SAL_OVERRIDE;
305 private:
306 TimeFormatter maTimeFormatter;
307 CurrentTimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
308 virtual ~CurrentTimeLabel();
309 virtual void TimeHasChanged (const oslDateTime& rCurrentTime) SAL_OVERRIDE;
312 class PresentationTimeLabel : public TimeLabel
314 public:
315 static ::rtl::Reference<Element> Create (
316 const ::rtl::Reference<PresenterToolBar>& rpToolBar);
317 virtual void SetModes (
318 const SharedElementMode& rpNormalMode,
319 const SharedElementMode& rpMouseOverMode,
320 const SharedElementMode& rpSelectedMode,
321 const SharedElementMode& rpDisabledMode) SAL_OVERRIDE;
322 private:
323 TimeFormatter maTimeFormatter;
324 TimeValue maStartTimeValue;
325 PresentationTimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
326 virtual ~PresentationTimeLabel();
327 virtual void TimeHasChanged (const oslDateTime& rCurrentTime) SAL_OVERRIDE;
330 class VerticalSeparator : public Element
332 public:
333 explicit VerticalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
334 virtual void Paint (
335 const Reference<rendering::XCanvas>& rxCanvas,
336 const rendering::ViewState& rViewState) SAL_OVERRIDE;
337 virtual bool IsFilling() const SAL_OVERRIDE;
339 protected:
340 virtual awt::Size CreateBoundingSize (
341 const Reference<rendering::XCanvas>& rxCanvas) SAL_OVERRIDE;
344 class HorizontalSeparator : public Element
346 public:
347 explicit HorizontalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
348 virtual void Paint (
349 const Reference<rendering::XCanvas>& rxCanvas,
350 const rendering::ViewState& rViewState) SAL_OVERRIDE;
351 virtual bool IsFilling() const SAL_OVERRIDE;
353 protected:
354 virtual awt::Size CreateBoundingSize (
355 const Reference<rendering::XCanvas>& rxCanvas) SAL_OVERRIDE;
357 } // end of anonymous namespace
359 //===== PresenterToolBar ======================================================
361 PresenterToolBar::PresenterToolBar (
362 const Reference<XComponentContext>& rxContext,
363 const css::uno::Reference<css::awt::XWindow>& rxWindow,
364 const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
365 const ::rtl::Reference<PresenterController>& rpPresenterController,
366 const Anchor eAnchor)
367 : PresenterToolBarInterfaceBase(m_aMutex),
368 mxComponentContext(rxContext),
369 maElementContainer(),
370 mpCurrentContainerPart(),
371 mxWindow(rxWindow),
372 mxCanvas(rxCanvas),
373 mxSlideShowController(),
374 mxCurrentSlide(),
375 mpPresenterController(rpPresenterController),
376 mbIsLayoutPending(false),
377 meAnchor(eAnchor),
378 maBoundingBox(),
379 maMinimalSize()
383 void PresenterToolBar::Initialize (
384 const OUString& rsConfigurationPath)
388 CreateControls(rsConfigurationPath);
390 if (mxWindow.is())
392 mxWindow->addWindowListener(this);
393 mxWindow->addPaintListener(this);
394 mxWindow->addMouseListener(this);
395 mxWindow->addMouseMotionListener(this);
397 Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
398 if (xPeer.is())
399 xPeer->setBackground(util::Color(0xff000000));
401 mxWindow->setVisible(sal_True);
404 mxSlideShowController = mpPresenterController->GetSlideShowController();
405 UpdateSlideNumber();
406 mbIsLayoutPending = true;
408 catch (RuntimeException&)
410 mpCurrentContainerPart.reset();
411 maElementContainer.clear();
412 throw;
416 PresenterToolBar::~PresenterToolBar()
420 void SAL_CALL PresenterToolBar::disposing()
422 if (mxWindow.is())
424 mxWindow->removeWindowListener(this);
425 mxWindow->removePaintListener(this);
426 mxWindow->removeMouseListener(this);
427 mxWindow->removeMouseMotionListener(this);
428 mxWindow = NULL;
431 // Dispose tool bar elements.
432 ElementContainer::iterator iPart (maElementContainer.begin());
433 ElementContainer::const_iterator iEnd (maElementContainer.end());
434 for ( ; iPart!=iEnd; ++iPart)
436 OSL_ASSERT(iPart->get()!=NULL);
437 ElementContainerPart::iterator iElement ((*iPart)->begin());
438 ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
439 for ( ; iElement!=iPartEnd; ++iElement)
441 if (iElement->get() != NULL)
443 ::rtl::Reference<Element> pElement (*iElement);
444 Reference<lang::XComponent> xComponent (
445 static_cast<XWeak*>(pElement.get()), UNO_QUERY);
446 if (xComponent.is())
447 xComponent->dispose();
452 mpCurrentContainerPart.reset();
453 maElementContainer.clear();
456 void PresenterToolBar::InvalidateArea (
457 const awt::Rectangle& rRepaintBox,
458 const bool bSynchronous)
460 ::boost::shared_ptr<PresenterPaintManager> xManager(mpPresenterController->GetPaintManager());
461 if (!xManager)
462 return;
463 xManager->Invalidate(
464 mxWindow,
465 rRepaintBox,
466 bSynchronous);
469 void PresenterToolBar::RequestLayout()
471 mbIsLayoutPending = true;
473 ::boost::shared_ptr<PresenterPaintManager> xManager(mpPresenterController->GetPaintManager());
474 if (!xManager)
475 return;
477 xManager->Invalidate(mxWindow);
480 geometry::RealSize2D PresenterToolBar::GetMinimalSize()
482 if (mbIsLayoutPending)
483 Layout(mxCanvas);
484 return maMinimalSize;
487 ::rtl::Reference<PresenterController> PresenterToolBar::GetPresenterController() const
489 return mpPresenterController;
492 Reference<XComponentContext> PresenterToolBar::GetComponentContext() const
494 return mxComponentContext;
497 //----- lang::XEventListener -------------------------------------------------
499 void SAL_CALL PresenterToolBar::disposing (const lang::EventObject& rEventObject)
500 throw (RuntimeException, std::exception)
502 if (rEventObject.Source == mxWindow)
503 mxWindow = NULL;
506 //----- XWindowListener -------------------------------------------------------
508 void SAL_CALL PresenterToolBar::windowResized (const awt::WindowEvent& rEvent)
509 throw (RuntimeException, std::exception)
511 (void)rEvent;
512 mbIsLayoutPending = true;
515 void SAL_CALL PresenterToolBar::windowMoved (const awt::WindowEvent& rEvent)
516 throw (RuntimeException, std::exception)
518 (void)rEvent;
521 void SAL_CALL PresenterToolBar::windowShown (const lang::EventObject& rEvent)
522 throw (RuntimeException, std::exception)
524 (void)rEvent;
525 mbIsLayoutPending = true;
528 void SAL_CALL PresenterToolBar::windowHidden (const lang::EventObject& rEvent)
529 throw (RuntimeException, std::exception)
531 (void)rEvent;
534 //----- XPaintListener --------------------------------------------------------
535 void SAL_CALL PresenterToolBar::windowPaint (const css::awt::PaintEvent& rEvent)
536 throw (RuntimeException, std::exception)
538 if ( ! mxCanvas.is())
539 return;
541 if ( ! mbIsPresenterViewActive)
542 return;
544 const rendering::ViewState aViewState (
545 geometry::AffineMatrix2D(1,0,0, 0,1,0),
546 PresenterGeometryHelper::CreatePolygon(rEvent.UpdateRect, mxCanvas->getDevice()));
548 if (mbIsLayoutPending)
549 Layout(mxCanvas);
551 Paint(rEvent.UpdateRect, aViewState);
553 // Make the back buffer visible.
554 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
555 if (xSpriteCanvas.is())
556 xSpriteCanvas->updateScreen(sal_False);
559 //----- XMouseListener --------------------------------------------------------
560 void SAL_CALL PresenterToolBar::mousePressed (const css::awt::MouseEvent& rEvent)
561 throw(css::uno::RuntimeException, std::exception)
563 ThrowIfDisposed();
564 CheckMouseOver(rEvent, true, true);
567 void SAL_CALL PresenterToolBar::mouseReleased (const css::awt::MouseEvent& rEvent)
568 throw(css::uno::RuntimeException, std::exception)
570 ThrowIfDisposed();
571 CheckMouseOver(rEvent, true);
574 void SAL_CALL PresenterToolBar::mouseEntered (const css::awt::MouseEvent& rEvent)
575 throw(css::uno::RuntimeException, std::exception)
577 ThrowIfDisposed();
578 CheckMouseOver(rEvent, true);
581 void SAL_CALL PresenterToolBar::mouseExited (const css::awt::MouseEvent& rEvent)
582 throw(css::uno::RuntimeException, std::exception)
584 ThrowIfDisposed();
585 CheckMouseOver(rEvent, false);
588 //----- XMouseMotionListener --------------------------------------------------
590 void SAL_CALL PresenterToolBar::mouseMoved (const css::awt::MouseEvent& rEvent)
591 throw (css::uno::RuntimeException, std::exception)
593 ThrowIfDisposed();
594 CheckMouseOver(rEvent, true);
597 void SAL_CALL PresenterToolBar::mouseDragged (const css::awt::MouseEvent& rEvent)
598 throw (css::uno::RuntimeException, std::exception)
600 ThrowIfDisposed();
601 (void)rEvent;
604 //----- XDrawView -------------------------------------------------------------
606 void SAL_CALL PresenterToolBar::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
607 throw (RuntimeException, std::exception)
609 if (rxSlide != mxCurrentSlide)
611 mxCurrentSlide = rxSlide;
612 UpdateSlideNumber();
616 Reference<drawing::XDrawPage> SAL_CALL PresenterToolBar::getCurrentPage()
617 throw (RuntimeException, std::exception)
619 return mxCurrentSlide;
624 void PresenterToolBar::CreateControls (
625 const OUString& rsConfigurationPath)
627 if ( ! mxWindow.is())
628 return;
630 // Expand the macro in the bitmap file names.
631 PresenterConfigurationAccess aConfiguration (
632 mxComponentContext,
633 OUString("/org.openoffice.Office.PresenterScreen/"),
634 PresenterConfigurationAccess::READ_ONLY);
636 mpCurrentContainerPart.reset(new ElementContainerPart());
637 maElementContainer.clear();
638 maElementContainer.push_back(mpCurrentContainerPart);
640 Reference<container::XHierarchicalNameAccess> xToolBarNode (
641 aConfiguration.GetConfigurationNode(rsConfigurationPath),
642 UNO_QUERY);
643 if (xToolBarNode.is())
645 Reference<container::XNameAccess> xEntries (
646 PresenterConfigurationAccess::GetConfigurationNode(xToolBarNode, "Entries"),
647 UNO_QUERY);
648 Context aContext;
649 aContext.mxPresenterHelper = mpPresenterController->GetPresenterHelper();
650 aContext.mxCanvas = mxCanvas;
651 if (xEntries.is()
652 && aContext.mxPresenterHelper.is()
653 && aContext.mxCanvas.is())
655 PresenterConfigurationAccess::ForAll(
656 xEntries,
657 ::boost::bind(&PresenterToolBar::ProcessEntry, this, _2, ::boost::ref(aContext)));
662 void PresenterToolBar::ProcessEntry (
663 const Reference<beans::XPropertySet>& rxProperties,
664 Context& rContext)
666 if ( ! rxProperties.is())
667 return;
669 // Type has to be present.
670 OUString sType;
671 if ( ! (PresenterConfigurationAccess::GetProperty(rxProperties, "Type") >>= sType))
672 return;
674 OUString sName;
675 PresenterConfigurationAccess::GetProperty(rxProperties, "Name") >>= sName;
677 // Read mode specific values.
678 SharedElementMode pNormalMode (new ElementMode());
679 SharedElementMode pMouseOverMode (new ElementMode());
680 SharedElementMode pSelectedMode (new ElementMode());
681 SharedElementMode pDisabledMode (new ElementMode());
682 pNormalMode->ReadElementMode(rxProperties, "Normal", pNormalMode, rContext);
683 pMouseOverMode->ReadElementMode(rxProperties, "MouseOver", pNormalMode, rContext);
684 pSelectedMode->ReadElementMode(rxProperties, "Selected", pNormalMode, rContext);
685 pDisabledMode->ReadElementMode(rxProperties, "Disabled", pNormalMode, rContext);
687 // Create new element.
688 ::rtl::Reference<Element> pElement;
689 if ( sType == "Button" )
690 pElement = Button::Create(this);
691 else if ( sType == "CurrentTimeLabel" )
692 pElement = CurrentTimeLabel::Create(this);
693 else if ( sType == "PresentationTimeLabel" )
694 pElement = PresentationTimeLabel::Create(this);
695 else if ( sType == "VerticalSeparator" )
696 pElement = ::rtl::Reference<Element>(new VerticalSeparator(this));
697 else if ( sType == "HorizontalSeparator" )
698 pElement = ::rtl::Reference<Element>(new HorizontalSeparator(this));
699 else if ( sType == "Label" )
700 pElement = ::rtl::Reference<Element>(new Label(this));
701 else if ( sType == "ChangeOrientation" )
703 mpCurrentContainerPart.reset(new ElementContainerPart());
704 maElementContainer.push_back(mpCurrentContainerPart);
705 return;
707 if (pElement.is())
709 pElement->SetModes( pNormalMode, pMouseOverMode, pSelectedMode, pDisabledMode);
710 pElement->UpdateState();
711 if (mpCurrentContainerPart.get() != NULL)
712 mpCurrentContainerPart->push_back(pElement);
716 void PresenterToolBar::Layout (
717 const Reference<rendering::XCanvas>& rxCanvas)
719 if (maElementContainer.empty())
720 return;
722 mbIsLayoutPending = false;
724 const awt::Rectangle aWindowBox (mxWindow->getPosSize());
725 ElementContainer::iterator iPart;
726 ElementContainer::iterator iEnd (maElementContainer.end());
727 ElementContainer::iterator iBegin (maElementContainer.begin());
728 ::std::vector<geometry::RealSize2D> aPartSizes (maElementContainer.size());
729 geometry::RealSize2D aTotalSize (0,0);
730 bool bIsHorizontal (true);
731 sal_Int32 nIndex;
732 double nTotalHorizontalGap (0);
733 sal_Int32 nGapCount (0);
734 for (iPart=maElementContainer.begin(),nIndex=0; iPart!=iEnd; ++iPart,++nIndex)
736 geometry::RealSize2D aSize (CalculatePartSize(rxCanvas, *iPart, bIsHorizontal));
738 // Remember the size of each part for later.
739 aPartSizes[nIndex] = aSize;
741 // Add gaps between elements.
742 if ((*iPart)->size()>1 && bIsHorizontal)
744 nTotalHorizontalGap += ((*iPart)->size() - 1) * gnGapSize;
745 nGapCount += (*iPart)->size()-1;
748 // Orientation changes for each part.
749 bIsHorizontal = !bIsHorizontal;
750 // Width is accumulated.
751 aTotalSize.Width += aSize.Width;
752 // Height is the maximum height of all parts.
753 aTotalSize.Height = ::std::max(aTotalSize.Height, aSize.Height);
755 // Add gaps between parts.
756 if (maElementContainer.size() > 1)
758 nTotalHorizontalGap += (maElementContainer.size() - 1) * gnGapSize;
759 nGapCount += maElementContainer.size()-1;
762 // Calculate the minimal size so that the window size of the tool bar
763 // can be adapted accordingly.
764 maMinimalSize = aTotalSize;
765 maMinimalSize.Width += nTotalHorizontalGap;
767 // Calculate the gaps between elements.
768 double nGapWidth (0);
769 if (nGapCount > 0)
771 if (aTotalSize.Width + nTotalHorizontalGap > aWindowBox.Width)
772 nTotalHorizontalGap = aWindowBox.Width - aTotalSize.Width;
773 nGapWidth = nTotalHorizontalGap / nGapCount;
776 // Determine the location of the left edge.
777 double nX (0);
778 switch (meAnchor)
780 case Left : nX = 0; break;
781 case Center: nX = (aWindowBox.Width - aTotalSize.Width - nTotalHorizontalGap) / 2; break;
782 case Right: nX = aWindowBox.Width - aTotalSize.Width - nTotalHorizontalGap; break;
785 // Place the parts.
786 double nY ((aWindowBox.Height - aTotalSize.Height) / 2);
787 bIsHorizontal = true;
789 maBoundingBox.X1 = nX;
790 maBoundingBox.Y1 = nY;
791 maBoundingBox.X2 = nX + aTotalSize.Width + nTotalHorizontalGap;
792 maBoundingBox.Y2 = nY + aTotalSize.Height;
794 /* push front or back ? ... */
795 /// check whether RTL interface or not
796 if(!AllSettings::GetLayoutRTL()){
797 for (iPart=maElementContainer.begin(), nIndex=0; iPart!=iEnd; ++iPart,++nIndex)
799 geometry::RealRectangle2D aBoundingBox(
800 nX, nY,
801 nX+aPartSizes[nIndex].Width, nY+aTotalSize.Height);
803 // Add space for gaps between elements.
804 if ((*iPart)->size() > 1)
805 if (bIsHorizontal)
806 aBoundingBox.X2 += ((*iPart)->size()-1) * nGapWidth;
808 LayoutPart(rxCanvas, *iPart, aBoundingBox, aPartSizes[nIndex], bIsHorizontal);
809 bIsHorizontal = !bIsHorizontal;
810 nX += aBoundingBox.X2 - aBoundingBox.X1 + nGapWidth;
813 else {
814 for (iPart=maElementContainer.end()-1, nIndex=2; iPart!=iBegin-1; --iPart, --nIndex)
816 geometry::RealRectangle2D aBoundingBox(
817 nX, nY,
818 nX+aPartSizes[nIndex].Width, nY+aTotalSize.Height);
820 // Add space for gaps between elements.
821 if ((*iPart)->size() > 1)
822 if (bIsHorizontal)
823 aBoundingBox.X2 += ((*iPart)->size()-1) * nGapWidth;
825 LayoutPart(rxCanvas, *iPart, aBoundingBox, aPartSizes[nIndex], bIsHorizontal);
826 bIsHorizontal = !bIsHorizontal;
827 nX += aBoundingBox.X2 - aBoundingBox.X1 + nGapWidth;
831 // The whole window has to be repainted.
832 ::boost::shared_ptr<PresenterPaintManager> xManager(mpPresenterController->GetPaintManager());
833 if (!xManager)
834 return;
835 xManager->Invalidate(mxWindow);
838 geometry::RealSize2D PresenterToolBar::CalculatePartSize (
839 const Reference<rendering::XCanvas>& rxCanvas,
840 const SharedElementContainerPart& rpPart,
841 const bool bIsHorizontal)
843 geometry::RealSize2D aTotalSize (0,0);
845 if (mxWindow.is())
847 // Calculate the summed width of all elements.
848 ElementContainerPart::const_iterator iElement;
849 for (iElement=rpPart->begin(); iElement!=rpPart->end(); ++iElement)
851 if (iElement->get() == NULL)
852 continue;
854 const awt::Size aBSize ((*iElement)->GetBoundingSize(rxCanvas));
855 if (bIsHorizontal)
857 aTotalSize.Width += aBSize.Width;
858 if (aBSize.Height > aTotalSize.Height)
859 aTotalSize.Height = aBSize.Height;
861 else
863 aTotalSize.Height += aBSize.Height;
864 if (aBSize.Width > aTotalSize.Width)
865 aTotalSize.Width = aBSize.Width;
869 return aTotalSize;
872 void PresenterToolBar::LayoutPart (
873 const Reference<rendering::XCanvas>& rxCanvas,
874 const SharedElementContainerPart& rpPart,
875 const geometry::RealRectangle2D& rBoundingBox,
876 const geometry::RealSize2D& rPartSize,
877 const bool bIsHorizontal)
879 double nGap (0);
880 if (rpPart->size() > 1)
882 if (bIsHorizontal)
883 nGap = (rBoundingBox.X2 - rBoundingBox.X1 - rPartSize.Width) / (rpPart->size()-1);
884 else
885 nGap = (rBoundingBox.Y2 - rBoundingBox.Y1 - rPartSize.Height) / (rpPart->size()-1);
888 // Place the elements.
889 double nX (rBoundingBox.X1);
890 double nY (rBoundingBox.Y1);
892 ElementContainerPart::const_iterator iElement;
893 ElementContainerPart::const_iterator iEnd (rpPart->end());
894 ElementContainerPart::const_iterator iBegin (rpPart->begin());
896 /// check whether RTL interface or not
897 if(!AllSettings::GetLayoutRTL()){
898 for (iElement=rpPart->begin(); iElement!=iEnd; ++iElement)
900 if (iElement->get() == NULL)
901 continue;
903 const awt::Size aElementSize ((*iElement)->GetBoundingSize(rxCanvas));
904 if (bIsHorizontal)
906 if ((*iElement)->IsFilling())
908 nY = rBoundingBox.Y1;
909 (*iElement)->SetSize(geometry::RealSize2D(aElementSize.Width, rBoundingBox.Y2 - rBoundingBox.Y1));
911 else
912 nY = rBoundingBox.Y1 + (rBoundingBox.Y2-rBoundingBox.Y1 - aElementSize.Height) / 2;
913 (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
914 nX += aElementSize.Width + nGap;
916 else
918 if ((*iElement)->IsFilling())
920 nX = rBoundingBox.X1;
921 (*iElement)->SetSize(geometry::RealSize2D(rBoundingBox.X2 - rBoundingBox.X1, aElementSize.Height));
923 else
924 nX = rBoundingBox.X1 + (rBoundingBox.X2-rBoundingBox.X1 - aElementSize.Width) / 2;
925 (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
926 nY += aElementSize.Height + nGap;
930 else {
931 for (iElement=rpPart->end()-1; iElement!=iBegin-1; --iElement)
933 if (iElement->get() == NULL)
934 continue;
936 const awt::Size aElementSize ((*iElement)->GetBoundingSize(rxCanvas));
937 if (bIsHorizontal)
939 if ((*iElement)->IsFilling())
941 nY = rBoundingBox.Y1;
942 (*iElement)->SetSize(geometry::RealSize2D(aElementSize.Width, rBoundingBox.Y2 - rBoundingBox.Y1));
944 else
945 nY = rBoundingBox.Y1 + (rBoundingBox.Y2-rBoundingBox.Y1 - aElementSize.Height) / 2;
946 (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
947 nX += aElementSize.Width + nGap;
949 else
951 // reverse presentation time with current time
952 if (iElement==iBegin){
953 iElement=iBegin+2;
955 else if (iElement==iBegin+2){
956 iElement=iBegin;
958 const awt::Size aNewElementSize ((*iElement)->GetBoundingSize(rxCanvas));
959 if ((*iElement)->IsFilling())
961 nX = rBoundingBox.X1;
962 (*iElement)->SetSize(geometry::RealSize2D(rBoundingBox.X2 - rBoundingBox.X1, aNewElementSize.Height));
964 else
965 nX = rBoundingBox.X1 + (rBoundingBox.X2-rBoundingBox.X1 - aNewElementSize.Width) / 2;
966 (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
967 nY += aNewElementSize.Height + nGap;
969 // return the index as it was before the reversing
970 if (iElement==iBegin)
971 iElement=iBegin+2;
972 else if (iElement==iBegin+2)
973 iElement=iBegin;
980 void PresenterToolBar::Paint (
981 const awt::Rectangle& rUpdateBox,
982 const rendering::ViewState& rViewState)
984 OSL_ASSERT(mxCanvas.is());
986 ElementContainer::iterator iPart;
987 ElementContainer::const_iterator iEnd (maElementContainer.end());
988 for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart)
990 ElementContainerPart::iterator iElement;
991 ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
992 for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement)
994 if (iElement->get() != NULL)
996 if ( ! (*iElement)->IsOutside(rUpdateBox))
997 (*iElement)->Paint(mxCanvas, rViewState);
1003 void PresenterToolBar::UpdateSlideNumber()
1005 if( mxSlideShowController.is() )
1007 ElementContainer::iterator iPart;
1008 ElementContainer::const_iterator iEnd (maElementContainer.end());
1009 for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart)
1011 ElementContainerPart::iterator iElement;
1012 ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
1013 for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement)
1015 if (iElement->get() != NULL)
1016 (*iElement)->CurrentSlideHasChanged();
1022 void PresenterToolBar::CheckMouseOver (
1023 const css::awt::MouseEvent& rEvent,
1024 const bool bOverWindow,
1025 const bool bMouseDown)
1027 css::awt::MouseEvent rTemp =rEvent;
1028 if(AllSettings::GetLayoutRTL()){
1029 awt::Rectangle aWindowBox = mxWindow->getPosSize();
1030 rTemp.X=aWindowBox.Width-rTemp.X;
1032 ElementContainer::iterator iPart;
1033 ElementContainer::const_iterator iEnd (maElementContainer.end());
1034 for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart)
1036 ElementContainerPart::iterator iElement;
1037 ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
1038 for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement)
1040 if (iElement->get() == NULL)
1041 continue;
1043 awt::Rectangle aBox ((*iElement)->GetBoundingBox());
1044 const bool bIsOver = bOverWindow
1045 && aBox.X <= rTemp.X
1046 && aBox.Width+aBox.X-1 >= rTemp.X
1047 && aBox.Y <= rTemp.Y
1048 && aBox.Height+aBox.Y-1 >= rTemp.Y;
1049 (*iElement)->SetState(
1050 bIsOver,
1051 bIsOver && rTemp.Buttons!=0 && bMouseDown && rTemp.ClickCount>0);
1056 void PresenterToolBar::ThrowIfDisposed() const
1057 throw (::com::sun::star::lang::DisposedException)
1059 if (rBHelper.bDisposed || rBHelper.bInDispose)
1061 throw lang::DisposedException (
1062 OUString( "PresenterToolBar has already been disposed"),
1063 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1067 //===== PresenterToolBarView ==================================================
1069 PresenterToolBarView::PresenterToolBarView (
1070 const Reference<XComponentContext>& rxContext,
1071 const Reference<XResourceId>& rxViewId,
1072 const Reference<frame::XController>& rxController,
1073 const ::rtl::Reference<PresenterController>& rpPresenterController)
1074 : PresenterToolBarViewInterfaceBase(m_aMutex),
1075 mxPane(),
1076 mxViewId(rxViewId),
1077 mxWindow(),
1078 mxCanvas(),
1079 mpPresenterController(rpPresenterController),
1080 mxSlideShowController(rpPresenterController->GetSlideShowController()),
1081 mpToolBar()
1085 Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW);
1086 Reference<XConfigurationController> xCC(xCM->getConfigurationController(),UNO_QUERY_THROW);
1087 mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW);
1089 mxWindow = mxPane->getWindow();
1090 mxCanvas = mxPane->getCanvas();
1092 mpToolBar = new PresenterToolBar(
1093 rxContext,
1094 mxWindow,
1095 mxCanvas,
1096 rpPresenterController,
1097 PresenterToolBar::Center);
1098 mpToolBar->Initialize("PresenterScreenSettings/ToolBars/ToolBar");
1100 if (mxWindow.is())
1102 mxWindow->addPaintListener(this);
1104 Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
1105 if (xPeer.is())
1106 xPeer->setBackground(util::Color(0xff000000));
1108 mxWindow->setVisible(sal_True);
1111 catch (RuntimeException&)
1113 mxViewId = NULL;
1114 throw;
1118 PresenterToolBarView::~PresenterToolBarView()
1122 void SAL_CALL PresenterToolBarView::disposing()
1124 Reference<lang::XComponent> xComponent (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY);
1125 mpToolBar = NULL;
1126 if (xComponent.is())
1127 xComponent->dispose();
1129 if (mxWindow.is())
1131 mxWindow->removePaintListener(this);
1132 mxWindow = NULL;
1134 mxCanvas = NULL;
1135 mxViewId = NULL;
1136 mxPane = NULL;
1137 mpPresenterController = NULL;
1138 mxSlideShowController = NULL;
1142 ::rtl::Reference<PresenterToolBar> PresenterToolBarView::GetPresenterToolBar() const
1144 return mpToolBar;
1147 //----- XPaintListener --------------------------------------------------------
1149 void SAL_CALL PresenterToolBarView::windowPaint (const css::awt::PaintEvent& rEvent)
1150 throw (RuntimeException, std::exception)
1152 awt::Rectangle aWindowBox (mxWindow->getPosSize());
1153 mpPresenterController->GetCanvasHelper()->Paint(
1154 mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
1155 mxCanvas,
1156 rEvent.UpdateRect,
1157 awt::Rectangle(0,0,aWindowBox.Width, aWindowBox.Height),
1158 awt::Rectangle());
1161 //----- lang::XEventListener -------------------------------------------------
1163 void SAL_CALL PresenterToolBarView::disposing (const lang::EventObject& rEventObject)
1164 throw (RuntimeException, std::exception)
1166 if (rEventObject.Source == mxWindow)
1167 mxWindow = NULL;
1170 //----- XResourceId -----------------------------------------------------------
1172 Reference<XResourceId> SAL_CALL PresenterToolBarView::getResourceId()
1173 throw (RuntimeException, std::exception)
1175 return mxViewId;
1178 sal_Bool SAL_CALL PresenterToolBarView::isAnchorOnly()
1179 throw (RuntimeException, std::exception)
1181 return false;
1184 //----- XDrawView -------------------------------------------------------------
1186 void SAL_CALL PresenterToolBarView::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
1187 throw (RuntimeException, std::exception)
1189 Reference<drawing::XDrawView> xToolBar (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY);
1190 if (xToolBar.is())
1191 xToolBar->setCurrentPage(rxSlide);
1194 Reference<drawing::XDrawPage> SAL_CALL PresenterToolBarView::getCurrentPage()
1195 throw (RuntimeException, std::exception)
1197 return NULL;
1200 //===== PresenterToolBar::Element =============================================
1202 namespace {
1204 Element::Element (
1205 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1206 : ElementInterfaceBase(m_aMutex),
1207 mpToolBar(rpToolBar),
1208 maLocation(),
1209 maSize(),
1210 mpNormal(),
1211 mpMouseOver(),
1212 mpSelected(),
1213 mpDisabled(),
1214 mpMode(),
1215 mbIsOver(false),
1216 mbIsPressed(false),
1217 mbIsSelected(false),
1218 mbIsEnabled(true)
1220 if (mpToolBar.get() != NULL)
1222 OSL_ASSERT(mpToolBar->GetPresenterController().is());
1223 OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
1227 Element::~Element()
1231 void Element::SetModes (
1232 const SharedElementMode& rpNormalMode,
1233 const SharedElementMode& rpMouseOverMode,
1234 const SharedElementMode& rpSelectedMode,
1235 const SharedElementMode& rpDisabledMode)
1237 mpNormal = rpNormalMode;
1238 mpMouseOver = rpMouseOverMode;
1239 mpSelected = rpSelectedMode;
1240 mpDisabled = rpDisabledMode;
1241 mpMode = rpNormalMode;
1244 void Element::disposing()
1248 awt::Size Element::GetBoundingSize (
1249 const Reference<rendering::XCanvas>& rxCanvas)
1251 maSize = CreateBoundingSize(rxCanvas);
1252 return maSize;
1255 awt::Rectangle Element::GetBoundingBox() const
1257 return awt::Rectangle(maLocation.X,maLocation.Y, maSize.Width, maSize.Height);
1260 void Element::CurrentSlideHasChanged()
1262 UpdateState();
1265 void Element::SetLocation (const awt::Point& rLocation)
1267 maLocation = rLocation;
1270 void Element::SetSize (const geometry::RealSize2D& rSize)
1272 maSize = awt::Size(sal_Int32(0.5+rSize.Width), sal_Int32(0.5+rSize.Height));
1275 bool Element::SetState (
1276 const bool bIsOver,
1277 const bool bIsPressed)
1279 bool bModified (mbIsOver != bIsOver || mbIsPressed != bIsPressed);
1280 bool bClicked (mbIsPressed && bIsOver && ! bIsPressed);
1282 mbIsOver = bIsOver;
1283 mbIsPressed = bIsPressed;
1285 // When the element is disabled then ignore mouse over or selection.
1286 // When the element is selected then ignore mouse over.
1287 if ( ! mbIsEnabled)
1288 mpMode = mpDisabled;
1289 else if (mbIsSelected)
1290 mpMode = mpSelected;
1291 else if (mbIsOver)
1292 mpMode = mpMouseOver;
1293 else
1294 mpMode = mpNormal;
1296 if (bClicked && mbIsEnabled)
1298 if (mpMode.get() != NULL)
1302 if (mpMode->msAction.isEmpty())
1303 break;
1305 if (mpToolBar.get() == NULL)
1306 break;
1308 if (mpToolBar->GetPresenterController().get() == NULL)
1309 break;
1311 mpToolBar->GetPresenterController()->DispatchUnoCommand(mpMode->msAction);
1312 mpToolBar->RequestLayout();
1314 while (false);
1318 else if (bModified)
1320 Invalidate();
1323 return bModified;
1326 void Element::Invalidate (const bool bSynchronous)
1328 OSL_ASSERT(mpToolBar.is());
1329 mpToolBar->InvalidateArea(GetBoundingBox(), bSynchronous);
1332 bool Element::IsOutside (const awt::Rectangle& rBox)
1334 if (rBox.X >= maLocation.X+maSize.Width)
1335 return true;
1336 else if (rBox.Y >= maLocation.Y+maSize.Height)
1337 return true;
1338 else if (maLocation.X >= rBox.X+rBox.Width)
1339 return true;
1340 else if (maLocation.Y >= rBox.Y+rBox.Height)
1341 return true;
1342 else
1343 return false;
1347 bool Element::IsFilling() const
1349 return false;
1352 void Element::UpdateState()
1354 OSL_ASSERT(mpToolBar.get() != NULL);
1355 OSL_ASSERT(mpToolBar->GetPresenterController().get() != NULL);
1357 if (mpMode.get() == NULL)
1358 return;
1360 util::URL aURL (mpToolBar->GetPresenterController()->CreateURLFromString(mpMode->msAction));
1361 Reference<frame::XDispatch> xDispatch (mpToolBar->GetPresenterController()->GetDispatch(aURL));
1362 if (xDispatch.is())
1364 xDispatch->addStatusListener(this, aURL);
1365 xDispatch->removeStatusListener(this, aURL);
1369 //----- lang::XEventListener --------------------------------------------------
1371 void SAL_CALL Element::disposing (const css::lang::EventObject& rEvent)
1372 throw(css::uno::RuntimeException, std::exception)
1374 (void)rEvent;
1377 //----- document::XEventListener ----------------------------------------------
1379 void SAL_CALL Element::notifyEvent (const css::document::EventObject& rEvent)
1380 throw(css::uno::RuntimeException, std::exception)
1382 (void)rEvent;
1383 UpdateState();
1386 //----- frame::XStatusListener ------------------------------------------------
1388 void SAL_CALL Element::statusChanged (const css::frame::FeatureStateEvent& rEvent)
1389 throw(css::uno::RuntimeException, std::exception)
1391 bool bIsSelected (mbIsSelected);
1392 bool bIsEnabled (rEvent.IsEnabled);
1393 rEvent.State >>= bIsSelected;
1395 if (bIsSelected != mbIsSelected || bIsEnabled != mbIsEnabled)
1397 mbIsEnabled = bIsEnabled;
1398 mbIsSelected = bIsSelected;
1399 SetState(mbIsOver, mbIsPressed);
1400 mpToolBar->RequestLayout();
1404 } // end of anonymous namespace
1406 //===== ElementMode ===========================================================
1408 namespace {
1410 ElementMode::ElementMode()
1411 : mpIcon(),
1412 msAction(),
1413 maText()
1417 void ElementMode::ReadElementMode (
1418 const Reference<beans::XPropertySet>& rxElementProperties,
1419 const OUString& rsModeName,
1420 ::boost::shared_ptr<ElementMode>& rpDefaultMode,
1421 ::sdext::presenter::PresenterToolBar::Context& rContext)
1425 Reference<container::XHierarchicalNameAccess> xNode (
1426 PresenterConfigurationAccess::GetProperty(rxElementProperties, rsModeName),
1427 UNO_QUERY);
1428 Reference<beans::XPropertySet> xProperties (
1429 PresenterConfigurationAccess::GetNodeProperties(xNode, OUString()));
1430 if ( ! xProperties.is() && rpDefaultMode.get()!=NULL)
1432 // The mode is not specified. Use the given, possibly empty,
1433 // default mode instead.
1434 mpIcon = rpDefaultMode->mpIcon;
1435 msAction = rpDefaultMode->msAction;
1436 maText = rpDefaultMode->maText;
1439 // Read action.
1440 if ( ! (PresenterConfigurationAccess::GetProperty(xProperties, "Action") >>= msAction))
1441 if (rpDefaultMode.get()!=NULL)
1442 msAction = rpDefaultMode->msAction;
1444 // Read text and font
1445 OUString sText (rpDefaultMode.get()!=NULL ? rpDefaultMode->maText.GetText() : OUString());
1446 PresenterConfigurationAccess::GetProperty(xProperties, "Text") >>= sText;
1447 Reference<container::XHierarchicalNameAccess> xFontNode (
1448 PresenterConfigurationAccess::GetProperty(xProperties, "Font"), UNO_QUERY);
1449 PresenterTheme::SharedFontDescriptor pFont (PresenterTheme::ReadFont(
1450 xFontNode,
1452 rpDefaultMode.get()!=NULL
1453 ? rpDefaultMode->maText.GetFont()
1454 : PresenterTheme::SharedFontDescriptor()));
1455 maText = Text(sText,pFont);
1457 // Read bitmaps to display as icons.
1458 Reference<container::XHierarchicalNameAccess> xIconNode (
1459 PresenterConfigurationAccess::GetProperty(xProperties, "Icon"), UNO_QUERY);
1460 mpIcon = PresenterBitmapContainer::LoadBitmap(
1461 xIconNode,
1463 rContext.mxPresenterHelper,
1464 rContext.mxCanvas,
1465 rpDefaultMode.get()!=NULL ? rpDefaultMode->mpIcon : SharedBitmapDescriptor());
1467 catch(Exception&)
1469 OSL_ASSERT(false);
1473 } // end of anonymous namespace
1475 //===== Button ================================================================
1477 namespace {
1479 ::rtl::Reference<Element> Button::Create (
1480 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1482 ::rtl::Reference<Button> pElement (new Button(rpToolBar));
1483 pElement->Initialize();
1484 return ::rtl::Reference<Element>(pElement.get());
1487 Button::Button (
1488 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1489 : Element(rpToolBar),
1490 mbIsListenerRegistered(false)
1492 OSL_ASSERT(mpToolBar.get() != NULL);
1493 OSL_ASSERT(mpToolBar->GetPresenterController().is());
1494 OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
1497 Button::~Button()
1501 void Button::Initialize()
1503 mpToolBar->GetPresenterController()->GetWindowManager()->AddLayoutListener(this);
1504 mbIsListenerRegistered = true;
1507 void Button::disposing()
1509 OSL_ASSERT(mpToolBar.get() != NULL);
1510 if (mpToolBar.get() != NULL
1511 && mbIsListenerRegistered)
1513 OSL_ASSERT(mpToolBar->GetPresenterController().is());
1514 OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
1516 mbIsListenerRegistered = false;
1517 mpToolBar->GetPresenterController()->GetWindowManager()->RemoveLayoutListener(this);
1519 Element::disposing();
1522 void Button::Paint (
1523 const Reference<rendering::XCanvas>& rxCanvas,
1524 const rendering::ViewState& rViewState)
1526 OSL_ASSERT(rxCanvas.is());
1528 if (mpMode.get() == NULL)
1529 return;
1531 if (mpMode->mpIcon.get() == NULL)
1532 return;
1534 geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
1535 sal_Int32 nTextHeight (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
1537 PaintIcon(rxCanvas, nTextHeight, rViewState);
1538 awt::Point aOffset(0,0);
1539 if ( ! IsEnabled())
1540 if (mpMode->mpIcon.get() != NULL)
1542 Reference<rendering::XBitmap> xBitmap (mpMode->mpIcon->GetNormalBitmap());
1543 if (xBitmap.is())
1544 aOffset.Y = xBitmap->getSize().Height;
1546 mpMode->maText.Paint(rxCanvas, rViewState, GetBoundingBox(), aOffset);
1549 awt::Size Button::CreateBoundingSize (
1550 const Reference<rendering::XCanvas>& rxCanvas)
1552 if (mpMode.get() == NULL)
1553 return awt::Size();
1555 geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
1556 const sal_Int32 nGap (5);
1557 sal_Int32 nTextHeight (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
1558 sal_Int32 nTextWidth (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.X2 - aTextBBox.X1));
1559 Reference<rendering::XBitmap> xBitmap;
1560 if (mpMode->mpIcon.get() != NULL)
1561 xBitmap = mpMode->mpIcon->GetNormalBitmap();
1562 if (xBitmap.is())
1564 geometry::IntegerSize2D aSize (xBitmap->getSize());
1565 return awt::Size(
1566 ::std::max(aSize.Width, sal_Int32(0.5 + aTextBBox.X2 - aTextBBox.X1)),
1567 aSize.Height+ nGap + nTextHeight);
1569 else
1570 return awt::Size(nTextWidth,nTextHeight);
1573 void Button::PaintIcon (
1574 const Reference<rendering::XCanvas>& rxCanvas,
1575 const sal_Int32 nTextHeight,
1576 const rendering::ViewState& rViewState)
1578 if (mpMode.get() == NULL)
1579 return;
1581 Reference<rendering::XBitmap> xBitmap (mpMode->mpIcon->GetBitmap(GetMode()));
1582 if (xBitmap.is())
1584 /// check whether RTL interface or not
1585 if(!AllSettings::GetLayoutRTL()){
1586 const sal_Int32 nX (maLocation.X
1587 + (maSize.Width-xBitmap->getSize().Width) / 2);
1588 const sal_Int32 nY (maLocation.Y
1589 + (maSize.Height - nTextHeight - xBitmap->getSize().Height) / 2);
1590 const rendering::RenderState aRenderState(
1591 geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
1592 NULL,
1593 Sequence<double>(4),
1594 rendering::CompositeOperation::OVER);
1595 rxCanvas->drawBitmap(xBitmap, rViewState, aRenderState);
1597 else {
1598 const sal_Int32 nX (maLocation.X
1599 + (maSize.Width+xBitmap->getSize().Width) / 2);
1600 const sal_Int32 nY (maLocation.Y
1601 + (maSize.Height - nTextHeight - xBitmap->getSize().Height) / 2);
1602 const rendering::RenderState aRenderState(
1603 geometry::AffineMatrix2D(-1,0,nX, 0,1,nY),
1604 NULL,
1605 Sequence<double>(4),
1606 rendering::CompositeOperation::OVER);
1607 rxCanvas->drawBitmap(xBitmap, rViewState, aRenderState);
1612 PresenterBitmapDescriptor::Mode Button::GetMode() const
1614 if ( ! IsEnabled())
1615 return PresenterBitmapDescriptor::Disabled;
1616 else if (mbIsPressed)
1617 return PresenterBitmapDescriptor::ButtonDown;
1618 else if (mbIsOver)
1619 return PresenterBitmapDescriptor::MouseOver;
1620 else
1621 return PresenterBitmapDescriptor::Normal;
1624 //----- lang::XEventListener --------------------------------------------------
1626 void SAL_CALL Button::disposing (const css::lang::EventObject& rEvent)
1627 throw(css::uno::RuntimeException, std::exception)
1629 (void)rEvent;
1630 mbIsListenerRegistered = false;
1631 Element::disposing(rEvent);
1634 } // end of anonymous namespace
1636 //===== PresenterToolBar::Label ===============================================
1638 namespace {
1640 Label::Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1641 : Element(rpToolBar)
1645 awt::Size Label::CreateBoundingSize (
1646 const Reference<rendering::XCanvas>& rxCanvas)
1648 if (mpMode.get() == NULL)
1649 return awt::Size(0,0);
1651 geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
1652 return awt::Size(
1653 sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.X2 - aTextBBox.X1),
1654 sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
1657 void Label::SetText (const OUString& rsText)
1659 OSL_ASSERT(mpToolBar.get() != NULL);
1660 if (mpMode.get() == NULL)
1661 return;
1663 const bool bRequestLayout (mpMode->maText.GetText().getLength() != rsText.getLength());
1665 mpMode->maText.SetText(rsText);
1666 // Just use the character count for determing whether a layout is
1667 // necessary. This is an optimization to avoid layouts every time a new
1668 // time value is set on some labels.
1669 if (bRequestLayout)
1670 mpToolBar->RequestLayout();
1671 else
1672 Invalidate(false);
1675 void Label::Paint (
1676 const Reference<rendering::XCanvas>& rxCanvas,
1677 const rendering::ViewState& rViewState)
1679 OSL_ASSERT(rxCanvas.is());
1680 if (mpMode.get() == NULL)
1681 return;
1683 mpMode->maText.Paint(rxCanvas, rViewState, GetBoundingBox(), awt::Point(0,0));
1686 bool Label::SetState (const bool bIsOver, const bool bIsPressed)
1688 // For labels there is no mouse over effect.
1689 (void)bIsOver;
1690 (void)bIsPressed;
1691 return Element::SetState(false, false);
1694 } // end of anonymous namespace
1696 //===== Text ==================================================================
1698 namespace {
1700 Text::Text()
1701 : msText(),
1702 mpFont()
1706 Text::Text (
1707 const OUString& rsText,
1708 const PresenterTheme::SharedFontDescriptor& rpFont)
1709 : msText(rsText),
1710 mpFont(rpFont)
1714 void Text::SetText (const OUString& rsText)
1716 msText = rsText;
1719 OUString Text::GetText() const
1721 return msText;
1724 PresenterTheme::SharedFontDescriptor Text::GetFont() const
1726 return mpFont;
1729 void Text::Paint (
1730 const Reference<rendering::XCanvas>& rxCanvas,
1731 const rendering::ViewState& rViewState,
1732 const awt::Rectangle& rBoundingBox,
1733 const awt::Point& rOffset)
1735 (void)rOffset;
1736 OSL_ASSERT(rxCanvas.is());
1738 if (msText.isEmpty())
1739 return;
1740 if (mpFont.get() == NULL)
1741 return;
1743 if ( ! mpFont->mxFont.is())
1744 mpFont->PrepareFont(rxCanvas);
1745 if ( ! mpFont->mxFont.is())
1746 return;
1748 rendering::StringContext aContext (msText, 0, msText.getLength());
1750 Reference<rendering::XTextLayout> xLayout (
1751 mpFont->mxFont->createTextLayout(
1752 aContext,
1753 rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
1754 0));
1755 geometry::RealRectangle2D aBox (xLayout->queryTextBounds());
1756 const double nTextWidth = aBox.X2 - aBox.X1;
1757 const double nY = rBoundingBox.Y + rBoundingBox.Height - aBox.Y2;
1758 const double nX = rBoundingBox.X + (rBoundingBox.Width - nTextWidth)/2;
1760 rendering::RenderState aRenderState(
1761 geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
1762 NULL,
1763 Sequence<double>(4),
1764 rendering::CompositeOperation::SOURCE);
1765 PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);
1766 rxCanvas->drawTextLayout(
1767 xLayout,
1768 rViewState,
1769 aRenderState);
1772 geometry::RealRectangle2D Text::GetBoundingBox (const Reference<rendering::XCanvas>& rxCanvas)
1774 if (mpFont.get() != NULL && !msText.isEmpty())
1776 if ( ! mpFont->mxFont.is())
1777 mpFont->PrepareFont(rxCanvas);
1778 if (mpFont->mxFont.is())
1780 rendering::StringContext aContext (msText, 0, msText.getLength());
1781 Reference<rendering::XTextLayout> xLayout (
1782 mpFont->mxFont->createTextLayout(
1783 aContext,
1784 rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
1785 0));
1786 return xLayout->queryTextBounds();
1789 return geometry::RealRectangle2D(0,0,0,0);
1792 //===== TimeFormatter =========================================================
1794 TimeFormatter::TimeFormatter()
1795 : mbIs24HourFormat(true),
1796 mbIsAmPmFormat(false),
1797 mbIsShowSeconds(true)
1801 OUString TimeFormatter::FormatTime (const oslDateTime& rTime)
1803 OUStringBuffer sText;
1805 const sal_Int32 nHours (sal::static_int_cast<sal_Int32>(rTime.Hours));
1806 const sal_Int32 nMinutes (sal::static_int_cast<sal_Int32>(rTime.Minutes));
1807 const sal_Int32 nSeconds(sal::static_int_cast<sal_Int32>(rTime.Seconds));
1808 // Hours
1809 if (mbIs24HourFormat)
1810 sText.append(OUString::number(nHours));
1811 else
1812 sText.append(OUString::number(
1813 sal::static_int_cast<sal_Int32>(nHours>12 ? nHours-12 : nHours)));
1815 sText.append(":");
1817 // Minutes
1818 const OUString sMinutes (OUString::number(nMinutes));
1819 if (sMinutes.getLength() == 1)
1820 sText.append("0");
1821 sText.append(sMinutes);
1823 // Seconds
1824 if (mbIsShowSeconds)
1826 sText.append(":");
1827 const OUString sSeconds (OUString::number(nSeconds));
1828 if (sSeconds.getLength() == 1)
1829 sText.append("0");
1830 sText.append(sSeconds);
1832 if (mbIsAmPmFormat)
1834 if (rTime.Hours < 12)
1835 sText.append("am");
1836 else
1837 sText.append("pm");
1839 return sText.makeStringAndClear();
1842 //===== TimeLabel =============================================================
1844 TimeLabel::TimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1845 : Label(rpToolBar),
1846 mpListener()
1850 void SAL_CALL TimeLabel::disposing()
1852 PresenterClockTimer::Instance(mpToolBar->GetComponentContext())->RemoveListener(mpListener);
1853 mpListener.reset();
1856 void TimeLabel::ConnectToTimer()
1858 mpListener.reset(new Listener(this));
1859 PresenterClockTimer::Instance(mpToolBar->GetComponentContext())->AddListener(mpListener);
1862 //===== CurrentTimeLabel ======================================================
1864 ::rtl::Reference<Element> CurrentTimeLabel::Create (
1865 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1867 ::rtl::Reference<TimeLabel> pElement(new CurrentTimeLabel(rpToolBar));
1868 pElement->ConnectToTimer();
1869 return ::rtl::Reference<Element>(pElement.get());
1872 CurrentTimeLabel::~CurrentTimeLabel()
1876 CurrentTimeLabel::CurrentTimeLabel (
1877 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1878 : TimeLabel(rpToolBar),
1879 maTimeFormatter()
1883 void CurrentTimeLabel::TimeHasChanged (const oslDateTime& rCurrentTime)
1885 SetText(maTimeFormatter.FormatTime(rCurrentTime));
1886 Invalidate(false);
1889 void CurrentTimeLabel::SetModes (
1890 const SharedElementMode& rpNormalMode,
1891 const SharedElementMode& rpMouseOverMode,
1892 const SharedElementMode& rpSelectedMode,
1893 const SharedElementMode& rpDisabledMode)
1895 TimeLabel::SetModes(rpNormalMode, rpMouseOverMode, rpSelectedMode, rpDisabledMode);
1896 SetText(maTimeFormatter.FormatTime(PresenterClockTimer::GetCurrentTime()));
1899 //===== PresentationTimeLabel =================================================
1901 ::rtl::Reference<Element> PresentationTimeLabel::Create (
1902 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1904 ::rtl::Reference<TimeLabel> pElement(new PresentationTimeLabel(rpToolBar));
1905 pElement->ConnectToTimer();
1906 return ::rtl::Reference<Element>(pElement.get());
1909 PresentationTimeLabel::~PresentationTimeLabel()
1913 PresentationTimeLabel::PresentationTimeLabel (
1914 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1915 : TimeLabel(rpToolBar),
1916 maTimeFormatter(),
1917 maStartTimeValue()
1919 maStartTimeValue.Seconds = 0;
1920 maStartTimeValue.Nanosec = 0;
1923 void PresentationTimeLabel::TimeHasChanged (const oslDateTime& rCurrentTime)
1925 TimeValue aCurrentTimeValue;
1926 if (osl_getTimeValueFromDateTime(&rCurrentTime, &aCurrentTimeValue))
1928 if (maStartTimeValue.Seconds==0 && maStartTimeValue.Nanosec==0)
1930 // This method is called for the first time. Initialize the
1931 // start time. The start time is rounded to nearest second to
1932 // keep the time updates synchronized with the current time label.
1933 maStartTimeValue = aCurrentTimeValue;
1934 if (maStartTimeValue.Nanosec >= 500000000)
1935 maStartTimeValue.Seconds += 1;
1936 maStartTimeValue.Nanosec = 0;
1939 TimeValue aElapsedTimeValue;
1940 aElapsedTimeValue.Seconds = aCurrentTimeValue.Seconds - maStartTimeValue.Seconds;
1941 aElapsedTimeValue.Nanosec = aCurrentTimeValue.Nanosec - maStartTimeValue.Nanosec;
1943 oslDateTime aElapsedDateTime;
1944 if (osl_getDateTimeFromTimeValue(&aElapsedTimeValue, &aElapsedDateTime))
1946 SetText(maTimeFormatter.FormatTime(aElapsedDateTime));
1947 Invalidate(false);
1952 void PresentationTimeLabel::SetModes (
1953 const SharedElementMode& rpNormalMode,
1954 const SharedElementMode& rpMouseOverMode,
1955 const SharedElementMode& rpSelectedMode,
1956 const SharedElementMode& rpDisabledMode)
1958 TimeLabel::SetModes(rpNormalMode, rpMouseOverMode, rpSelectedMode, rpDisabledMode);
1960 oslDateTime aStartDateTime;
1961 if (osl_getDateTimeFromTimeValue(&maStartTimeValue, &aStartDateTime))
1963 SetText(maTimeFormatter.FormatTime(aStartDateTime));
1967 //===== VerticalSeparator =====================================================
1969 VerticalSeparator::VerticalSeparator (
1970 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1971 : Element(rpToolBar)
1975 void VerticalSeparator::Paint (
1976 const Reference<rendering::XCanvas>& rxCanvas,
1977 const rendering::ViewState& rViewState)
1979 OSL_ASSERT(rxCanvas.is());
1981 awt::Rectangle aBBox (GetBoundingBox());
1983 rendering::RenderState aRenderState(
1984 geometry::AffineMatrix2D(1,0,0, 0,1,0),
1985 NULL,
1986 Sequence<double>(4),
1987 rendering::CompositeOperation::OVER);
1988 if (mpMode.get() != NULL)
1990 PresenterTheme::SharedFontDescriptor pFont (mpMode->maText.GetFont());
1991 if (pFont.get() != NULL)
1992 PresenterCanvasHelper::SetDeviceColor(aRenderState, pFont->mnColor);
1995 if (aBBox.Height >= gnMinimalSeparatorSize + 2*gnSeparatorInset)
1997 aBBox.Height -= 2*gnSeparatorInset;
1998 aBBox.Y += gnSeparatorInset;
2000 rxCanvas->fillPolyPolygon(
2001 PresenterGeometryHelper::CreatePolygon(aBBox, rxCanvas->getDevice()),
2002 rViewState,
2003 aRenderState);
2006 awt::Size VerticalSeparator::CreateBoundingSize (
2007 const Reference<rendering::XCanvas>& rxCanvas)
2009 (void)rxCanvas;
2010 return awt::Size(1,20);
2013 bool VerticalSeparator::IsFilling() const
2015 return true;
2018 //===== HorizontalSeparator ===================================================
2020 HorizontalSeparator::HorizontalSeparator (
2021 const ::rtl::Reference<PresenterToolBar>& rpToolBar)
2022 : Element(rpToolBar)
2026 void HorizontalSeparator::Paint (
2027 const Reference<rendering::XCanvas>& rxCanvas,
2028 const rendering::ViewState& rViewState)
2030 OSL_ASSERT(rxCanvas.is());
2032 awt::Rectangle aBBox (GetBoundingBox());
2034 rendering::RenderState aRenderState(
2035 geometry::AffineMatrix2D(1,0,0, 0,1,0),
2036 NULL,
2037 Sequence<double>(4),
2038 rendering::CompositeOperation::OVER);
2039 if (mpMode.get() != NULL)
2041 PresenterTheme::SharedFontDescriptor pFont (mpMode->maText.GetFont());
2042 if (pFont.get() != NULL)
2043 PresenterCanvasHelper::SetDeviceColor(aRenderState, pFont->mnColor);
2046 if (aBBox.Width >= gnMinimalSeparatorSize+2*gnSeparatorInset)
2048 aBBox.Width -= 2*gnSeparatorInset;
2049 aBBox.X += gnSeparatorInset;
2051 rxCanvas->fillPolyPolygon(
2052 PresenterGeometryHelper::CreatePolygon(aBBox, rxCanvas->getDevice()),
2053 rViewState,
2054 aRenderState);
2057 awt::Size HorizontalSeparator::CreateBoundingSize (
2058 const Reference<rendering::XCanvas>& rxCanvas)
2060 (void)rxCanvas;
2061 return awt::Size(20,1);
2064 bool HorizontalSeparator::IsFilling() const
2066 return true;
2069 } // end of anonymous namespace
2071 } } // end of namespace ::sdext::presenter
2073 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */