1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: PresenterClock.cxx,v $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_sdext.hxx"
35 #include "PresenterClock.hxx"
36 #include "PresenterComponent.hxx"
37 #include "PresenterConfigurationAccess.hxx"
38 #include "PresenterGeometryHelper.hxx"
39 #include <com/sun/star/awt/InvalidateStyle.hpp>
40 #include <com/sun/star/awt/MouseButton.hpp>
41 #include <com/sun/star/awt/Point.hpp>
42 #include <com/sun/star/awt/XWindowPeer.hpp>
43 #include <com/sun/star/container/XNameAccess.hpp>
44 #include <com/sun/star/deployment/XPackageInformationProvider.hpp>
45 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
46 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
47 #include <com/sun/star/rendering/CompositeOperation.hpp>
48 #include <com/sun/star/rendering/PathCapType.hpp>
49 #include <com/sun/star/rendering/TextDirection.hpp>
50 #include <com/sun/star/rendering/XCanvasFont.hpp>
51 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
52 #include <com/sun/star/util/Color.hpp>
53 #include <osl/mutex.hxx>
55 #include <rtl/ref.hxx>
56 #include <vos/timer.hxx>
57 #include <boost/bind.hpp>
60 using namespace ::com::sun::star
;
61 using namespace ::com::sun::star::uno
;
62 using namespace ::com::sun::star::drawing::framework
;
63 using ::rtl::OUString
;
65 namespace sdext
{ namespace presenter
{
68 /** Wrapper around a library timer.
70 class PresenterClock::Timer
: public vos::OTimer
73 explicit Timer (const ::rtl::Reference
<PresenterClock
>& rpClock
);
74 virtual ~Timer (void);
79 virtual void SAL_CALL
onShot (void);
82 ::rtl::Reference
<PresenterClock
> mpClock
;
89 bool GetDateTime (oslDateTime
& rDateTime
);
91 class BitmapDescriptor
94 Reference
<rendering::XBitmap
> mxBitmap
;
96 Reference
<rendering::XBitmap
> mxScaledBitmap
;
97 geometry::RealPoint2D maScaledOffset
;
104 class PresenterClock::Painter
108 const Reference
<rendering::XCanvas
>& rxCanvas
,
109 const rendering::ViewState
& rViewState
,
110 const rendering::RenderState
& rRenderState
,
111 const util::Color
& rBackgroundColor
,
112 const sal_Int32 nHour
,
113 const sal_Int32 nMinute
,
114 const sal_Int32 nSecond
,
115 const bool bShowSeconds
) = 0;
116 virtual void Resize (const awt::Size
& rSize
) = 0;
123 class AnalogDefaultPainter
: public PresenterClock::Painter
126 AnalogDefaultPainter (void);
127 virtual ~AnalogDefaultPainter (void) {}
129 const Reference
<rendering::XCanvas
>& rxCanvas
,
130 const rendering::ViewState
& rViewState
,
131 const rendering::RenderState
& rRenderState
,
132 const util::Color
& rBackgroundColor
,
133 const sal_Int32 nHour
,
134 const sal_Int32 nMinute
,
135 const sal_Int32 nSecond
,
136 const bool bShowSeconds
);
137 virtual void Resize (const awt::Size
& rSize
);
139 geometry::RealPoint2D maCenter
;
140 double mnOuterRadius
;
142 Reference
<rendering::XBitmap
> mxBitmap
;
144 /** Relative length (with respect to radius) from center to the tip of
147 static const double mnRelativeHourHandLength
;
148 /** Relative length (with respect to radius) from center to the
149 oposing end of the tip of the hand.
151 static const double mnRelativeHourHandLength2
;
152 static const double mnRelativeHourHandWidth
;
153 static const double mnRelativeMinuteHandLength
;
154 static const double mnRelativeMinuteHandLength2
;
155 static const double mnRelativeMinuteHandWidth
;
156 static const double mnRelativeSecondHandLength
;
157 static const double mnRelativeSecondHandLength2
;
158 static const double mnRelativeSecondHandWidth
;
160 void PaintAngledLine (
162 const double nInnerRadius
,
163 const double nOuterRadius
,
164 const double nStrokeWidth
,
165 const Reference
<rendering::XCanvas
>& rxCanvas
,
166 const rendering::ViewState
& rViewState
,
167 const rendering::RenderState
& rRenderState
);
171 class AnalogBitmapPainter
: public PresenterClock::Painter
175 const Reference
<XComponentContext
>& rxContext
,
176 const OUString
& rsThemeName
);
177 virtual ~AnalogBitmapPainter (void) {}
179 const Reference
<rendering::XCanvas
>& rxCanvas
,
180 const rendering::ViewState
& rViewState
,
181 const rendering::RenderState
& rRenderState
,
182 const util::Color
& rBackgroundColor
,
183 const sal_Int32 nHour
,
184 const sal_Int32 nMinute
,
185 const sal_Int32 nSecond
,
186 const bool bShowSeconds
);
187 virtual void Resize (const awt::Size
& rSize
);
189 css::uno::Reference
<css::uno::XComponentContext
> mxComponentContext
;
190 const OUString msThemeName
;
192 bool mbThemeLoadingFailed
;
193 geometry::RealPoint2D maCenter
;
194 double mnOuterRadius
;
195 BitmapDescriptor maFace
;
196 BitmapDescriptor maMinuteHand
;
197 BitmapDescriptor maHourHand
;
199 void PrepareBitmaps (const Reference
<rendering::XCanvas
>& rxCanvas
);
200 Reference
<container::XNameAccess
> GetTheme (
201 PresenterConfigurationAccess
& rConfiguration
);
202 bool ThemeNameComparator (
203 const ::rtl::OUString
& rsKey
,
204 const Reference
<container::XNameAccess
>& rxCandidate
,
205 const ::rtl::OUString
& rsCurrentThemeName
);
207 PresenterConfigurationAccess
& rConfiguration
,
208 const Reference
<container::XNameAccess
>& rxNameAccess
,
209 const Reference
<rendering::XCanvas
>& rxCanvas
);
211 const OUString
& rsKey
,
212 const ::std::vector
<Any
>& rValues
,
213 const OUString
& rsBitmapPath
,
214 const Reference
<container::XNameAccess
>& rxBitmapLoader
);
215 void ScaleBitmaps (void);
219 class DigitalDefaultPainter
: public PresenterClock::Painter
222 DigitalDefaultPainter (
223 const ::rtl::Reference
<PresenterController
>& rpPresenterController
,
224 const Reference
<XResourceId
>& rxViewId
);
225 virtual ~DigitalDefaultPainter (void);
228 const Reference
<rendering::XCanvas
>& rxCanvas
,
229 const rendering::ViewState
& rViewState
,
230 const rendering::RenderState
& rRenderState
,
231 const util::Color
& rBackgroundColor
,
232 const sal_Int32 nHour
,
233 const sal_Int32 nMinute
,
234 const sal_Int32 nSecond
,
235 const bool bShowSeconds
);
236 virtual void Resize (const awt::Size
& rSize
);
239 ::rtl::Reference
<PresenterController
> mpPresenterController
;
240 bool mbIs24HourFormat
;
241 bool mbIsAdaptFontSize
;
242 Reference
<rendering::XCanvasFont
> mxFont
;
243 awt::Size maWindowSize
;
247 const Reference
<rendering::XCanvas
>& rxCanvas
,
248 const bool bIsShowSeconds
);
252 } // end of anonymous namespace
257 //===== PresenterClock =================================================================
259 ::rtl::Reference
<PresenterClock
> PresenterClock::Create (
260 const Reference
<XComponentContext
>& rxContext
,
261 const Reference
<XResourceId
>& rxViewId
,
262 const Reference
<frame::XController
>& rxController
,
263 const ::rtl::Reference
<PresenterController
>& rpPresenterController
)
265 ::rtl::Reference
<PresenterClock
> pClock (new PresenterClock(
269 rpPresenterController
));
277 PresenterClock::PresenterClock (
278 const Reference
<XComponentContext
>& rxContext
,
279 const Reference
<XResourceId
>& rxViewId
,
280 const Reference
<frame::XController
>& rxController
,
281 const ::rtl::Reference
<PresenterController
>& rpPresenterController
)
282 : PresenterClockInterfaceBase(m_aMutex
),
283 mxComponentContext(rxContext
),
288 mpPresenterController(rpPresenterController
),
289 mbIsResizePending(true),
299 mbIsShowSeconds(true)
303 maViewState
.AffineTransform
= geometry::AffineMatrix2D(1,0,0, 0,1,0);
304 maRenderState
.AffineTransform
= geometry::AffineMatrix2D(1,0,0, 0,1,0);
305 maRenderState
.DeviceColor
= Sequence
<double>(4);
306 PresenterCanvasHelper::SetDeviceColor(maRenderState
, util::Color(0x00000000));
311 Reference
<XControllerManager
> xCM (rxController
, UNO_QUERY_THROW
);
312 Reference
<XConfigurationController
> xCC (xCM
->getConfigurationController(), UNO_QUERY_THROW
);
313 mxPane
= Reference
<XPane
>(xCC
->getResource(rxViewId
->getAnchor()), UNO_QUERY_THROW
);
315 mxWindow
= mxPane
->getWindow();
318 mxWindow
->addPaintListener(this);
319 mxWindow
->addWindowListener(this);
320 mxWindow
->addMouseListener(this);
321 Reference
<awt::XWindowPeer
> xPeer (mxWindow
, UNO_QUERY
);
323 xPeer
->setBackground(util::Color(0xff000000));
324 mxWindow
->setVisible(sal_True
);
329 catch (RuntimeException
&)
339 PresenterClock::~PresenterClock (void)
346 void PresenterClock::LateInit (void)
348 mpTimer
= new Timer(this);
354 void SAL_CALL
PresenterClock::disposing (void)
356 // osl::MutexGuard aGuard (m_aMutex);
363 mxWindow
->removePaintListener(this);
364 mxWindow
->removeWindowListener(this);
365 mxWindow
->removeMouseListener(this);
375 void PresenterClock::UpdateTime (void)
377 // Get current time and check whether it is different from last time.
378 oslDateTime aDateTime
;
379 if ( ! GetDateTime(aDateTime
))
381 if (aDateTime
.Hours
!= mnHour
382 || aDateTime
.Minutes
!= mnMinute
383 || aDateTime
.Seconds
!= mnSecond
)
385 mnHour
= aDateTime
.Hours
% 24;
386 mnMinute
= aDateTime
.Minutes
% 60;
387 mnSecond
= aDateTime
.Seconds
% 60;
389 Reference
<awt::XWindowPeer
> xPeer (mxWindow
, UNO_QUERY
);
391 xPeer
->invalidate(awt::InvalidateStyle::NOERASE
|
392 awt::InvalidateStyle::UPDATE
);
399 //----- lang::XEventListener -------------------------------------------------
401 void SAL_CALL
PresenterClock::disposing (const lang::EventObject
& rEventObject
)
402 throw (RuntimeException
)
404 // ::osl::MutexGuard aSolarGuard (::osl::Mutex::getGlobalMutex());
405 // osl::MutexGuard aGuard (m_aMutex);
407 if (rEventObject
.Source
== mxWindow
)
418 //----- XPaintListener --------------------------------------------------------
420 void SAL_CALL
PresenterClock::windowPaint (const awt::PaintEvent
& rEvent
)
421 throw (RuntimeException
)
425 ::osl::MutexGuard
aSolarGuard (::osl::Mutex::getGlobalMutex());
426 Paint(rEvent
.UpdateRect
);
432 //----- XWindowListener -------------------------------------------------------
434 void SAL_CALL
PresenterClock::windowResized (const awt::WindowEvent
& rEvent
)
435 throw (RuntimeException
)
438 mbIsResizePending
= true;
444 void SAL_CALL
PresenterClock::windowMoved (const awt::WindowEvent
& rEvent
)
445 throw (RuntimeException
)
448 mbIsResizePending
= true;
454 void SAL_CALL
PresenterClock::windowShown (const lang::EventObject
& rEvent
)
455 throw (RuntimeException
)
458 mbIsResizePending
= true;
464 void SAL_CALL
PresenterClock::windowHidden (const lang::EventObject
& rEvent
)
465 throw (RuntimeException
)
473 //----- XMouseListener --------------------------------------------------------
475 void SAL_CALL
PresenterClock::mousePressed (const css::awt::MouseEvent
& rEvent
)
476 throw (css::uno::RuntimeException
)
479 if (rEvent
.Buttons
== awt::MouseButton::LEFT
)
488 void SAL_CALL
PresenterClock::mouseReleased (const css::awt::MouseEvent
& rEvent
)
489 throw (css::uno::RuntimeException
)
497 void SAL_CALL
PresenterClock::mouseEntered (const css::awt::MouseEvent
& rEvent
)
498 throw (css::uno::RuntimeException
)
506 void SAL_CALL
PresenterClock::mouseExited (const css::awt::MouseEvent
& rEvent
)
507 throw (css::uno::RuntimeException
)
515 //----- XResourceId -----------------------------------------------------------
517 Reference
<XResourceId
> SAL_CALL
PresenterClock::getResourceId (void)
518 throw (RuntimeException
)
526 sal_Bool SAL_CALL
PresenterClock::isAnchorOnly (void)
527 throw (RuntimeException
)
535 //-----------------------------------------------------------------------------
537 void PresenterClock::Resize (void)
540 mxCanvas
= Reference
<rendering::XCanvas
>(mxPane
->getCanvas(), UNO_QUERY
);
541 if (mxWindow
.is() && mxCanvas
.is())
543 const awt::Rectangle
aWindowBox (mxWindow
->getPosSize());
544 const awt::Size
aWindowSize(aWindowBox
.Width
,aWindowBox
.Height
);
545 if (mpClockPainter
.get() != NULL
)
546 mpClockPainter
->Resize(aWindowSize
);
547 if (mpClockPainter2
.get() != NULL
)
548 mpClockPainter2
->Resize(aWindowSize
);
549 mbIsResizePending
= false;
556 void PresenterClock::Paint (const awt::Rectangle
& rUpdateBox
)
558 if ( ! mxCanvas
.is() && mxPane
.is())
559 mxCanvas
= Reference
<rendering::XCanvas
>(mxPane
->getCanvas(), UNO_QUERY
);
562 || ! mxCanvas
->getDevice().is())
569 if (mbIsResizePending
)
572 Reference
<rendering::XPolyPolygon2D
> xUpdatePolygon (
573 PresenterGeometryHelper::CreatePolygon(rUpdateBox
, mxCanvas
->getDevice()));
575 Clear(xUpdatePolygon
);
577 if (mpClockPainter
.get() != NULL
)
578 mpClockPainter
->Paint(mxCanvas
,
581 mpPresenterController
->GetViewBackgroundColor(mxViewId
->getResourceURL()),
587 if (mpClockPainter2
.get() != NULL
)
588 mpClockPainter2
->Paint(
592 mpPresenterController
->GetViewBackgroundColor(mxViewId
->getResourceURL()),
598 catch (RuntimeException
& e
)
603 // Make the back buffer visible.
604 Reference
<rendering::XSpriteCanvas
> xSpriteCanvas (mxCanvas
, UNO_QUERY
);
605 if (xSpriteCanvas
.is())
606 xSpriteCanvas
->updateScreen(sal_False
);
612 void PresenterClock::Clear (const Reference
<rendering::XPolyPolygon2D
>& rxUpdatePolygon
)
614 rendering::RenderState aRenderState
= maRenderState
;
615 const sal_Int32
nColor (
616 mpPresenterController
->GetViewBackgroundColor(mxViewId
->getResourceURL()));
617 aRenderState
.DeviceColor
[0] = ((nColor
&0x00ff0000) >> 16) / 255.0;
618 aRenderState
.DeviceColor
[1] = ((nColor
&0x0000ff00) >> 8) / 255.0;
619 aRenderState
.DeviceColor
[2] = ((nColor
&0x000000ff) >> 0) / 255.0;
621 if (rxUpdatePolygon
.is())
622 mxCanvas
->fillPolyPolygon(
631 void PresenterClock::SetMode (const sal_Int32 nMode
)
638 mpClockPainter
.reset(
639 new AnalogBitmapPainter(
641 OUString::createFromAscii("ClockTheme")));
642 mpClockPainter2
.reset();
646 mpClockPainter
.reset();
647 mpClockPainter2
.reset(new AnalogDefaultPainter());
651 mpClockPainter
.reset();
652 mpClockPainter2
.reset(new DigitalDefaultPainter(mpPresenterController
, mxViewId
));
656 mpClockPainter
.reset(
657 new AnalogBitmapPainter(
659 OUString::createFromAscii("ClockTheme")));
660 mpClockPainter2
.reset(new AnalogDefaultPainter());
669 void PresenterClock::ThrowIfDisposed (void)
670 throw (::com::sun::star::lang::DisposedException
)
672 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
674 throw lang::DisposedException (
675 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
676 "PresenterClock object has already been disposed")),
677 static_cast<uno::XWeak
*>(this));
684 //===== Timer =================================================================
686 PresenterClock::Timer::Timer (const ::rtl::Reference
<PresenterClock
>& rpClock
)
687 : OTimer(vos::TTimeValue(10), vos::TTimeValue(100/*ms*/)),
697 PresenterClock::Timer::~Timer (void)
706 void PresenterClock::Timer::Stop (void)
716 void SAL_CALL
PresenterClock::Timer::onShot (void)
718 if (mpClock
.get() != NULL
)
719 mpClock
->UpdateTime();
726 //=============================================================================
728 bool GetDateTime (oslDateTime
& rDateTime
)
730 TimeValue aSystemTime
;
731 TimeValue aLocalTime
;
732 if (osl_getSystemTime(&aSystemTime
))
733 if (osl_getLocalTimeFromSystemTime(&aSystemTime
, &aLocalTime
))
734 if (osl_getDateTimeFromTimeValue(&aLocalTime
, &rDateTime
))
742 //===== AnalogDefaultPainter ==================================================
744 const double AnalogDefaultPainter::mnRelativeHourHandLength
= 0.65;
745 const double AnalogDefaultPainter::mnRelativeHourHandLength2 (-0.1);
746 const double AnalogDefaultPainter::mnRelativeHourHandWidth (0.055);
747 const double AnalogDefaultPainter::mnRelativeMinuteHandLength (-0.2);
748 const double AnalogDefaultPainter::mnRelativeMinuteHandLength2 (0.85);
749 const double AnalogDefaultPainter::mnRelativeMinuteHandWidth (0.025);
750 const double AnalogDefaultPainter::mnRelativeSecondHandLength (-0.25);
751 const double AnalogDefaultPainter::mnRelativeSecondHandLength2 (0.95);
752 const double AnalogDefaultPainter::mnRelativeSecondHandWidth (0.015);
754 AnalogDefaultPainter::AnalogDefaultPainter (void)
765 void AnalogDefaultPainter::Paint (
766 const Reference
<rendering::XCanvas
>& rxCanvas
,
767 const rendering::ViewState
& rViewState
,
768 const rendering::RenderState
& rRenderState
,
769 const util::Color
& rBackgroundColor
,
770 const sal_Int32 nHour
,
771 const sal_Int32 nMinute
,
772 const sal_Int32 nSecond
,
773 const bool bShowSeconds
)
775 double nInnerRadius (0);
776 double nStrokeWidth (0.1);
777 const double nClockSize (2*mnOuterRadius
);
779 // Some antialiasing is created by painting into a bitmap twice the
780 // screen size and then scaling it down.
781 const sal_Int32
nSuperSampleFactor (2);
782 if ( ! mxBitmap
.is())
784 mxBitmap
= (rxCanvas
->getDevice()->createCompatibleBitmap(
785 geometry::IntegerSize2D(
786 maSize
.Width
*nSuperSampleFactor
,
787 maSize
.Height
*nSuperSampleFactor
)));
789 Reference
<rendering::XCanvas
> xBitmapCanvas (mxBitmap
, UNO_QUERY
);
790 rendering::RenderState
aRenderState(rRenderState
);
791 aRenderState
.AffineTransform
.m00
= nSuperSampleFactor
;
792 aRenderState
.AffineTransform
.m11
= nSuperSampleFactor
;
794 // Clear the background.
795 aRenderState
.DeviceColor
[0] = ((rBackgroundColor
&0x00ff0000) >> 16) / 255.0;
796 aRenderState
.DeviceColor
[1] = ((rBackgroundColor
&0x0000ff00) >> 8) / 255.0;
797 aRenderState
.DeviceColor
[2] = ((rBackgroundColor
&0x000000ff) >> 0) / 255.0;
798 Reference
<rendering::XPolyPolygon2D
> xPolygon (
799 PresenterGeometryHelper::CreatePolygon(
800 awt::Rectangle(0,0,maSize
.Width
,maSize
.Height
),
801 xBitmapCanvas
->getDevice()));
803 xBitmapCanvas
->fillPolyPolygon(xPolygon
, rViewState
, aRenderState
);
805 // Clock face and clock hands are painted in black.
806 aRenderState
.DeviceColor
[0] = 0;
807 aRenderState
.DeviceColor
[1] = 0;
808 aRenderState
.DeviceColor
[2] = 0;
810 // Paint the clock face.
811 for (sal_Int32 nHourMark
=0; nHourMark
<12; ++nHourMark
)
813 if (nHourMark
%3 == 0)
815 nInnerRadius
= 0.7 * mnOuterRadius
;
816 nStrokeWidth
= 0.05 * nClockSize
;
820 nInnerRadius
= 0.8 * mnOuterRadius
;
821 nStrokeWidth
= 0.03 * nClockSize
;
824 const double nAngle (nHourMark
* 2 * M_PI
/ 12);
825 PaintAngledLine(nAngle
, nInnerRadius
, mnOuterRadius
, nStrokeWidth
,
826 xBitmapCanvas
, rViewState
, aRenderState
);
829 // Paint the hour hand.
830 const double nHoursAngle (((nHour
%12)+nMinute
/60.0) * 2 * M_PI
/ 12);
831 PaintAngledLine(nHoursAngle
,
832 mnRelativeHourHandLength2
*mnOuterRadius
,
833 mnRelativeHourHandLength
*mnOuterRadius
,
834 mnRelativeHourHandWidth
*nClockSize
,
835 xBitmapCanvas
, rViewState
, aRenderState
);
837 // Paint the minute hand.
838 const double nMinutesAngle ((nMinute
+nSecond
/60.0) * 2 * M_PI
/ 60);
839 PaintAngledLine(nMinutesAngle
,
840 mnRelativeMinuteHandLength2
*mnOuterRadius
,
841 mnRelativeMinuteHandLength
*mnOuterRadius
,
842 mnRelativeMinuteHandWidth
*nClockSize
,
843 xBitmapCanvas
, rViewState
, aRenderState
);
845 // Optionally paint the second hand.
848 const double nSecondsAngle (nSecond
* 2 * M_PI
/ 60);
849 PaintAngledLine(nSecondsAngle
,
850 mnRelativeSecondHandLength2
*mnOuterRadius
,
851 mnRelativeSecondHandLength
*mnOuterRadius
,
852 mnRelativeSecondHandWidth
*nClockSize
,
853 xBitmapCanvas
, rViewState
, aRenderState
);
856 aRenderState
.AffineTransform
.m00
= 1.0 / nSuperSampleFactor
;
857 aRenderState
.AffineTransform
.m11
= 1.0 / nSuperSampleFactor
;
858 rxCanvas
->drawBitmap(mxBitmap
,rViewState
,aRenderState
);
864 void AnalogDefaultPainter::PaintAngledLine (
866 const double nInnerRadius
,
867 const double nOuterRadius
,
868 const double nStrokeWidth
,
869 const Reference
<rendering::XCanvas
>& rxCanvas
,
870 const rendering::ViewState
& rViewState
,
871 const rendering::RenderState
& rRenderState
)
873 if ( ! rxCanvas
.is())
876 rendering::StrokeAttributes aStrokeAttributes
;
877 aStrokeAttributes
.StrokeWidth
= nStrokeWidth
;
878 aStrokeAttributes
.StartCapType
= rendering::PathCapType::SQUARE
;
879 aStrokeAttributes
.EndCapType
= rendering::PathCapType::SQUARE
;
880 aStrokeAttributes
.StartCapType
= rendering::PathCapType::BUTT
;
881 aStrokeAttributes
.EndCapType
= rendering::PathCapType::BUTT
;
882 const double nCos (cos(nAngle
- M_PI
/2));
883 const double nSin (sin(nAngle
- M_PI
/2));
885 Sequence
<Sequence
<geometry::RealPoint2D
> > aPoints(1);
886 aPoints
[0] = Sequence
<geometry::RealPoint2D
>(2);
887 aPoints
[0][0] = geometry::RealPoint2D(
888 maCenter
.X
+ nInnerRadius
*nCos
+ 0.5,
889 maCenter
.Y
+ nInnerRadius
*nSin
+ 0.5);
890 aPoints
[0][1] = geometry::RealPoint2D(
891 maCenter
.X
+ nOuterRadius
*nCos
+ 0.5,
892 maCenter
.Y
+ nOuterRadius
*nSin
+ 0.5);
894 Reference
<rendering::XPolyPolygon2D
> xLine (
895 rxCanvas
->getDevice()->createCompatibleLinePolyPolygon(aPoints
),
899 rxCanvas
->strokePolyPolygon(
909 void AnalogDefaultPainter::Resize (const awt::Size
& rWindowSize
)
911 maSize
= rWindowSize
;
912 maCenter
= geometry::RealPoint2D(rWindowSize
.Width
/2.0, rWindowSize
.Height
/2.0);
913 mnOuterRadius
= ::std::min(rWindowSize
.Width
, rWindowSize
.Height
) / 2.0 - 2;
920 //===== AnalogBitmapPainter ===================================================
922 AnalogBitmapPainter::AnalogBitmapPainter (
923 const Reference
<XComponentContext
>& rxContext
,
924 const OUString
& rsThemeName
)
925 : mxComponentContext(rxContext
),
926 msThemeName(rsThemeName
),
927 mbThemeLoaded(false),
928 mbThemeLoadingFailed(false),
940 void AnalogBitmapPainter::Paint (
941 const Reference
<rendering::XCanvas
>& rxCanvas
,
942 const rendering::ViewState
& rViewState
,
943 const rendering::RenderState
& rRenderState
,
944 const util::Color
& rBackgroundColor
,
945 const sal_Int32 nHour
,
946 const sal_Int32 nMinute
,
947 const sal_Int32 nSecond
,
948 const bool bShowSeconds
)
950 (void)rBackgroundColor
;
954 if ( ! rxCanvas
.is())
957 rendering::RenderState aRenderState
= rRenderState
;
961 PrepareBitmaps(rxCanvas
);
963 if (maFace
.mxScaledBitmap
.is())
965 aRenderState
.AffineTransform
= geometry::AffineMatrix2D(
966 1,0, maCenter
.X
- maFace
.maScaledOffset
.X
,
967 0,1, maCenter
.Y
- maFace
.maScaledOffset
.Y
);
968 rxCanvas
->drawBitmap(maFace
.mxScaledBitmap
, rViewState
, aRenderState
);
971 if (maMinuteHand
.mxScaledBitmap
.is())
973 const double nMinuteAngle ((nMinute
+nSecond
/60.0) * 2.0 * M_PI
/ 60.0);
974 const double nCos (cos(nMinuteAngle
- M_PI
/2));
975 const double nSin (sin(nMinuteAngle
- M_PI
/2));
976 aRenderState
.AffineTransform
= geometry::AffineMatrix2D(
979 -maMinuteHand
.maScaledOffset
.X
*nCos
980 + maMinuteHand
.maScaledOffset
.Y
*nSin
+maCenter
.X
,
983 -maMinuteHand
.maScaledOffset
.X
*nSin
984 - maMinuteHand
.maScaledOffset
.Y
*nCos
+maCenter
.Y
);
985 rxCanvas
->drawBitmap(maMinuteHand
.mxScaledBitmap
, rViewState
, aRenderState
);
988 if (maHourHand
.mxScaledBitmap
.is())
990 const double nHoursAngle ((nHour
%12+nMinute
/60.0) * 2.0 * M_PI
/ 12.0);
991 const double nCos (cos(nHoursAngle
- M_PI
/2));
992 const double nSin (sin(nHoursAngle
- M_PI
/2));
993 aRenderState
.AffineTransform
= geometry::AffineMatrix2D(
996 -maHourHand
.maScaledOffset
.X
*nCos
+maHourHand
.maScaledOffset
.Y
*nSin
+maCenter
.X
,
999 -maHourHand
.maScaledOffset
.X
*nSin
-maHourHand
.maScaledOffset
.Y
*nCos
+maCenter
.Y
);
1000 rxCanvas
->drawBitmap(maHourHand
.mxScaledBitmap
, rViewState
, aRenderState
);
1003 catch(beans::UnknownPropertyException
&)
1006 catch(RuntimeException
&)
1014 void AnalogBitmapPainter::Resize (const awt::Size
& rWindowSize
)
1016 maCenter
= geometry::RealPoint2D(rWindowSize
.Width
/2.0, rWindowSize
.Height
/2.0);
1017 mnOuterRadius
= ::std::min(rWindowSize
.Width
, rWindowSize
.Height
) / 2.0 - 2;
1018 maFace
.mxScaledBitmap
= NULL
;
1019 maHourHand
.mxScaledBitmap
= NULL
;
1020 maMinuteHand
.mxScaledBitmap
= NULL
;
1026 void AnalogBitmapPainter::PrepareBitmaps (const Reference
<rendering::XCanvas
>& rxCanvas
)
1028 if (mbThemeLoadingFailed
)
1030 // Theme loading has failed previously. Do not try a second time.
1033 if ( ! rxCanvas
.is())
1035 // No canvas => bitmaps can neither be loaded, transformed into the
1036 // right format, nor can they be painted.
1040 if ( ! mbThemeLoaded
)
1042 mbThemeLoaded
= true;
1044 // Get access to the clock bitmaps in the configuration.
1045 PresenterConfigurationAccess
aConfiguration (
1047 OUString::createFromAscii("org.openoffice.Office.extension.PresenterScreen"),
1048 PresenterConfigurationAccess::READ_ONLY
);
1050 Reference
<container::XNameAccess
> xTheme (GetTheme(aConfiguration
));
1052 LoadBitmaps(aConfiguration
, xTheme
, rxCanvas
);
1054 mbThemeLoadingFailed
= true;
1063 Reference
<container::XNameAccess
> AnalogBitmapPainter::GetTheme (
1064 PresenterConfigurationAccess
& rConfiguration
)
1066 Reference
<container::XNameAccess
> xTheme
;
1068 // Get root of clock themes.
1069 Reference
<container::XHierarchicalNameAccess
> xClock (
1070 rConfiguration
.GetConfigurationNode(
1071 OUString::createFromAscii("PresenterScreenSettings/AnalogBitmapClock")),
1074 // Determine the name of the theme to use.
1075 OUString
sCurrentThemeName (OUString::createFromAscii("DefaultTheme"));
1076 rConfiguration
.GetConfigurationNode(
1078 OUString::createFromAscii("CurrentTheme")) >>= sCurrentThemeName
;
1080 // Load the clock theme.
1081 Reference
<container::XNameAccess
> xThemes (
1082 rConfiguration
.GetConfigurationNode(
1084 OUString::createFromAscii("Themes")),
1088 xTheme
= Reference
<container::XNameAccess
>(
1089 PresenterConfigurationAccess::Find(
1091 ::boost::bind(&AnalogBitmapPainter::ThemeNameComparator
,
1092 this, _1
, _2
, sCurrentThemeName
)),
1102 bool AnalogBitmapPainter::ThemeNameComparator (
1103 const OUString
& rsKey
,
1104 const Reference
<container::XNameAccess
>& rxCandidate
,
1105 const OUString
& rsCurrentThemeName
)
1108 if (rxCandidate
.is())
1110 OUString sThemeName
;
1111 if (rxCandidate
->getByName(OUString::createFromAscii("ThemeName")) >>= sThemeName
)
1113 return sThemeName
== rsCurrentThemeName
;
1123 void AnalogBitmapPainter::LoadBitmaps (
1124 PresenterConfigurationAccess
& rConfiguration
,
1125 const Reference
<container::XNameAccess
>& rxClockTheme
,
1126 const Reference
<rendering::XCanvas
>& rxCanvas
)
1128 (void)rConfiguration
;
1130 // Get base path to bitmaps.
1131 Reference
<deployment::XPackageInformationProvider
> xInformationProvider (
1132 mxComponentContext
->getValueByName(OUString::createFromAscii(
1133 "/singletons/com.sun.star.deployment.PackageInformationProvider")),
1136 if (xInformationProvider
.is())
1137 sLocation
= xInformationProvider
->getPackageLocation(gsExtensionIdentifier
);
1138 sLocation
+= OUString::createFromAscii("/");
1140 // Create the bitmap loader.
1141 Reference
<lang::XMultiComponentFactory
> xFactory (
1142 mxComponentContext
->getServiceManager(), UNO_QUERY
);
1143 if ( ! xFactory
.is())
1145 Sequence
<Any
> aArguments(1);
1146 aArguments
[0] <<= rxCanvas
;
1147 Reference
<container::XNameAccess
> xBitmapLoader(
1148 xFactory
->createInstanceWithArgumentsAndContext(
1149 OUString::createFromAscii("com.sun.star.drawing.PresenterWorkaroundService"),
1151 mxComponentContext
),
1153 if ( ! xBitmapLoader
.is())
1157 // Iterate over all entries in the bitmap list and load the bitmaps.
1158 Reference
<container::XNameAccess
> xBitmaps (
1159 rxClockTheme
->getByName(OUString::createFromAscii("Bitmaps")),
1161 ::std::vector
<rtl::OUString
> aBitmapProperties (3);
1162 aBitmapProperties
[0] = OUString::createFromAscii("FileName");
1163 aBitmapProperties
[1] = OUString::createFromAscii("XOffset");
1164 aBitmapProperties
[2] = OUString::createFromAscii("YOffset");
1165 PresenterConfigurationAccess::ForAll(
1168 ::boost::bind(&AnalogBitmapPainter::LoadBitmap
,
1179 void AnalogBitmapPainter::LoadBitmap (
1180 const OUString
& rsKey
,
1181 const ::std::vector
<Any
>& rValues
,
1182 const OUString
& rsBitmapPath
,
1183 const Reference
<container::XNameAccess
>& rxBitmapLoader
)
1185 if (rValues
.size() == 3)
1187 BitmapDescriptor
* pDescriptor
= NULL
;
1188 if (rsKey
== OUString::createFromAscii("Face"))
1189 pDescriptor
= &maFace
;
1190 else if (rsKey
== OUString::createFromAscii("HourHand"))
1191 pDescriptor
= &maHourHand
;
1192 else if (rsKey
== OUString::createFromAscii("MinuteHand"))
1193 pDescriptor
= &maMinuteHand
;
1195 if (pDescriptor
== NULL
)
1199 if ( ! (rValues
[0] >>= sFileName
))
1202 rValues
[1] >>= pDescriptor
->maOffset
.X
;
1203 rValues
[2] >>= pDescriptor
->maOffset
.Y
;
1205 pDescriptor
->mxBitmap
= Reference
<rendering::XBitmap
>(
1206 rxBitmapLoader
->getByName(rsBitmapPath
+sFileName
), UNO_QUERY
);
1208 if ( ! pDescriptor
->mxBitmap
.is())
1209 mbThemeLoadingFailed
= true;
1216 void AnalogBitmapPainter::ScaleBitmaps (void)
1218 if (mbThemeLoadingFailed
)
1220 if ( ! maFace
.mxBitmap
.is())
1223 const geometry::IntegerSize2D
aFaceSize (maFace
.mxBitmap
->getSize());
1224 const sal_Int32 nSize
= std::max(aFaceSize
.Width
, aFaceSize
.Height
);
1225 const double nScale
= mnOuterRadius
*2 / nSize
;
1227 BitmapDescriptor
* aDescriptors
[3] = { &maFace
, &maHourHand
, &maMinuteHand
};
1228 for (int nIndex
=0; nIndex
<3; ++nIndex
)
1230 BitmapDescriptor
& rDescriptor (*aDescriptors
[nIndex
]);
1231 if ( ! rDescriptor
.mxScaledBitmap
.is() && rDescriptor
.mxBitmap
.is())
1233 const geometry::IntegerSize2D
aBitmapSize (rDescriptor
.mxBitmap
->getSize());
1234 rDescriptor
.mxScaledBitmap
= rDescriptor
.mxBitmap
->getScaledBitmap(
1235 geometry::RealSize2D(aBitmapSize
.Width
*nScale
, aBitmapSize
.Height
*nScale
),
1237 rDescriptor
.maScaledOffset
= geometry::RealPoint2D(
1238 rDescriptor
.maOffset
.X
* nScale
,
1239 rDescriptor
.maOffset
.Y
* nScale
);
1247 //===== DigitalDefaultPainter =================================================
1249 DigitalDefaultPainter::DigitalDefaultPainter (
1250 const ::rtl::Reference
<PresenterController
>& rpPresenterController
,
1251 const Reference
<XResourceId
>& rxViewId
)
1252 : mpPresenterController(rpPresenterController
),
1253 mbIs24HourFormat(false),
1254 mbIsAdaptFontSize(true),
1257 msViewURL(rxViewId
.is() ? rxViewId
->getResourceURL() : OUString())
1264 DigitalDefaultPainter::~DigitalDefaultPainter (void)
1271 void DigitalDefaultPainter::Paint (
1272 const Reference
<rendering::XCanvas
>& rxCanvas
,
1273 const rendering::ViewState
& rViewState
,
1274 const rendering::RenderState
& rRenderState
,
1275 const util::Color
& rBackgroundColor
,
1276 const sal_Int32 nHour
,
1277 const sal_Int32 nMinute
,
1278 const sal_Int32 nSecond
,
1279 const bool bIsShowSeconds
)
1281 (void)rBackgroundColor
;
1285 CreateFont(rxCanvas
,bIsShowSeconds
);
1291 if (mbIs24HourFormat
)
1292 sText
= OUString::valueOf(nHour
);
1295 sText
= OUString::valueOf(nHour
>12 ? nHour
-12 : nHour
);
1297 sText
+= OUString::createFromAscii(":");
1298 const OUString
sMinutes (OUString::valueOf(nMinute
));
1299 switch (sMinutes
.getLength())
1302 sText
+= OUString::createFromAscii("0") + sMinutes
;
1313 sText
+= OUString::createFromAscii(":");
1314 const OUString
sSeconds (OUString::valueOf(nSecond
));
1315 switch (sSeconds
.getLength())
1318 sText
+= OUString::createFromAscii("0") + sSeconds
;
1329 rendering::StringContext
aContext (
1333 Reference
<rendering::XTextLayout
> xLayout (mxFont
->createTextLayout(
1335 rendering::TextDirection::WEAK_LEFT_TO_RIGHT
,
1337 if ( ! xLayout
.is())
1339 geometry::RealRectangle2D
aBox (xLayout
->queryTextBounds());
1342 rendering::RenderState
aRenderState(
1343 geometry::AffineMatrix2D(1,0,0, 0,1,0),
1345 Sequence
<double>(4),
1346 rendering::CompositeOperation::SOURCE
);
1348 util::Color
aFontColor (mpPresenterController
->GetViewFontColor(msViewURL
));
1349 PresenterCanvasHelper::SetDeviceColor(aRenderState
, aFontColor
);
1350 aRenderState
.AffineTransform
.m02
1351 = (maWindowSize
.Width
- (aBox
.X2
-aBox
.X1
+1)) / 2 - aBox
.X1
;
1352 aRenderState
.AffineTransform
.m12
1353 = (maWindowSize
.Height
- (aBox
.Y2
-aBox
.Y1
+1)) / 2 - aBox
.Y1
;
1359 rendering::TextDirection::WEAK_LEFT_TO_RIGHT
);
1365 void DigitalDefaultPainter::Resize (const awt::Size
& rSize
)
1367 if (maWindowSize
.Width
!= rSize
.Width
|| maWindowSize
.Height
!= rSize
.Height
)
1369 maWindowSize
= rSize
;
1370 if (mbIsAdaptFontSize
)
1378 void DigitalDefaultPainter::CreateFont (
1379 const Reference
<rendering::XCanvas
>& rxCanvas
,
1380 const bool bIsShowSeconds
)
1383 && rxCanvas
->getDevice().is()
1384 && maWindowSize
.Width
>0
1385 && maWindowSize
.Height
>0)
1387 // Create a time template for determinging the right font size.
1388 // Assume that 0 is the widest digit or that all digits have the
1390 OUString sTimeTemplate
;
1391 // For the case that not all digits have the same width, create
1392 // different templates for 12 and 24 hour mode.
1393 if (mbIs24HourFormat
)
1394 sTimeTemplate
= OUString::createFromAscii("20");
1396 sTimeTemplate
= OUString::createFromAscii("10");
1398 sTimeTemplate
+= OUString::createFromAscii(":00:00");
1400 sTimeTemplate
+= OUString::createFromAscii(":00");
1402 rendering::StringContext
aContext (
1405 sTimeTemplate
.getLength());
1407 // When the font size is adapted to the window size (as large as
1408 // possible without overlapping) then that is done in a four step
1410 // 1. Create a font in a default size, e.g. 10pt.
1411 // 2. Determine a scale factor from enlarging the text bounding box
1412 // to maximal size inside the window.
1413 // 3. Create a new font by scaling the default size with the factor
1414 // calculated in step 2.
1415 // 4. Text may be rendered differently in different sizes.
1416 // Therefore repeat step 2 and 3 once. More iterations may lead to
1417 // even better results but probably not to visible differences.
1418 rendering::FontRequest
aFontRequest (mpPresenterController
->GetViewFontRequest(msViewURL
));
1419 // TODO: use font from view style from configuration
1420 aFontRequest
.CellSize
= 10;
1422 for (sal_Int32 nLoop
=0; nLoop
<3; ++nLoop
)
1424 mxFont
= rxCanvas
->createFont(
1426 Sequence
<beans::PropertyValue
>(),
1427 geometry::Matrix2D(1,0,0,1));
1430 Reference
<rendering::XTextLayout
> xLayout (mxFont
->createTextLayout(
1432 rendering::TextDirection::WEAK_LEFT_TO_RIGHT
,
1435 if ( ! xLayout
.is())
1438 geometry::RealRectangle2D
aBox (xLayout
->queryTextBounds());
1439 if (aBox
.X2
<=aBox
.X1
|| aBox
.Y2
<=aBox
.Y1
)
1441 const double nHorizontalFactor
= maWindowSize
.Width
/ (aBox
.X2
-aBox
.X1
+1);
1442 const double nVerticalFactor
= maWindowSize
.Height
/ (aBox
.Y2
-aBox
.Y1
+1);
1443 aFontRequest
.CellSize
*= ::std::min(nHorizontalFactor
,nVerticalFactor
);
1450 } // end of anonymous namespace
1453 } } // end of namespace ::sdext::presenter