1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sdext.hxx"
26 
27 #include "PresenterToolBar.hxx"
28 
29 #include "PresenterBitmapContainer.hxx"
30 #include "PresenterCanvasHelper.hxx"
31 #include "PresenterComponent.hxx"
32 #include "PresenterGeometryHelper.hxx"
33 #include "PresenterPaintManager.hxx"
34 #include "PresenterPaneBase.hxx"
35 #include "PresenterPaneFactory.hxx"
36 #include "PresenterTimer.hxx"
37 #include "PresenterWindowManager.hxx"
38 
39 #include <cppuhelper/compbase2.hxx>
40 #include <com/sun/star/awt/FontDescriptor.hpp>
41 #include <com/sun/star/awt/PosSize.hpp>
42 #include <com/sun/star/awt/XWindowPeer.hpp>
43 #include <com/sun/star/deployment/XPackageInformationProvider.hpp>
44 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
45 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
46 #include <com/sun/star/drawing/framework/XPane.hpp>
47 #include <com/sun/star/geometry/AffineMatrix2D.hpp>
48 #include <com/sun/star/lang/XServiceName.hpp>
49 #include <com/sun/star/rendering/CompositeOperation.hpp>
50 #include <com/sun/star/rendering/RenderState.hpp>
51 #include <com/sun/star/rendering/TextDirection.hpp>
52 #include <com/sun/star/rendering/ViewState.hpp>
53 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
54 #include <com/sun/star/text/XTextRange.hpp>
55 #include <com/sun/star/util/Color.hpp>
56 #include <com/sun/star/util/XURLTransformer.hpp>
57 #include <rtl/ustrbuf.hxx>
58 #include <boost/bind.hpp>
59 #include <boost/function.hpp>
60 #include <boost/enable_shared_from_this.hpp>
61 #include <map>
62 
63 using namespace ::com::sun::star;
64 using namespace ::com::sun::star::uno;
65 using namespace ::com::sun::star::drawing::framework;
66 using ::rtl::OUString;
67 
68 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
69 
70 namespace sdext { namespace presenter {
71 
72 static const sal_Int32 gnGapSize (20);
73 static const sal_Int32 gnMinimalSeparatorSize (20);
74 static const sal_Int32 gnSeparatorInset (0);
75 
76 namespace {
77 
78     class Text
79     {
80     public:
81         Text (void);
82         Text (const Text& rText);
83         Text (
84             const OUString& rsText,
85             const PresenterTheme::SharedFontDescriptor& rpFont);
86 
87         void SetText (const OUString& rsText);
88         OUString GetText (void) const;
89         PresenterTheme::SharedFontDescriptor GetFont (void) const;
90 
91         void Paint (
92             const Reference<rendering::XCanvas>& rxCanvas,
93             const rendering::ViewState& rViewState,
94             const awt::Rectangle& rBoundingBox,
95             const awt::Point& rOffset);
96 
97         geometry::RealRectangle2D GetBoundingBox (
98             const Reference<rendering::XCanvas>& rxCanvas);
99 
100     private:
101         OUString msText;
102         PresenterTheme::SharedFontDescriptor mpFont;
103     };
104 
105     class ElementMode
106         : private ::boost::noncopyable
107     {
108     public:
109         ElementMode (void);
110 
111         SharedBitmapDescriptor mpIcon;
112         OUString msAction;
113         Text maText;
114 
115         void ReadElementMode (
116             const Reference<beans::XPropertySet>& rxProperties,
117             const ::rtl::OUString& rsModeName,
118             ::boost::shared_ptr<ElementMode>& rpDefaultMode,
119             ::sdext::presenter::PresenterToolBar::Context& rContext);
120     };
121     typedef ::boost::shared_ptr<ElementMode> SharedElementMode;
122 
123 }  // end of anonymous namespace
124 
125 
126 class PresenterToolBar::Context
127     : private ::boost::noncopyable
128 {
129 public:
130     ::rtl::OUString msBasePath;
131     Reference<drawing::XPresenterHelper> mxPresenterHelper;
132     css::uno::Reference<css::rendering::XCanvas> mxCanvas;
133 };
134 
135 
136 
137 
138 //===== PresenterToolBar::Element =============================================
139 
140 namespace {
141     typedef cppu::WeakComponentImplHelper2<
142         css::document::XEventListener,
143         css::frame::XStatusListener
144         > ElementInterfaceBase;
145 
146     class Element
147         : private ::cppu::BaseMutex,
148           private ::boost::noncopyable,
149           public ElementInterfaceBase
150     {
151     public:
152         Element (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
153         virtual ~Element (void);
154 
155         virtual void SAL_CALL disposing (void);
156 
157         virtual void SetModes (
158             const SharedElementMode& rpNormalMode,
159             const SharedElementMode& rpMouseOverMode,
160             const SharedElementMode& rpSelectedMode,
161             const SharedElementMode& rpDisabledMode);
162         virtual void CurrentSlideHasChanged (void);
163         virtual void SetLocation (const awt::Point& rLocation);
164         virtual void SetSize (const geometry::RealSize2D& rSize);
165         virtual void Paint (
166             const Reference<rendering::XCanvas>& rxCanvas,
167             const rendering::ViewState& rViewState) = 0;
168         awt::Size GetBoundingSize (
169             const Reference<rendering::XCanvas>& rxCanvas);
170         awt::Rectangle GetBoundingBox (void) const;
171         virtual bool SetState (const bool bIsOver, const bool bIsPressed);
172         virtual void Invalidate (const bool bSynchronous = true);
173         virtual bool IsOutside (const awt::Rectangle& rBox);
174         virtual bool IsFilling (void) const;
175         void UpdateState (void);
176 
177         OUString GetAction (void) const;
178 
179         // lang::XEventListener
180 
181         virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent)
182             throw(css::uno::RuntimeException);
183 
184         // document::XEventListener
185 
186         virtual void SAL_CALL notifyEvent (const css::document::EventObject& rEvent)
187             throw(css::uno::RuntimeException);
188 
189         // frame::XStatusListener
190 
191         virtual void SAL_CALL statusChanged (const css::frame::FeatureStateEvent& rEvent)
192             throw(css::uno::RuntimeException);
193 
194     protected:
195         ::rtl::Reference<PresenterToolBar> mpToolBar;
196         awt::Point maLocation;
197         awt::Size maSize;
198         SharedElementMode mpNormal;
199         SharedElementMode mpMouseOver;
200         SharedElementMode mpSelected;
201         SharedElementMode mpDisabled;
202         SharedElementMode mpMode;
203         bool mbIsOver;
204         bool mbIsPressed;
205         bool mbIsSelected;
206 
207         virtual awt::Size CreateBoundingSize (
208             const Reference<rendering::XCanvas>& rxCanvas) = 0;
209 
210         bool IsEnabled (void) const;
211         void SetEnabledState (const bool bIsEnabled);
212 
213     private:
214         bool mbIsEnabled;
215     };
216 
217 } // end of anonymous namespace
218 
219 
220 class PresenterToolBar::ElementContainerPart
221     : public ::std::vector<rtl::Reference<Element> >
222 {
223 };
224 
225 
226 
227 
228 //===== Button ================================================================
229 
230 namespace {
231 
232     class Button : public Element
233     {
234     public:
235         static ::rtl::Reference<Element> Create (
236             const ::rtl::Reference<PresenterToolBar>& rpToolBar);
237 
238         virtual ~Button (void);
239         virtual void SAL_CALL disposing (void);
240 
241         virtual void Paint (
242             const Reference<rendering::XCanvas>& rxCanvas,
243             const rendering::ViewState& rViewState);
244 
245         // lang::XEventListener
246 
247         virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent)
248             throw(css::uno::RuntimeException);
249 
250     protected:
251         virtual awt::Size CreateBoundingSize (
252             const Reference<rendering::XCanvas>& rxCanvas);
253 
254     private:
255         bool mbIsListenerRegistered;
256 
257         Button (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
258         void Initialize (void);
259         void PaintIcon (
260             const Reference<rendering::XCanvas>& rxCanvas,
261             const sal_Int32 nTextHeight,
262             const rendering::ViewState& rViewState);
263         PresenterBitmapDescriptor::Mode GetMode (void) const;
264     };
265 
266 
267 
268 
269 //===== Label =================================================================
270 
271     class Label : public Element
272     {
273     public:
274         Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
275 
276         void SetText (const OUString& rsText);
277         virtual void Paint (
278             const Reference<rendering::XCanvas>& rxCanvas,
279             const rendering::ViewState& rViewState);
280         virtual bool SetState (const bool bIsOver, const bool bIsPressed);
281 
282     protected:
283         virtual awt::Size CreateBoundingSize (
284             const Reference<rendering::XCanvas>& rxCanvas);
285     };
286 
287 
288 // Some specialized controls.
289 
290 
291     class ProgressLabel : public Label
292     {
293     public:
294         ProgressLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
295         virtual void CurrentSlideHasChanged (void);
296     };
297 
298     class TimeFormatter
299     {
300     public:
301         TimeFormatter (void);
302         OUString FormatTime (const oslDateTime& rTime);
303     private:
304         bool mbIs24HourFormat;
305         bool mbIsAmPmFormat;
306         bool mbIsShowSeconds;
307     };
308 
309     class TimeLabel : public Label
310     {
311     public:
312         void ConnectToTimer (void);
313         virtual void TimeHasChanged (const oslDateTime& rCurrentTime) = 0;
314     protected:
315         TimeLabel(const ::rtl::Reference<PresenterToolBar>& rpToolBar);
316         using Element::disposing;
317         virtual void SAL_CALL disposing (void);
318     private:
319         class Listener : public PresenterClockTimer::Listener
320         {
321         public:
322             Listener (const ::rtl::Reference<TimeLabel>& rxLabel)
323                 : mxLabel(rxLabel) {}
324             virtual ~Listener (void) {}
325             virtual void TimeHasChanged (const oslDateTime& rCurrentTime)
326             { if (mxLabel.is()) mxLabel->TimeHasChanged(rCurrentTime); }
327         private:
328             ::rtl::Reference<TimeLabel> mxLabel;
329         };
330         ::boost::shared_ptr<PresenterClockTimer::Listener> mpListener;
331     };
332 
333     class CurrentTimeLabel : public TimeLabel
334     {
335     public:
336         static ::rtl::Reference<Element> Create (
337             const ::rtl::Reference<PresenterToolBar>& rpToolBar);
338         virtual void SetModes (
339             const SharedElementMode& rpNormalMode,
340             const SharedElementMode& rpMouseOverMode,
341             const SharedElementMode& rpSelectedMode,
342             const SharedElementMode& rpDisabledMode);
343     private:
344         TimeFormatter maTimeFormatter;
345         CurrentTimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
346         virtual ~CurrentTimeLabel (void);
347         virtual void TimeHasChanged (const oslDateTime& rCurrentTime);
348     };
349 
350     class PresentationTimeLabel : public TimeLabel
351     {
352     public:
353         static ::rtl::Reference<Element> Create (
354             const ::rtl::Reference<PresenterToolBar>& rpToolBar);
355         virtual void SetModes (
356             const SharedElementMode& rpNormalMode,
357             const SharedElementMode& rpMouseOverMode,
358             const SharedElementMode& rpSelectedMode,
359             const SharedElementMode& rpDisabledMode);
360     private:
361         TimeFormatter maTimeFormatter;
362         TimeValue maStartTimeValue;
363         PresentationTimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
364         virtual ~PresentationTimeLabel (void);
365         virtual void TimeHasChanged (const oslDateTime& rCurrentTime);
366     };
367 
368     class VerticalSeparator : public Element
369     {
370     public:
371         explicit VerticalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
372         virtual void Paint (
373             const Reference<rendering::XCanvas>& rxCanvas,
374             const rendering::ViewState& rViewState);
375         virtual bool IsFilling (void) const;
376 
377     protected:
378         virtual awt::Size CreateBoundingSize (
379             const Reference<rendering::XCanvas>& rxCanvas);
380     };
381 
382     class HorizontalSeparator : public Element
383     {
384     public:
385         explicit HorizontalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
386         virtual void Paint (
387             const Reference<rendering::XCanvas>& rxCanvas,
388             const rendering::ViewState& rViewState);
389         virtual bool IsFilling (void) const;
390 
391     protected:
392         virtual awt::Size CreateBoundingSize (
393             const Reference<rendering::XCanvas>& rxCanvas);
394     };
395 } // end of anonymous namespace
396 
397 
398 
399 //===== PresenterToolBar ======================================================
400 
401 PresenterToolBar::PresenterToolBar (
402     const Reference<XComponentContext>& rxContext,
403     const css::uno::Reference<css::awt::XWindow>& rxWindow,
404     const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
405     const ::rtl::Reference<PresenterController>& rpPresenterController,
406     const Anchor eAnchor)
407     : PresenterToolBarInterfaceBase(m_aMutex),
408       mxComponentContext(rxContext),
409       maElementContainer(),
410       mpCurrentContainerPart(),
411       mxWindow(rxWindow),
412       mxCanvas(rxCanvas),
413       mxSlideShowController(),
414       mxCurrentSlide(),
415       mpPresenterController(rpPresenterController),
416       mbIsLayoutPending(false),
417       meAnchor(eAnchor),
418       maBoundingBox(),
419       maMinimalSize()
420 {
421 }
422 
423 
424 
425 
426 void PresenterToolBar::Initialize (
427     const ::rtl::OUString& rsConfigurationPath)
428 {
429     try
430     {
431         CreateControls(rsConfigurationPath);
432 
433         if (mxWindow.is())
434         {
435             mxWindow->addWindowListener(this);
436             mxWindow->addPaintListener(this);
437             mxWindow->addMouseListener(this);
438             mxWindow->addMouseMotionListener(this);
439 
440             Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
441             if (xPeer.is())
442                 xPeer->setBackground(util::Color(0xff000000));
443 
444             mxWindow->setVisible(sal_True);
445         }
446 
447         mxSlideShowController = mpPresenterController->GetSlideShowController();
448         UpdateSlideNumber();
449         mbIsLayoutPending = true;
450     }
451     catch (RuntimeException&)
452     {
453         mpCurrentContainerPart.reset();
454         maElementContainer.clear();
455         throw;
456     }
457 }
458 
459 
460 
461 
462 PresenterToolBar::~PresenterToolBar (void)
463 {
464 }
465 
466 
467 
468 
469 void SAL_CALL PresenterToolBar::disposing (void)
470 {
471     if (mxWindow.is())
472     {
473         mxWindow->removeWindowListener(this);
474         mxWindow->removePaintListener(this);
475         mxWindow->removeMouseListener(this);
476         mxWindow->removeMouseMotionListener(this);
477         mxWindow = NULL;
478     }
479 
480     // Dispose tool bar elements.
481     ElementContainer::iterator iPart (maElementContainer.begin());
482     ElementContainer::const_iterator iEnd (maElementContainer.end());
483     for ( ; iPart!=iEnd; ++iPart)
484     {
485         OSL_ASSERT(iPart->get()!=NULL);
486         ElementContainerPart::iterator iElement ((*iPart)->begin());
487         ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
488         for ( ; iElement!=iPartEnd; ++iElement)
489         {
490             if (iElement->get() != NULL)
491             {
492                 ::rtl::Reference<Element> pElement (*iElement);
493                 Reference<lang::XComponent> xComponent (
494                     static_cast<XWeak*>(pElement.get()), UNO_QUERY);
495                 if (xComponent.is())
496                     xComponent->dispose();
497             }
498         }
499     }
500 
501     mpCurrentContainerPart.reset();
502     maElementContainer.clear();
503 }
504 
505 
506 
507 
508 void PresenterToolBar::InvalidateArea (
509     const awt::Rectangle& rRepaintBox,
510     const bool bSynchronous)
511 {
512     mpPresenterController->GetPaintManager()->Invalidate(
513         mxWindow,
514         rRepaintBox,
515         bSynchronous);
516 }
517 
518 
519 
520 
521 sal_Int32 PresenterToolBar::GetCurrentSlideIndex (void)
522 {
523     if (mxSlideShowController.is())
524         return mxSlideShowController->getCurrentSlideIndex();
525     else
526         return -1;
527 }
528 
529 
530 
531 
532 sal_Int32 PresenterToolBar::GetSlideCount (void)
533 {
534     if (mxSlideShowController.is())
535         return mxSlideShowController->getSlideCount();
536     else
537         return 0;
538 }
539 
540 
541 
542 
543 void PresenterToolBar::RequestLayout (void)
544 {
545     mbIsLayoutPending = true;
546 
547     mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
548 }
549 
550 
551 
552 
553 geometry::RealSize2D PresenterToolBar::GetSize (void)
554 {
555     if (mbIsLayoutPending)
556         Layout(mxCanvas);
557     return geometry::RealSize2D(
558         maBoundingBox.X2 - maBoundingBox.X1,
559         maBoundingBox.Y2 - maBoundingBox.Y1);
560 }
561 
562 
563 
564 
565 geometry::RealSize2D PresenterToolBar::GetMinimalSize (void)
566 {
567     if (mbIsLayoutPending)
568         Layout(mxCanvas);
569     return maMinimalSize;
570 }
571 
572 
573 
574 
575 ::rtl::Reference<PresenterController> PresenterToolBar::GetPresenterController (void) const
576 {
577     return mpPresenterController;
578 }
579 
580 
581 
582 
583 Reference<awt::XWindow> PresenterToolBar::GetWindow (void) const
584 {
585     return mxWindow;
586 }
587 
588 
589 
590 
591 Reference<XComponentContext> PresenterToolBar::GetComponentContext (void) const
592 {
593     return mxComponentContext;
594 }
595 
596 
597 
598 
599 //-----  lang::XEventListener -------------------------------------------------
600 
601 void SAL_CALL PresenterToolBar::disposing (const lang::EventObject& rEventObject)
602     throw (RuntimeException)
603 {
604     if (rEventObject.Source == mxWindow)
605         mxWindow = NULL;
606 }
607 
608 
609 
610 
611 //----- XWindowListener -------------------------------------------------------
612 
613 void SAL_CALL PresenterToolBar::windowResized (const awt::WindowEvent& rEvent)
614     throw (RuntimeException)
615 {
616     (void)rEvent;
617     mbIsLayoutPending = true;
618 }
619 
620 
621 
622 
623 void SAL_CALL PresenterToolBar::windowMoved (const awt::WindowEvent& rEvent)
624     throw (RuntimeException)
625 {
626     (void)rEvent;
627 }
628 
629 
630 
631 
632 void SAL_CALL PresenterToolBar::windowShown (const lang::EventObject& rEvent)
633     throw (RuntimeException)
634 {
635     (void)rEvent;
636     mbIsLayoutPending = true;
637 }
638 
639 
640 
641 
642 void SAL_CALL PresenterToolBar::windowHidden (const lang::EventObject& rEvent)
643     throw (RuntimeException)
644 {
645     (void)rEvent;
646 }
647 
648 
649 
650 
651 //----- XPaintListener --------------------------------------------------------
652 
653 void SAL_CALL PresenterToolBar::windowPaint (const css::awt::PaintEvent& rEvent)
654     throw (RuntimeException)
655 {
656     if ( ! mxCanvas.is())
657         return;
658 
659     if ( ! mbIsPresenterViewActive)
660         return;
661 
662     const rendering::ViewState aViewState (
663         geometry::AffineMatrix2D(1,0,0, 0,1,0),
664         PresenterGeometryHelper::CreatePolygon(rEvent.UpdateRect, mxCanvas->getDevice()));
665 
666     if (mbIsLayoutPending)
667         Layout(mxCanvas);
668 
669     Paint(rEvent.UpdateRect, aViewState);
670 
671     // Make the back buffer visible.
672     Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
673     if (xSpriteCanvas.is())
674         xSpriteCanvas->updateScreen(sal_False);
675 }
676 
677 
678 
679 
680 //----- XMouseListener --------------------------------------------------------
681 
682 void SAL_CALL PresenterToolBar::mousePressed (const css::awt::MouseEvent& rEvent)
683     throw(css::uno::RuntimeException)
684 {
685     CheckMouseOver(rEvent, true, true);
686 }
687 
688 
689 
690 
691 void SAL_CALL PresenterToolBar::mouseReleased (const css::awt::MouseEvent& rEvent)
692     throw(css::uno::RuntimeException)
693 {
694     CheckMouseOver(rEvent, true);
695 }
696 
697 
698 
699 
700 void SAL_CALL PresenterToolBar::mouseEntered (const css::awt::MouseEvent& rEvent)
701     throw(css::uno::RuntimeException)
702 {
703     CheckMouseOver(rEvent, true);
704 }
705 
706 
707 
708 
709 void SAL_CALL PresenterToolBar::mouseExited (const css::awt::MouseEvent& rEvent)
710     throw(css::uno::RuntimeException)
711 {
712     CheckMouseOver(rEvent, false);
713 }
714 
715 
716 
717 
718 //----- XMouseMotionListener --------------------------------------------------
719 
720 void SAL_CALL PresenterToolBar::mouseMoved (const css::awt::MouseEvent& rEvent)
721     throw (css::uno::RuntimeException)
722 {
723     ThrowIfDisposed();
724 
725     CheckMouseOver(rEvent, true);
726 }
727 
728 
729 
730 
731 void SAL_CALL PresenterToolBar::mouseDragged (const css::awt::MouseEvent& rEvent)
732     throw (css::uno::RuntimeException)
733 {
734     ThrowIfDisposed();
735     (void)rEvent;
736 }
737 
738 
739 
740 
741 //----- XDrawView -------------------------------------------------------------
742 
743 void SAL_CALL PresenterToolBar::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
744     throw (RuntimeException)
745 {
746     if (rxSlide != mxCurrentSlide)
747     {
748         mxCurrentSlide = rxSlide;
749         UpdateSlideNumber();
750     }
751 }
752 
753 
754 
755 
756 Reference<drawing::XDrawPage> SAL_CALL PresenterToolBar::getCurrentPage (void)
757     throw (RuntimeException)
758 {
759     return mxCurrentSlide;
760 }
761 
762 
763 
764 
765 //-----------------------------------------------------------------------------
766 
767 void PresenterToolBar::CreateControls (
768     const ::rtl::OUString& rsConfigurationPath)
769 {
770     if ( ! mxWindow.is())
771         return;
772 
773     // Expand the macro in the bitmap file names.
774     PresenterConfigurationAccess aConfiguration (
775         mxComponentContext,
776         OUString::createFromAscii("/org.openoffice.Office.extension.PresenterScreen/"),
777         PresenterConfigurationAccess::READ_ONLY);
778 
779     const OUString sBasePath (PresenterComponent::GetBasePath(mxComponentContext));
780 
781     mpCurrentContainerPart.reset(new ElementContainerPart());
782     maElementContainer.clear();
783     maElementContainer.push_back(mpCurrentContainerPart);
784 
785     Reference<container::XHierarchicalNameAccess> xToolBarNode (
786         aConfiguration.GetConfigurationNode(rsConfigurationPath),
787         UNO_QUERY);
788     if (xToolBarNode.is())
789     {
790         Reference<container::XNameAccess> xEntries (
791             PresenterConfigurationAccess::GetConfigurationNode(xToolBarNode, A2S("Entries")),
792             UNO_QUERY);
793         Context aContext;
794         aContext.msBasePath = sBasePath;
795         aContext.mxPresenterHelper = mpPresenterController->GetPresenterHelper();
796         aContext.mxCanvas = mxCanvas;
797         if (xEntries.is()
798             && aContext.mxPresenterHelper.is()
799             && aContext.mxCanvas.is())
800         {
801             PresenterConfigurationAccess::ForAll(
802                 xEntries,
803                 ::boost::bind(&PresenterToolBar::ProcessEntry, this, _2, ::boost::ref(aContext)));
804         }
805     }
806 }
807 
808 
809 
810 
811 void PresenterToolBar::ProcessEntry (
812     const Reference<beans::XPropertySet>& rxProperties,
813     Context& rContext)
814 {
815     if ( ! rxProperties.is())
816         return;
817 
818     // Type has to be present.
819     OUString sType;
820     if ( ! (PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Type")) >>= sType))
821         return;
822 
823     OUString sName;
824     PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Name")) >>= sName;
825 
826     // Read mode specific values.
827     SharedElementMode pNormalMode (new ElementMode());
828     SharedElementMode pMouseOverMode (new ElementMode());
829     SharedElementMode pSelectedMode (new ElementMode());
830     SharedElementMode pDisabledMode (new ElementMode());
831     pNormalMode->ReadElementMode(rxProperties, A2S("Normal"), pNormalMode, rContext);
832     pMouseOverMode->ReadElementMode(rxProperties, A2S("MouseOver"), pNormalMode, rContext);
833     pSelectedMode->ReadElementMode(rxProperties, A2S("Selected"), pNormalMode, rContext);
834     pDisabledMode->ReadElementMode(rxProperties, A2S("Disabled"), pNormalMode, rContext);
835 
836     // Create new element.
837     ::rtl::Reference<Element> pElement;
838     if (sType.equalsAscii("Button"))
839         pElement = Button::Create(this);
840     else if (sType.equalsAscii("CurrentTimeLabel"))
841         pElement = CurrentTimeLabel::Create(this);
842     else if (sType.equalsAscii("PresentationTimeLabel"))
843         pElement = PresentationTimeLabel::Create(this);
844     else if (sType.equalsAscii("VerticalSeparator"))
845         pElement = ::rtl::Reference<Element>(new VerticalSeparator(this));
846     else if (sType.equalsAscii("HorizontalSeparator"))
847         pElement = ::rtl::Reference<Element>(new HorizontalSeparator(this));
848     else if (sType.equalsAscii("Label"))
849         pElement = ::rtl::Reference<Element>(new Label(this));
850     else if (sType.equalsAscii("ChangeOrientation"))
851     {
852         mpCurrentContainerPart.reset(new ElementContainerPart());
853         maElementContainer.push_back(mpCurrentContainerPart);
854         return;
855     }
856     if (pElement.is())
857     {
858         pElement->SetModes( pNormalMode, pMouseOverMode, pSelectedMode, pDisabledMode);
859         pElement->UpdateState();
860         if (mpCurrentContainerPart.get() != NULL)
861             mpCurrentContainerPart->push_back(pElement);
862     }
863 }
864 
865 
866 
867 
868 void PresenterToolBar::Layout (
869     const Reference<rendering::XCanvas>& rxCanvas)
870 {
871     if (maElementContainer.size() == 0)
872         return;
873 
874     mbIsLayoutPending = false;
875 
876     const awt::Rectangle aWindowBox (mxWindow->getPosSize());
877     ElementContainer::iterator iPart;
878     ElementContainer::iterator iEnd (maElementContainer.end());
879     ::std::vector<geometry::RealSize2D> aPartSizes (maElementContainer.size());
880     geometry::RealSize2D aTotalSize (0,0);
881 	bool bIsHorizontal (true);
882     sal_Int32 nIndex;
883     double nTotalHorizontalGap (0);
884     sal_Int32 nGapCount (0);
885     for (iPart=maElementContainer.begin(),nIndex=0; iPart!=iEnd; ++iPart,++nIndex)
886     {
887         geometry::RealSize2D aSize (CalculatePartSize(rxCanvas, *iPart, bIsHorizontal));
888 
889         // Remember the size of each part for later.
890         aPartSizes[nIndex] = aSize;
891 
892         // Add gaps between elements.
893         if ((*iPart)->size()>1 && bIsHorizontal)
894         {
895             nTotalHorizontalGap += ((*iPart)->size() - 1) * gnGapSize;
896             nGapCount += (*iPart)->size()-1;
897         }
898 
899         // Orientation changes for each part.
900         bIsHorizontal = !bIsHorizontal;
901         // Width is accumulated.
902         aTotalSize.Width += aSize.Width;
903         // Height is the maximum height of all parts.
904         aTotalSize.Height = ::std::max(aTotalSize.Height, aSize.Height);
905     }
906     // Add gaps between parts.
907     if (maElementContainer.size() > 1)
908     {
909         nTotalHorizontalGap += (maElementContainer.size() - 1) * gnGapSize;
910         nGapCount += maElementContainer.size()-1;
911     }
912 
913     // Calculate the minimal size so that the window size of the tool bar
914     // can be adapted accordingly.
915     maMinimalSize = aTotalSize;
916     maMinimalSize.Width += nTotalHorizontalGap;
917 
918     // Calculate the gaps between elements.
919     double nGapWidth (0);
920     if (nGapCount > 0)
921     {
922         if (aTotalSize.Width + nTotalHorizontalGap > aWindowBox.Width)
923             nTotalHorizontalGap = aWindowBox.Width - aTotalSize.Width;
924         nGapWidth = nTotalHorizontalGap / nGapCount;
925     }
926 
927     // Determine the location of the left edge.
928     double nX (0);
929     switch (meAnchor)
930     {
931         case Left : nX = 0; break;
932         case Center: nX = (aWindowBox.Width - aTotalSize.Width - nTotalHorizontalGap) / 2; break;
933         case Right: nX = aWindowBox.Width - aTotalSize.Width - nTotalHorizontalGap; break;
934     }
935 
936     // Place the parts.
937     double nY ((aWindowBox.Height - aTotalSize.Height) / 2);
938     bIsHorizontal = true;
939 
940     maBoundingBox.X1 = nX;
941     maBoundingBox.Y1 = nY;
942     maBoundingBox.X2 = nX + aTotalSize.Width + nTotalHorizontalGap;
943     maBoundingBox.Y2 = nY + aTotalSize.Height;
944 
945     for (iPart=maElementContainer.begin(), nIndex=0; iPart!=iEnd; ++iPart,++nIndex)
946     {
947         geometry::RealRectangle2D aBoundingBox(
948             nX, nY,
949             nX+aPartSizes[nIndex].Width, nY+aTotalSize.Height);
950 
951         // Add space for gaps between elements.
952         if ((*iPart)->size() > 1)
953             if (bIsHorizontal)
954                 aBoundingBox.X2 += ((*iPart)->size()-1) * nGapWidth;
955 
956         LayoutPart(rxCanvas, *iPart, aBoundingBox, aPartSizes[nIndex], bIsHorizontal);
957         bIsHorizontal = !bIsHorizontal;
958         nX += aBoundingBox.X2 - aBoundingBox.X1 + nGapWidth;
959     }
960 
961     // The whole window has to be repainted.
962     mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
963 }
964 
965 
966 
967 
968 geometry::RealSize2D PresenterToolBar::CalculatePartSize (
969     const Reference<rendering::XCanvas>& rxCanvas,
970     const SharedElementContainerPart& rpPart,
971     const bool bIsHorizontal)
972 {
973     geometry::RealSize2D aTotalSize (0,0);
974 
975     if (mxWindow.is())
976     {
977         const awt::Rectangle aWindowBox (mxWindow->getPosSize());
978 
979         // Calculate the summed width of all elements.
980         ElementContainerPart::const_iterator iElement;
981         for (iElement=rpPart->begin(); iElement!=rpPart->end(); ++iElement)
982         {
983             if (iElement->get() == NULL)
984                 continue;
985 
986             const awt::Size aBSize ((*iElement)->GetBoundingSize(rxCanvas));
987             if (bIsHorizontal)
988             {
989                 aTotalSize.Width += aBSize.Width;
990                 if (aBSize.Height > aTotalSize.Height)
991                     aTotalSize.Height = aBSize.Height;
992             }
993             else
994             {
995                 aTotalSize.Height += aBSize.Height;
996                 if (aBSize.Width > aTotalSize.Width)
997                     aTotalSize.Width = aBSize.Width;
998             }
999         }
1000     }
1001     return aTotalSize;
1002 }
1003 
1004 
1005 
1006 
1007 void PresenterToolBar::LayoutPart (
1008     const Reference<rendering::XCanvas>& rxCanvas,
1009     const SharedElementContainerPart& rpPart,
1010     const geometry::RealRectangle2D& rBoundingBox,
1011     const geometry::RealSize2D& rPartSize,
1012     const bool bIsHorizontal)
1013 {
1014     double nGap (0);
1015     if (rpPart->size() > 1)
1016     {
1017         if (bIsHorizontal)
1018             nGap = (rBoundingBox.X2 - rBoundingBox.X1 - rPartSize.Width) / (rpPart->size()-1);
1019         else
1020             nGap = (rBoundingBox.Y2 - rBoundingBox.Y1 - rPartSize.Height) / (rpPart->size()-1);
1021     }
1022 
1023     // Place the elements.
1024     double nX (rBoundingBox.X1);
1025     double nY (rBoundingBox.Y1);
1026 
1027     ElementContainerPart::const_iterator iElement;
1028     ElementContainerPart::const_iterator iEnd (rpPart->end());
1029     for (iElement=rpPart->begin(); iElement!=iEnd; ++iElement)
1030     {
1031         if (iElement->get() == NULL)
1032             continue;
1033 
1034         const awt::Size aElementSize ((*iElement)->GetBoundingSize(rxCanvas));
1035         if (bIsHorizontal)
1036         {
1037             if ((*iElement)->IsFilling())
1038             {
1039                 nY = rBoundingBox.Y1;
1040                 (*iElement)->SetSize(geometry::RealSize2D(aElementSize.Width, rBoundingBox.Y2 - rBoundingBox.Y1));
1041             }
1042             else
1043                 nY = rBoundingBox.Y1 + (rBoundingBox.Y2-rBoundingBox.Y1 - aElementSize.Height) / 2;
1044             (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
1045             nX += aElementSize.Width + nGap;
1046         }
1047         else
1048         {
1049             if ((*iElement)->IsFilling())
1050             {
1051                 nX = rBoundingBox.X1;
1052                 (*iElement)->SetSize(geometry::RealSize2D(rBoundingBox.X2 - rBoundingBox.X1, aElementSize.Height));
1053             }
1054             else
1055                 nX = rBoundingBox.X1 + (rBoundingBox.X2-rBoundingBox.X1 - aElementSize.Width) / 2;
1056             (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
1057             nY += aElementSize.Height + nGap;
1058         }
1059     }
1060 }
1061 
1062 
1063 
1064 
1065 void PresenterToolBar::Paint (
1066     const awt::Rectangle& rUpdateBox,
1067     const rendering::ViewState& rViewState)
1068 {
1069     OSL_ASSERT(mxCanvas.is());
1070 
1071     ElementContainer::iterator iPart;
1072     ElementContainer::const_iterator iEnd (maElementContainer.end());
1073     for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart)
1074     {
1075         ElementContainerPart::iterator iElement;
1076         ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
1077         for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement)
1078         {
1079             if (iElement->get() != NULL)
1080             {
1081                 if ( ! (*iElement)->IsOutside(rUpdateBox))
1082                     (*iElement)->Paint(mxCanvas, rViewState);
1083             }
1084         }
1085     }
1086 }
1087 
1088 
1089 
1090 
1091 void PresenterToolBar::UpdateSlideNumber (void)
1092 {
1093 	if( mxSlideShowController.is() )
1094 	{
1095         ElementContainer::iterator iPart;
1096         ElementContainer::const_iterator iEnd (maElementContainer.end());
1097         for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart)
1098         {
1099             ElementContainerPart::iterator iElement;
1100             ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
1101             for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement)
1102             {
1103                 if (iElement->get() != NULL)
1104                     (*iElement)->CurrentSlideHasChanged();
1105             }
1106         }
1107 	}
1108 }
1109 
1110 
1111 
1112 
1113 void PresenterToolBar::CheckMouseOver (
1114     const css::awt::MouseEvent& rEvent,
1115     const bool bOverWindow,
1116     const bool bMouseDown)
1117 {
1118     ElementContainer::iterator iPart;
1119     ElementContainer::const_iterator iEnd (maElementContainer.end());
1120     for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart)
1121     {
1122         ElementContainerPart::iterator iElement;
1123         ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
1124         for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement)
1125         {
1126             if (iElement->get() == NULL)
1127                 continue;
1128 
1129             awt::Rectangle aBox ((*iElement)->GetBoundingBox());
1130             const bool bIsOver = bOverWindow
1131                 && aBox.X <= rEvent.X
1132                 && aBox.Width+aBox.X-1 >= rEvent.X
1133                 && aBox.Y <= rEvent.Y
1134                 && aBox.Height+aBox.Y-1 >= rEvent.Y;
1135             (*iElement)->SetState(
1136                 bIsOver,
1137                 bIsOver && rEvent.Buttons!=0 && bMouseDown && rEvent.ClickCount>0);
1138         }
1139     }
1140 }
1141 
1142 
1143 
1144 
1145 void PresenterToolBar::ThrowIfDisposed (void) const
1146     throw (::com::sun::star::lang::DisposedException)
1147 {
1148 	if (rBHelper.bDisposed || rBHelper.bInDispose)
1149 	{
1150         throw lang::DisposedException (
1151             OUString(RTL_CONSTASCII_USTRINGPARAM(
1152                 "PresenterToolBar has already been disposed")),
1153             const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1154     }
1155 }
1156 
1157 
1158 
1159 
1160 //===== PresenterToolBarView ==================================================
1161 
1162 PresenterToolBarView::PresenterToolBarView (
1163     const Reference<XComponentContext>& rxContext,
1164     const Reference<XResourceId>& rxViewId,
1165     const Reference<frame::XController>& rxController,
1166     const ::rtl::Reference<PresenterController>& rpPresenterController)
1167     : PresenterToolBarViewInterfaceBase(m_aMutex),
1168       mxPane(),
1169       mxViewId(rxViewId),
1170       mxWindow(),
1171       mxCanvas(),
1172       mpPresenterController(rpPresenterController),
1173       mxSlideShowController(rpPresenterController->GetSlideShowController()),
1174       mpToolBar()
1175 {
1176     try
1177     {
1178         Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW);
1179         Reference<XConfigurationController> xCC(xCM->getConfigurationController(),UNO_QUERY_THROW);
1180         mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW);
1181 
1182         mxWindow = mxPane->getWindow();
1183         mxCanvas = mxPane->getCanvas();
1184 
1185         mpToolBar = new PresenterToolBar(
1186             rxContext,
1187             mxWindow,
1188             mxCanvas,
1189             rpPresenterController,
1190             PresenterToolBar::Center);
1191         mpToolBar->Initialize(A2S("PresenterScreenSettings/ToolBars/ToolBar"));
1192 
1193         if (mxWindow.is())
1194         {
1195             mxWindow->addPaintListener(this);
1196 
1197             Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
1198             if (xPeer.is())
1199                 xPeer->setBackground(util::Color(0xff000000));
1200 
1201             mxWindow->setVisible(sal_True);
1202         }
1203     }
1204     catch (RuntimeException&)
1205     {
1206         mxViewId = NULL;
1207         throw;
1208     }
1209 }
1210 
1211 
1212 
1213 
1214 PresenterToolBarView::~PresenterToolBarView (void)
1215 {
1216 }
1217 
1218 
1219 
1220 
1221 void SAL_CALL PresenterToolBarView::disposing (void)
1222 {
1223     Reference<lang::XComponent> xComponent (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY);
1224     mpToolBar = NULL;
1225     if (xComponent.is())
1226         xComponent->dispose();
1227 
1228     if (mxWindow.is())
1229     {
1230         mxWindow->removePaintListener(this);
1231         mxWindow = NULL;
1232     }
1233     mxCanvas = NULL;
1234     mxViewId = NULL;
1235     mxPane = NULL;
1236     mpPresenterController = NULL;
1237     mxSlideShowController = NULL;
1238 
1239 }
1240 
1241 
1242 
1243 
1244 ::rtl::Reference<PresenterToolBar> PresenterToolBarView::GetPresenterToolBar (void) const
1245 {
1246     return mpToolBar;
1247 }
1248 
1249 
1250 
1251 
1252 //----- XPaintListener --------------------------------------------------------
1253 
1254 void SAL_CALL PresenterToolBarView::windowPaint (const css::awt::PaintEvent& rEvent)
1255     throw (RuntimeException)
1256 {
1257     awt::Rectangle aWindowBox (mxWindow->getPosSize());
1258     mpPresenterController->GetCanvasHelper()->Paint(
1259         mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
1260         mxCanvas,
1261         rEvent.UpdateRect,
1262         awt::Rectangle(0,0,aWindowBox.Width, aWindowBox.Height),
1263         awt::Rectangle());
1264 }
1265 
1266 
1267 
1268 
1269 //-----  lang::XEventListener -------------------------------------------------
1270 
1271 void SAL_CALL PresenterToolBarView::disposing (const lang::EventObject& rEventObject)
1272     throw (RuntimeException)
1273 {
1274     if (rEventObject.Source == mxWindow)
1275         mxWindow = NULL;
1276 }
1277 
1278 
1279 
1280 
1281 //----- XResourceId -----------------------------------------------------------
1282 
1283 Reference<XResourceId> SAL_CALL PresenterToolBarView::getResourceId (void)
1284     throw (RuntimeException)
1285 {
1286     return mxViewId;
1287 }
1288 
1289 
1290 
1291 
1292 sal_Bool SAL_CALL PresenterToolBarView::isAnchorOnly (void)
1293     throw (RuntimeException)
1294 {
1295     return false;
1296 }
1297 
1298 
1299 
1300 
1301 //----- XDrawView -------------------------------------------------------------
1302 
1303 void SAL_CALL PresenterToolBarView::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
1304     throw (RuntimeException)
1305 {
1306     Reference<drawing::XDrawView> xToolBar (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY);
1307     if (xToolBar.is())
1308         xToolBar->setCurrentPage(rxSlide);
1309 }
1310 
1311 
1312 
1313 
1314 Reference<drawing::XDrawPage> SAL_CALL PresenterToolBarView::getCurrentPage (void)
1315     throw (RuntimeException)
1316 {
1317     return NULL;
1318 }
1319 
1320 
1321 
1322 
1323 //-----------------------------------------------------------------------------
1324 
1325 void PresenterToolBarView::ThrowIfDisposed (void) const
1326     throw (::com::sun::star::lang::DisposedException)
1327 {
1328 	if (rBHelper.bDisposed || rBHelper.bInDispose)
1329 	{
1330         throw lang::DisposedException (
1331             OUString(RTL_CONSTASCII_USTRINGPARAM(
1332                 "PresenterToolBarView has already been disposed")),
1333             const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
1334     }
1335 }
1336 
1337 
1338 
1339 
1340 //===== PresenterToolBar::Element =============================================
1341 
1342 namespace {
1343 
1344 Element::Element (
1345     const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1346     : ElementInterfaceBase(m_aMutex),
1347       mpToolBar(rpToolBar),
1348       maLocation(),
1349       maSize(),
1350       mpNormal(),
1351       mpMouseOver(),
1352       mpSelected(),
1353       mpDisabled(),
1354       mpMode(),
1355       mbIsOver(false),
1356       mbIsPressed(false),
1357       mbIsSelected(false),
1358       mbIsEnabled(true)
1359 {
1360     if (mpToolBar.get() != NULL)
1361     {
1362         OSL_ASSERT(mpToolBar->GetPresenterController().is());
1363         OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
1364     }
1365 }
1366 
1367 
1368 
1369 
1370 Element::~Element (void)
1371 {
1372 }
1373 
1374 
1375 
1376 
1377 void Element::SetModes (
1378     const SharedElementMode& rpNormalMode,
1379     const SharedElementMode& rpMouseOverMode,
1380     const SharedElementMode& rpSelectedMode,
1381     const SharedElementMode& rpDisabledMode)
1382 {
1383     mpNormal = rpNormalMode;
1384     mpMouseOver = rpMouseOverMode;
1385     mpSelected = rpSelectedMode;
1386     mpDisabled = rpDisabledMode;
1387     mpMode = rpNormalMode;
1388 }
1389 
1390 
1391 
1392 
1393 void Element::disposing (void)
1394 {
1395 }
1396 
1397 
1398 
1399 
1400 awt::Size Element::GetBoundingSize (
1401     const Reference<rendering::XCanvas>& rxCanvas)
1402 {
1403     maSize = CreateBoundingSize(rxCanvas);
1404     return maSize;
1405 }
1406 
1407 
1408 
1409 
1410 awt::Rectangle Element::GetBoundingBox (void) const
1411 {
1412     return awt::Rectangle(maLocation.X,maLocation.Y, maSize.Width, maSize.Height);
1413 }
1414 
1415 
1416 
1417 
1418 void Element::CurrentSlideHasChanged (void)
1419 {
1420     UpdateState();
1421 }
1422 
1423 
1424 
1425 
1426 void Element::SetLocation (const awt::Point& rLocation)
1427 {
1428     maLocation = rLocation;
1429 }
1430 
1431 
1432 
1433 void Element::SetSize (const geometry::RealSize2D& rSize)
1434 {
1435     maSize = awt::Size(sal_Int32(0.5+rSize.Width), sal_Int32(0.5+rSize.Height));
1436 }
1437 
1438 
1439 
1440 
1441 bool Element::SetState (
1442     const bool bIsOver,
1443     const bool bIsPressed)
1444 {
1445     bool bModified (mbIsOver != bIsOver || mbIsPressed != bIsPressed);
1446     bool bClicked (mbIsPressed && bIsOver && ! bIsPressed);
1447 
1448     mbIsOver = bIsOver;
1449     mbIsPressed = bIsPressed;
1450 
1451     // When the element is disabled then ignore mouse over or selection.
1452     // When the element is selected then ignore mouse over.
1453     if ( ! mbIsEnabled)
1454         mpMode = mpDisabled;
1455     else if (mbIsSelected)
1456         mpMode = mpSelected;
1457     else if (mbIsOver)
1458         mpMode = mpMouseOver;
1459     else
1460         mpMode = mpNormal;
1461 
1462     if (bClicked && mbIsEnabled)
1463     {
1464         if (mpMode.get() != NULL)
1465         {
1466             do
1467             {
1468                 if (mpMode->msAction.getLength() <= 0)
1469                     break;
1470 
1471                 if (mpToolBar.get() == NULL)
1472                     break;
1473 
1474                 if (mpToolBar->GetPresenterController().get() == NULL)
1475                     break;
1476 
1477                 mpToolBar->GetPresenterController()->DispatchUnoCommand(mpMode->msAction);
1478                 mpToolBar->RequestLayout();
1479             }
1480             while (false);
1481         }
1482 
1483     }
1484     else if (bModified)
1485     {
1486         Invalidate();
1487     }
1488 
1489     return bModified;
1490 }
1491 
1492 
1493 
1494 
1495 void Element::Invalidate (const bool bSynchronous)
1496 {
1497     OSL_ASSERT(mpToolBar.is());
1498     mpToolBar->InvalidateArea(GetBoundingBox(), bSynchronous);
1499 }
1500 
1501 
1502 
1503 
1504 bool Element::IsOutside (const awt::Rectangle& rBox)
1505 {
1506     if (rBox.X >= maLocation.X+maSize.Width)
1507         return true;
1508     else if (rBox.Y >= maLocation.Y+maSize.Height)
1509         return true;
1510     else if (maLocation.X >= rBox.X+rBox.Width)
1511         return true;
1512     else if (maLocation.Y >= rBox.Y+rBox.Height)
1513         return true;
1514     else
1515         return false;
1516 }
1517 
1518 
1519 
1520 bool Element::IsEnabled (void) const
1521 {
1522     return mbIsEnabled;
1523 }
1524 
1525 
1526 
1527 
1528 void Element::SetEnabledState (const bool bIsEnabled)
1529 {
1530     mbIsEnabled = bIsEnabled;
1531 }
1532 
1533 
1534 
1535 
1536 bool Element::IsFilling (void) const
1537 {
1538     return false;
1539 }
1540 
1541 
1542 
1543 
1544 void Element::UpdateState (void)
1545 {
1546     OSL_ASSERT(mpToolBar.get() != NULL);
1547     OSL_ASSERT(mpToolBar->GetPresenterController().get() != NULL);
1548 
1549     if (mpMode.get() == NULL)
1550         return;
1551 
1552     util::URL aURL (mpToolBar->GetPresenterController()->CreateURLFromString(mpMode->msAction));
1553     Reference<frame::XDispatch> xDispatch (mpToolBar->GetPresenterController()->GetDispatch(aURL));
1554     if (xDispatch.is())
1555     {
1556         xDispatch->addStatusListener(this, aURL);
1557         xDispatch->removeStatusListener(this, aURL);
1558     }
1559 }
1560 
1561 
1562 
1563 
1564 //----- lang::XEventListener --------------------------------------------------
1565 
1566 void SAL_CALL Element::disposing (const css::lang::EventObject& rEvent)
1567     throw(css::uno::RuntimeException)
1568 {
1569     (void)rEvent;
1570 }
1571 
1572 
1573 
1574 
1575 //----- document::XEventListener ----------------------------------------------
1576 
1577 void SAL_CALL Element::notifyEvent (const css::document::EventObject& rEvent)
1578     throw(css::uno::RuntimeException)
1579 {
1580     (void)rEvent;
1581     UpdateState();
1582 }
1583 
1584 
1585 
1586 
1587 //----- frame::XStatusListener ------------------------------------------------
1588 
1589 void SAL_CALL Element::statusChanged (const css::frame::FeatureStateEvent& rEvent)
1590     throw(css::uno::RuntimeException)
1591 {
1592     bool bIsSelected (mbIsSelected);
1593     bool bIsEnabled (rEvent.IsEnabled);
1594     rEvent.State >>= bIsSelected;
1595 
1596     if (bIsSelected != mbIsSelected || bIsEnabled != mbIsEnabled)
1597     {
1598         mbIsEnabled = bIsEnabled;
1599         mbIsSelected = bIsSelected;
1600         SetState(mbIsOver, mbIsPressed);
1601         mpToolBar->RequestLayout();
1602     }
1603 }
1604 
1605 } // end of anonymous namespace
1606 
1607 
1608 
1609 
1610 //===== ElementMode ===========================================================
1611 
1612 namespace {
1613 
1614 ElementMode::ElementMode (void)
1615     : mpIcon(),
1616       msAction(),
1617       maText()
1618 {
1619 }
1620 
1621 
1622 
1623 
1624 void ElementMode::ReadElementMode (
1625     const Reference<beans::XPropertySet>& rxElementProperties,
1626     const OUString& rsModeName,
1627     ::boost::shared_ptr<ElementMode>& rpDefaultMode,
1628     ::sdext::presenter::PresenterToolBar::Context& rContext)
1629 {
1630     try
1631     {
1632     Reference<container::XHierarchicalNameAccess> xNode (
1633         PresenterConfigurationAccess::GetProperty(rxElementProperties, rsModeName),
1634         UNO_QUERY);
1635     Reference<beans::XPropertySet> xProperties (
1636         PresenterConfigurationAccess::GetNodeProperties(xNode, OUString()));
1637     if ( ! xProperties.is() && rpDefaultMode.get()!=NULL)
1638     {
1639         // The mode is not specified.  Use the given, possibly empty,
1640         // default mode instead.
1641         mpIcon = rpDefaultMode->mpIcon;
1642         msAction = rpDefaultMode->msAction;
1643         maText = rpDefaultMode->maText;
1644     }
1645 
1646     // Read action.
1647     if ( ! (PresenterConfigurationAccess::GetProperty(xProperties, A2S("Action")) >>= msAction))
1648         if (rpDefaultMode.get()!=NULL)
1649             msAction = rpDefaultMode->msAction;
1650 
1651     // Read text and font
1652     OUString sText (rpDefaultMode.get()!=NULL ? rpDefaultMode->maText.GetText() : OUString());
1653     PresenterConfigurationAccess::GetProperty(xProperties, A2S("Text")) >>= sText;
1654     Reference<container::XHierarchicalNameAccess> xFontNode (
1655         PresenterConfigurationAccess::GetProperty(xProperties, A2S("Font")), UNO_QUERY);
1656     PresenterTheme::SharedFontDescriptor pFont (PresenterTheme::ReadFont(
1657         xFontNode,
1658         A2S(""),
1659         rpDefaultMode.get()!=NULL
1660             ? rpDefaultMode->maText.GetFont()
1661             : PresenterTheme::SharedFontDescriptor()));
1662     maText = Text(sText,pFont);
1663 
1664     // Read bitmaps to display as icons.
1665     Reference<container::XHierarchicalNameAccess> xIconNode (
1666         PresenterConfigurationAccess::GetProperty(xProperties, A2S("Icon")), UNO_QUERY);
1667     mpIcon = PresenterBitmapContainer::LoadBitmap(
1668         xIconNode,
1669         A2S(""),
1670         rContext.mxPresenterHelper,
1671         rContext.msBasePath,
1672         rContext.mxCanvas,
1673         rpDefaultMode.get()!=NULL ? rpDefaultMode->mpIcon : SharedBitmapDescriptor());
1674     }
1675     catch(Exception&)
1676     {
1677         OSL_ASSERT(false);
1678     }
1679 }
1680 
1681 } // end of anonymous namespace
1682 
1683 
1684 
1685 
1686 //===== Button ================================================================
1687 
1688 namespace {
1689 
1690 ::rtl::Reference<Element> Button::Create (
1691     const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1692 {
1693     ::rtl::Reference<Button> pElement (new Button(rpToolBar));
1694     pElement->Initialize();
1695     return ::rtl::Reference<Element>(pElement.get());
1696 }
1697 
1698 
1699 
1700 
1701 Button::Button (
1702     const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1703     : Element(rpToolBar),
1704       mbIsListenerRegistered(false)
1705 {
1706     OSL_ASSERT(mpToolBar.get() != NULL);
1707     OSL_ASSERT(mpToolBar->GetPresenterController().is());
1708     OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
1709 }
1710 
1711 
1712 
1713 
1714 Button::~Button (void)
1715 {
1716 }
1717 
1718 
1719 
1720 
1721 void Button::Initialize (void)
1722 {
1723     mpToolBar->GetPresenterController()->GetWindowManager()->AddLayoutListener(this);
1724     mbIsListenerRegistered = true;
1725 }
1726 
1727 
1728 
1729 
1730 void Button::disposing (void)
1731 {
1732     OSL_ASSERT(mpToolBar.get() != NULL);
1733     if (mpToolBar.get() != NULL
1734         && mbIsListenerRegistered)
1735     {
1736         OSL_ASSERT(mpToolBar->GetPresenterController().is());
1737         OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
1738 
1739         mbIsListenerRegistered = false;
1740         mpToolBar->GetPresenterController()->GetWindowManager()->RemoveLayoutListener(this);
1741     }
1742     Element::disposing();
1743 }
1744 
1745 
1746 
1747 
1748 void Button::Paint (
1749     const Reference<rendering::XCanvas>& rxCanvas,
1750     const rendering::ViewState& rViewState)
1751 {
1752     OSL_ASSERT(rxCanvas.is());
1753 
1754     if (mpMode.get() == NULL)
1755         return;
1756 
1757     if (mpMode->mpIcon.get() == NULL)
1758         return;
1759 
1760     geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
1761     sal_Int32 nTextHeight (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
1762 
1763     PaintIcon(rxCanvas, nTextHeight, rViewState);
1764     awt::Point aOffset(0,0);
1765     if ( ! IsEnabled())
1766         if (mpMode->mpIcon.get() != NULL)
1767         {
1768             Reference<rendering::XBitmap> xBitmap (mpMode->mpIcon->GetNormalBitmap());
1769             if (xBitmap.is())
1770                 aOffset.Y = xBitmap->getSize().Height;
1771         }
1772     mpMode->maText.Paint(rxCanvas, rViewState, GetBoundingBox(), aOffset);
1773 }
1774 
1775 
1776 
1777 
1778 awt::Size Button::CreateBoundingSize (
1779     const Reference<rendering::XCanvas>& rxCanvas)
1780 {
1781     if (mpMode.get() == NULL)
1782         return awt::Size();
1783 
1784     geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
1785     const sal_Int32 nGap (5);
1786     sal_Int32 nTextHeight (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
1787     sal_Int32 nTextWidth (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.X2 - aTextBBox.X1));
1788     Reference<rendering::XBitmap> xBitmap;
1789     if (mpMode->mpIcon.get() != NULL)
1790         xBitmap = mpMode->mpIcon->GetNormalBitmap();
1791     if (xBitmap.is())
1792     {
1793         geometry::IntegerSize2D aSize (xBitmap->getSize());
1794         return awt::Size(
1795             ::std::max(aSize.Width, sal_Int32(0.5 + aTextBBox.X2 - aTextBBox.X1)),
1796             aSize.Height+ nGap + nTextHeight);
1797     }
1798     else
1799         return awt::Size(nTextWidth,nTextHeight);
1800 }
1801 
1802 
1803 
1804 
1805 void Button::PaintIcon (
1806     const Reference<rendering::XCanvas>& rxCanvas,
1807     const sal_Int32 nTextHeight,
1808     const rendering::ViewState& rViewState)
1809 {
1810     if (mpMode.get() == NULL)
1811         return;
1812 
1813     Reference<rendering::XBitmap> xBitmap (mpMode->mpIcon->GetBitmap(GetMode()));
1814     if (xBitmap.is())
1815     {
1816         const sal_Int32 nX (maLocation.X
1817             + (maSize.Width-xBitmap->getSize().Width) / 2);
1818         const sal_Int32 nY (maLocation.Y
1819             + (maSize.Height - nTextHeight - xBitmap->getSize().Height) / 2);
1820         const rendering::RenderState aRenderState(
1821             geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
1822             NULL,
1823             Sequence<double>(4),
1824             rendering::CompositeOperation::OVER);
1825         rxCanvas->drawBitmap(xBitmap, rViewState, aRenderState);
1826     }
1827 }
1828 
1829 
1830 
1831 
1832 PresenterBitmapDescriptor::Mode Button::GetMode (void) const
1833 {
1834     if ( ! IsEnabled())
1835         return PresenterBitmapDescriptor::Disabled;
1836     else if (mbIsPressed)
1837         return PresenterBitmapDescriptor::ButtonDown;
1838     else if (mbIsOver)
1839         return PresenterBitmapDescriptor::MouseOver;
1840     else
1841         return PresenterBitmapDescriptor::Normal;
1842 }
1843 
1844 
1845 
1846 
1847 //----- lang::XEventListener --------------------------------------------------
1848 
1849 void SAL_CALL Button::disposing (const css::lang::EventObject& rEvent)
1850     throw(css::uno::RuntimeException)
1851 {
1852     (void)rEvent;
1853     mbIsListenerRegistered = false;
1854     Element::disposing(rEvent);
1855 }
1856 
1857 } // end of anonymous namespace
1858 
1859 
1860 
1861 
1862 //===== PresenterToolBar::Label ===============================================
1863 
1864 namespace {
1865 
1866 Label::Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
1867     : Element(rpToolBar)
1868 {
1869 }
1870 
1871 
1872 
1873 
1874 awt::Size Label::CreateBoundingSize (
1875     const Reference<rendering::XCanvas>& rxCanvas)
1876 {
1877     if (mpMode.get() == NULL)
1878         return awt::Size(0,0);
1879 
1880     geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
1881     return awt::Size(
1882         sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.X2 - aTextBBox.X1),
1883         sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
1884 }
1885 
1886 
1887 
1888 
1889 
1890 void Label::SetText (const OUString& rsText)
1891 {
1892     OSL_ASSERT(mpToolBar.get() != NULL);
1893     if (mpMode.get() == NULL)
1894         return;
1895 
1896     const bool bRequestLayout (mpMode->maText.GetText().getLength() != rsText.getLength());
1897 
1898     mpMode->maText.SetText(rsText);
1899     // Just use the character count for determing whether a layout is
1900     // necessary.  This is an optimization to avoid layouts every time a new
1901     // time value is set on some labels.
1902     if (bRequestLayout)
1903         mpToolBar->RequestLayout();
1904     else
1905         Invalidate(false);
1906 }
1907 
1908 
1909 
1910 
1911 void Label::Paint (
1912     const Reference<rendering::XCanvas>& rxCanvas,
1913     const rendering::ViewState& rViewState)
1914 {
1915     OSL_ASSERT(rxCanvas.is());
1916     if (mpMode.get() == NULL)
1917         return;
1918 
1919     mpMode->maText.Paint(rxCanvas, rViewState, GetBoundingBox(), awt::Point(0,0));
1920 }
1921 
1922 
1923 
1924 
1925 bool Label::SetState (const bool bIsOver, const bool bIsPressed)
1926 {
1927     // For labels there is no mouse over effect.
1928     (void)bIsOver;
1929     (void)bIsPressed;
1930     return Element::SetState(false, false);
1931 }
1932 
1933 } // end of anonymous namespace
1934 
1935 
1936 
1937 
1938 //===== Text ==================================================================
1939 
1940 namespace {
1941 
1942 Text::Text (void)
1943     : msText(),
1944       mpFont()
1945 {
1946 }
1947 
1948 
1949 
1950 
1951 Text::Text (const Text& rText)
1952     : msText(rText.msText),
1953       mpFont(rText.mpFont)
1954 {
1955 }
1956 
1957 
1958 
1959 
1960 Text::Text (
1961     const OUString& rsText,
1962     const PresenterTheme::SharedFontDescriptor& rpFont)
1963     : msText(rsText),
1964       mpFont(rpFont)
1965 {
1966 }
1967 
1968 
1969 
1970 
1971 void Text::SetText (const OUString& rsText)
1972 {
1973     msText = rsText;
1974 }
1975 
1976 
1977 
1978 
1979 OUString Text::GetText (void) const
1980 {
1981     return msText;
1982 }
1983 
1984 
1985 
1986 
1987 PresenterTheme::SharedFontDescriptor Text::GetFont (void) const
1988 {
1989     return mpFont;
1990 }
1991 
1992 
1993 
1994 
1995 void Text::Paint (
1996     const Reference<rendering::XCanvas>& rxCanvas,
1997     const rendering::ViewState& rViewState,
1998     const awt::Rectangle& rBoundingBox,
1999     const awt::Point& rOffset)
2000 {
2001     (void)rOffset;
2002     OSL_ASSERT(rxCanvas.is());
2003 
2004     if (msText.getLength() <= 0)
2005         return;
2006     if (mpFont.get() == NULL)
2007         return;
2008 
2009     if ( ! mpFont->mxFont.is())
2010         mpFont->PrepareFont(rxCanvas);
2011     if ( ! mpFont->mxFont.is())
2012         return;
2013 
2014     rendering::StringContext aContext (msText, 0, msText.getLength());
2015 
2016     Reference<rendering::XTextLayout> xLayout (
2017         mpFont->mxFont->createTextLayout(
2018             aContext,
2019             rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
2020             0));
2021 
2022     geometry::RealRectangle2D aBox (xLayout->queryTextBounds());
2023     const double nTextWidth = aBox.X2 - aBox.X1;
2024     const double nY = rBoundingBox.Y + rBoundingBox.Height - aBox.Y2;
2025     const double nX = rBoundingBox.X + (rBoundingBox.Width - nTextWidth)/2;
2026 
2027     rendering::RenderState aRenderState(
2028         geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
2029         NULL,
2030         Sequence<double>(4),
2031         rendering::CompositeOperation::SOURCE);
2032     PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);
2033 
2034     rxCanvas->drawText(
2035         aContext,
2036         mpFont->mxFont,
2037         rViewState,
2038         aRenderState,
2039         rendering::TextDirection::WEAK_LEFT_TO_RIGHT);
2040 }
2041 
2042 
2043 
2044 
2045 geometry::RealRectangle2D Text::GetBoundingBox (const Reference<rendering::XCanvas>& rxCanvas)
2046 {
2047     if (mpFont.get() != NULL && msText.getLength() > 0)
2048     {
2049         if ( ! mpFont->mxFont.is())
2050             mpFont->PrepareFont(rxCanvas);
2051         if (mpFont->mxFont.is())
2052         {
2053             rendering::StringContext aContext (msText, 0, msText.getLength());
2054             Reference<rendering::XTextLayout> xLayout (
2055                 mpFont->mxFont->createTextLayout(
2056                     aContext,
2057                     rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
2058                     0));
2059             return xLayout->queryTextBounds();
2060         }
2061     }
2062     return geometry::RealRectangle2D(0,0,0,0);
2063 }
2064 
2065 
2066 
2067 
2068 //===== ProgressLabel =========================================================
2069 
2070 ProgressLabel::ProgressLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
2071     : Label(rpToolBar)
2072 {
2073     SetText(A2S("-/-"));
2074 }
2075 
2076 
2077 
2078 
2079 void ProgressLabel::CurrentSlideHasChanged (void)
2080 {
2081     Label::CurrentSlideHasChanged();
2082     OSL_ASSERT(mpToolBar.is());
2083     try
2084     {
2085         const sal_Int32 nCurrentSlideIndex (mpToolBar->GetCurrentSlideIndex() + 1);
2086         const sal_Int32 nSlideCount (mpToolBar->GetSlideCount());
2087         if (nCurrentSlideIndex >= 0 && nSlideCount > 0)
2088             SetText(
2089                 OUString::valueOf(nCurrentSlideIndex)
2090                     + OUString::createFromAscii(" / ")
2091                         + OUString::valueOf(nSlideCount));
2092         else
2093             SetText(A2S(""));
2094         Invalidate();
2095     }
2096     catch (RuntimeException&)
2097     {
2098     }
2099 }
2100 
2101 
2102 
2103 
2104 //===== TimeFormatter =========================================================
2105 
2106 TimeFormatter::TimeFormatter (void)
2107     : mbIs24HourFormat(true),
2108       mbIsAmPmFormat(false),
2109       mbIsShowSeconds(true)
2110 {
2111 }
2112 
2113 
2114 
2115 
2116 OUString TimeFormatter::FormatTime (const oslDateTime& rTime)
2117 {
2118     ::rtl::OUStringBuffer sText;
2119 
2120     const sal_Int32 nHours (sal::static_int_cast<sal_Int32>(rTime.Hours));
2121     const sal_Int32 nMinutes (sal::static_int_cast<sal_Int32>(rTime.Minutes));
2122     const sal_Int32 nSeconds(sal::static_int_cast<sal_Int32>(rTime.Seconds));
2123 
2124     // Hours
2125     if (mbIs24HourFormat)
2126         sText.append(OUString::valueOf(nHours));
2127     else
2128         sText.append(OUString::valueOf(
2129             sal::static_int_cast<sal_Int32>(nHours>12 ? nHours-12 : nHours)));
2130 
2131     sText.append(A2S(":"));
2132 
2133     // Minutes
2134     const OUString sMinutes (OUString::valueOf(nMinutes));
2135     if (sMinutes.getLength() == 1)
2136         sText.append(A2S("0"));
2137     sText.append(sMinutes);
2138 
2139     // Seconds
2140     if (mbIsShowSeconds)
2141     {
2142         sText.append(A2S(":"));
2143         const OUString sSeconds (OUString::valueOf(nSeconds));
2144         if (sSeconds.getLength() == 1)
2145             sText.append(A2S("0"));
2146         sText.append(sSeconds);
2147     }
2148 
2149     if (mbIsAmPmFormat)
2150     {
2151         if (rTime.Hours < 12)
2152             sText.append(A2S("am"));
2153         else
2154             sText.append(A2S("pm"));
2155     }
2156     return sText.makeStringAndClear();
2157 }
2158 
2159 
2160 
2161 
2162 //===== TimeLabel =============================================================
2163 
2164 TimeLabel::TimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
2165     : Label(rpToolBar),
2166       mpListener()
2167 {
2168 }
2169 
2170 
2171 
2172 
2173 void SAL_CALL TimeLabel::disposing (void)
2174 {
2175     PresenterClockTimer::Instance(mpToolBar->GetComponentContext())->RemoveListener(mpListener);
2176     mpListener.reset();
2177 }
2178 
2179 
2180 
2181 
2182 void TimeLabel::ConnectToTimer (void)
2183 {
2184     mpListener.reset(new Listener(this));
2185     PresenterClockTimer::Instance(mpToolBar->GetComponentContext())->AddListener(mpListener);
2186 }
2187 
2188 
2189 
2190 
2191 //===== CurrentTimeLabel ======================================================
2192 
2193 ::rtl::Reference<Element> CurrentTimeLabel::Create (
2194     const ::rtl::Reference<PresenterToolBar>& rpToolBar)
2195 {
2196     ::rtl::Reference<TimeLabel> pElement(new CurrentTimeLabel(rpToolBar));
2197     pElement->ConnectToTimer();
2198     return ::rtl::Reference<Element>(pElement.get());
2199 }
2200 
2201 
2202 
2203 
2204 CurrentTimeLabel::~CurrentTimeLabel (void)
2205 {
2206 }
2207 
2208 
2209 
2210 
2211 CurrentTimeLabel::CurrentTimeLabel (
2212     const ::rtl::Reference<PresenterToolBar>& rpToolBar)
2213     : TimeLabel(rpToolBar),
2214       maTimeFormatter()
2215 {
2216 }
2217 
2218 
2219 
2220 
2221 void CurrentTimeLabel::TimeHasChanged (const oslDateTime& rCurrentTime)
2222 {
2223     SetText(maTimeFormatter.FormatTime(rCurrentTime));
2224     Invalidate(false);
2225 }
2226 
2227 
2228 
2229 
2230 void CurrentTimeLabel::SetModes (
2231     const SharedElementMode& rpNormalMode,
2232     const SharedElementMode& rpMouseOverMode,
2233     const SharedElementMode& rpSelectedMode,
2234     const SharedElementMode& rpDisabledMode)
2235 {
2236     TimeLabel::SetModes(rpNormalMode, rpMouseOverMode, rpSelectedMode, rpDisabledMode);
2237     SetText(maTimeFormatter.FormatTime(PresenterClockTimer::GetCurrentTime()));
2238 }
2239 
2240 
2241 
2242 
2243 //===== PresentationTimeLabel =================================================
2244 
2245 ::rtl::Reference<Element> PresentationTimeLabel::Create (
2246     const ::rtl::Reference<PresenterToolBar>& rpToolBar)
2247 {
2248     ::rtl::Reference<TimeLabel> pElement(new PresentationTimeLabel(rpToolBar));
2249     pElement->ConnectToTimer();
2250     return ::rtl::Reference<Element>(pElement.get());
2251 }
2252 
2253 
2254 
2255 
2256 PresentationTimeLabel::~PresentationTimeLabel (void)
2257 {
2258 }
2259 
2260 
2261 
2262 
2263 PresentationTimeLabel::PresentationTimeLabel (
2264     const ::rtl::Reference<PresenterToolBar>& rpToolBar)
2265     : TimeLabel(rpToolBar),
2266       maTimeFormatter(),
2267       maStartTimeValue()
2268 {
2269     maStartTimeValue.Seconds = 0;
2270     maStartTimeValue.Nanosec = 0;
2271 }
2272 
2273 
2274 
2275 
2276 void PresentationTimeLabel::TimeHasChanged (const oslDateTime& rCurrentTime)
2277 {
2278     TimeValue aCurrentTimeValue;
2279     if (osl_getTimeValueFromDateTime(const_cast<oslDateTime*>(&rCurrentTime), &aCurrentTimeValue))
2280     {
2281         if (maStartTimeValue.Seconds==0 && maStartTimeValue.Nanosec==0)
2282         {
2283             // This method is called for the first time.  Initialize the
2284             // start time.  The start time is rounded to nearest second to
2285             // keep the time updates synchronized with the current time label.
2286             maStartTimeValue = aCurrentTimeValue;
2287             if (maStartTimeValue.Nanosec >= 500000000)
2288                 maStartTimeValue.Seconds += 1;
2289             maStartTimeValue.Nanosec = 0;
2290         }
2291 
2292         TimeValue aElapsedTimeValue;
2293         aElapsedTimeValue.Seconds = aCurrentTimeValue.Seconds - maStartTimeValue.Seconds;
2294         aElapsedTimeValue.Nanosec = aCurrentTimeValue.Nanosec - maStartTimeValue.Nanosec;
2295 
2296         oslDateTime aElapsedDateTime;
2297         if (osl_getDateTimeFromTimeValue(&aElapsedTimeValue, &aElapsedDateTime))
2298         {
2299             SetText(maTimeFormatter.FormatTime(aElapsedDateTime));
2300             Invalidate(false);
2301         }
2302     }
2303 }
2304 
2305 
2306 
2307 void PresentationTimeLabel::SetModes (
2308     const SharedElementMode& rpNormalMode,
2309     const SharedElementMode& rpMouseOverMode,
2310     const SharedElementMode& rpSelectedMode,
2311     const SharedElementMode& rpDisabledMode)
2312 {
2313     TimeLabel::SetModes(rpNormalMode, rpMouseOverMode, rpSelectedMode, rpDisabledMode);
2314 
2315     oslDateTime aStartDateTime;
2316     if (osl_getDateTimeFromTimeValue(&maStartTimeValue, &aStartDateTime))
2317     {
2318         SetText(maTimeFormatter.FormatTime(aStartDateTime));
2319     }
2320 }
2321 
2322 
2323 
2324 
2325 //===== VerticalSeparator =====================================================
2326 
2327 VerticalSeparator::VerticalSeparator (
2328     const ::rtl::Reference<PresenterToolBar>& rpToolBar)
2329     : Element(rpToolBar)
2330 {
2331 }
2332 
2333 
2334 
2335 
2336 void VerticalSeparator::Paint (
2337     const Reference<rendering::XCanvas>& rxCanvas,
2338     const rendering::ViewState& rViewState)
2339 {
2340     OSL_ASSERT(rxCanvas.is());
2341 
2342     awt::Rectangle aBBox (GetBoundingBox());
2343 
2344     rendering::RenderState aRenderState(
2345         geometry::AffineMatrix2D(1,0,0, 0,1,0),
2346         NULL,
2347         Sequence<double>(4),
2348         rendering::CompositeOperation::OVER);
2349     if (mpMode.get() != NULL)
2350     {
2351         PresenterTheme::SharedFontDescriptor pFont (mpMode->maText.GetFont());
2352         if (pFont.get() != NULL)
2353             PresenterCanvasHelper::SetDeviceColor(aRenderState, pFont->mnColor);
2354     }
2355 
2356     if (aBBox.Height >= gnMinimalSeparatorSize + 2*gnSeparatorInset)
2357     {
2358         aBBox.Height -= 2*gnSeparatorInset;
2359         aBBox.Y += gnSeparatorInset;
2360     }
2361     rxCanvas->fillPolyPolygon(
2362         PresenterGeometryHelper::CreatePolygon(aBBox, rxCanvas->getDevice()),
2363         rViewState,
2364         aRenderState);
2365 }
2366 
2367 
2368 
2369 
2370 awt::Size VerticalSeparator::CreateBoundingSize (
2371     const Reference<rendering::XCanvas>& rxCanvas)
2372 {
2373     (void)rxCanvas;
2374     return awt::Size(1,20);
2375 }
2376 
2377 
2378 
2379 
2380 bool VerticalSeparator::IsFilling (void) const
2381 {
2382     return true;
2383 }
2384 
2385 
2386 
2387 
2388 //===== HorizontalSeparator ===================================================
2389 
2390 HorizontalSeparator::HorizontalSeparator (
2391     const ::rtl::Reference<PresenterToolBar>& rpToolBar)
2392     : Element(rpToolBar)
2393 {
2394 }
2395 
2396 
2397 
2398 
2399 void HorizontalSeparator::Paint (
2400     const Reference<rendering::XCanvas>& rxCanvas,
2401     const rendering::ViewState& rViewState)
2402 {
2403     OSL_ASSERT(rxCanvas.is());
2404 
2405     awt::Rectangle aBBox (GetBoundingBox());
2406 
2407     rendering::RenderState aRenderState(
2408         geometry::AffineMatrix2D(1,0,0, 0,1,0),
2409         NULL,
2410         Sequence<double>(4),
2411         rendering::CompositeOperation::OVER);
2412     if (mpMode.get() != NULL)
2413     {
2414         PresenterTheme::SharedFontDescriptor pFont (mpMode->maText.GetFont());
2415         if (pFont.get() != NULL)
2416             PresenterCanvasHelper::SetDeviceColor(aRenderState, pFont->mnColor);
2417     }
2418 
2419     if (aBBox.Width >= gnMinimalSeparatorSize+2*gnSeparatorInset)
2420     {
2421         aBBox.Width -= 2*gnSeparatorInset;
2422         aBBox.X += gnSeparatorInset;
2423     }
2424     rxCanvas->fillPolyPolygon(
2425         PresenterGeometryHelper::CreatePolygon(aBBox, rxCanvas->getDevice()),
2426         rViewState,
2427         aRenderState);
2428 }
2429 
2430 
2431 
2432 
2433 awt::Size HorizontalSeparator::CreateBoundingSize (
2434     const Reference<rendering::XCanvas>& rxCanvas)
2435 {
2436     (void)rxCanvas;
2437     return awt::Size(20,1);
2438 }
2439 
2440 
2441 
2442 
2443 bool HorizontalSeparator::IsFilling (void) const
2444 {
2445     return true;
2446 }
2447 
2448 
2449 
2450 
2451 } // end of anonymous namespace
2452 
2453 
2454 } } // end of namespace ::sdext::presenter
2455