1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "PresenterButton.hxx"
21 #include "PresenterCanvasHelper.hxx"
22 #include "PresenterController.hxx"
23 #include "PresenterGeometryHelper.hxx"
24 #include "PresenterPaintManager.hxx"
25 #include "PresenterUIPainter.hxx"
26 #include <com/sun/star/awt/PosSize.hpp>
27 #include <com/sun/star/awt/XWindowPeer.hpp>
28 #include <com/sun/star/drawing/XPresenterHelper.hpp>
29 #include <com/sun/star/rendering/CompositeOperation.hpp>
30 #include <com/sun/star/rendering/TextDirection.hpp>
32 using namespace ::com::sun::star
;
33 using namespace ::com::sun::star::uno
;
35 namespace sdext
{ namespace presenter
{
37 const static double gnHorizontalBorder (15);
38 const static double gnVerticalBorder (5);
40 ::rtl::Reference
<PresenterButton
> PresenterButton::Create (
41 const css::uno::Reference
<css::uno::XComponentContext
>& rxComponentContext
,
42 const ::rtl::Reference
<PresenterController
>& rpPresenterController
,
43 const std::shared_ptr
<PresenterTheme
>& rpTheme
,
44 const css::uno::Reference
<css::awt::XWindow
>& rxParentWindow
,
45 const css::uno::Reference
<css::rendering::XCanvas
>& rxParentCanvas
,
46 const OUString
& rsConfigurationName
)
48 Reference
<beans::XPropertySet
> xProperties (GetConfigurationProperties(
50 rsConfigurationName
));
55 PresenterConfigurationAccess::GetProperty(xProperties
, "Text") >>= sText
;
56 PresenterConfigurationAccess::GetProperty(xProperties
, "Action") >>= sAction
;
58 PresenterTheme::SharedFontDescriptor pFont
;
59 if (rpTheme
!= nullptr)
60 pFont
= rpTheme
->GetFont("ButtonFont");
62 PresenterTheme::SharedFontDescriptor pMouseOverFont
;
63 if (rpTheme
!= nullptr)
64 pMouseOverFont
= rpTheme
->GetFont("ButtonMouseOverFont");
66 rtl::Reference
<PresenterButton
> pButton (
69 rpPresenterController
,
76 pButton
->SetCanvas(rxParentCanvas
, rxParentWindow
);
83 PresenterButton::PresenterButton (
84 const css::uno::Reference
<css::uno::XComponentContext
>& rxComponentContext
,
85 const ::rtl::Reference
<PresenterController
>& rpPresenterController
,
86 const std::shared_ptr
<PresenterTheme
>& rpTheme
,
87 const css::uno::Reference
<css::awt::XWindow
>& rxParentWindow
,
88 const PresenterTheme::SharedFontDescriptor
& rpFont
,
89 const PresenterTheme::SharedFontDescriptor
& rpMouseOverFont
,
90 const OUString
& rsText
,
91 const OUString
& rsAction
)
92 : PresenterButtonInterfaceBase(m_aMutex
),
93 mpPresenterController(rpPresenterController
),
100 mpMouseOverFont(rpMouseOverFont
),
104 meState(PresenterBitmapDescriptor::Normal
),
110 Reference
<lang::XMultiComponentFactory
> xFactory (rxComponentContext
->getServiceManager());
111 if ( ! xFactory
.is())
112 throw RuntimeException();
114 mxPresenterHelper
.set(
115 xFactory
->createInstanceWithContext(
116 "com.sun.star.comp.Draw.PresenterHelper",
120 if (mxPresenterHelper
.is())
121 mxWindow
= mxPresenterHelper
->createWindow(rxParentWindow
,
127 // Make the background transparent.
128 Reference
<awt::XWindowPeer
> xPeer (mxWindow
, UNO_QUERY_THROW
);
129 xPeer
->setBackground(0xff000000);
131 mxWindow
->setVisible(true);
132 mxWindow
->addPaintListener(this);
133 mxWindow
->addMouseListener(this);
135 catch (RuntimeException
&)
140 PresenterButton::~PresenterButton()
144 void SAL_CALL
PresenterButton::disposing()
148 Reference
<lang::XComponent
> xComponent (mxCanvas
, UNO_QUERY
);
151 xComponent
->dispose();
156 mxWindow
->removePaintListener(this);
157 mxWindow
->removeMouseListener(this);
158 Reference
<lang::XComponent
> xComponent
= mxWindow
;
161 xComponent
->dispose();
165 void PresenterButton::SetCenter (const css::geometry::RealPoint2D
& rLocation
)
171 maCenter
= rLocation
;
172 mxWindow
->setPosSize(
173 sal_Int32(0.5 + maCenter
.X
- maButtonSize
.Width
/2),
174 sal_Int32(0.5 + maCenter
.Y
- maButtonSize
.Height
/2),
177 awt::PosSize::POSSIZE
);
183 // The button can not be painted but we can at least store the new center.
184 maCenter
= rLocation
;
188 void PresenterButton::SetCanvas (
189 const css::uno::Reference
<css::rendering::XCanvas
>& rxParentCanvas
,
190 const css::uno::Reference
<css::awt::XWindow
>& rxParentWindow
)
194 Reference
<lang::XComponent
> xComponent (mxCanvas
, UNO_QUERY
);
197 xComponent
->dispose();
200 if (!(mxPresenterHelper
.is() && rxParentCanvas
.is() && rxParentWindow
.is()))
203 mxCanvas
= mxPresenterHelper
->createSharedCanvas (
204 Reference
<rendering::XSpriteCanvas
>(rxParentCanvas
, UNO_QUERY
),
211 SetupButtonBitmaps();
216 css::geometry::IntegerSize2D
const & PresenterButton::GetSize()
218 if (maButtonSize
.Width
< 0)
219 CalculateButtonSize();
223 //----- XPaintListener --------------------------------------------------------
225 void SAL_CALL
PresenterButton::windowPaint (const css::awt::PaintEvent
& rEvent
)
228 if (!(mxWindow
.is() && mxCanvas
.is()))
231 Reference
<rendering::XBitmap
> xBitmap
;
232 if (meState
== PresenterBitmapDescriptor::MouseOver
)
233 xBitmap
= mxMouseOverBitmap
;
235 xBitmap
= mxNormalBitmap
;
239 rendering::ViewState
aViewState(
240 geometry::AffineMatrix2D(1,0,0, 0,1,0),
242 rendering::RenderState
aRenderState(
243 geometry::AffineMatrix2D(1,0,0, 0,1,0),
244 PresenterGeometryHelper::CreatePolygon(rEvent
.UpdateRect
, mxCanvas
->getDevice()),
246 rendering::CompositeOperation::SOURCE
);
248 mxCanvas
->drawBitmap(xBitmap
, aViewState
, aRenderState
);
250 Reference
<rendering::XSpriteCanvas
> xSpriteCanvas (mxCanvas
, UNO_QUERY
);
251 if (xSpriteCanvas
.is())
252 xSpriteCanvas
->updateScreen(false);
255 //----- XMouseListener --------------------------------------------------------
257 void SAL_CALL
PresenterButton::mousePressed (const css::awt::MouseEvent
&)
260 meState
= PresenterBitmapDescriptor::ButtonDown
;
263 void SAL_CALL
PresenterButton::mouseReleased (const css::awt::MouseEvent
&)
267 if (meState
== PresenterBitmapDescriptor::ButtonDown
)
269 OSL_ASSERT(mpPresenterController
.get()!=nullptr);
270 mpPresenterController
->DispatchUnoCommand(msAction
);
272 meState
= PresenterBitmapDescriptor::Normal
;
277 void SAL_CALL
PresenterButton::mouseEntered (const css::awt::MouseEvent
&)
280 meState
= PresenterBitmapDescriptor::MouseOver
;
284 void SAL_CALL
PresenterButton::mouseExited (const css::awt::MouseEvent
&)
287 meState
= PresenterBitmapDescriptor::Normal
;
291 //----- lang::XEventListener --------------------------------------------------
293 void SAL_CALL
PresenterButton::disposing (const css::lang::EventObject
& rEvent
)
295 if (rEvent
.Source
== mxWindow
)
300 css::geometry::IntegerSize2D
PresenterButton::CalculateButtonSize()
302 if (mpFont
.get()!=nullptr && !mpFont
->mxFont
.is() && mxCanvas
.is())
303 mpFont
->PrepareFont(mxCanvas
);
304 if (mpFont
.get()==nullptr || !mpFont
->mxFont
.is())
305 return geometry::IntegerSize2D(-1,-1);
307 geometry::RealSize2D
aTextSize (PresenterCanvasHelper::GetTextSize(mpFont
->mxFont
,msText
));
309 return geometry::IntegerSize2D (
310 sal_Int32(0.5 + aTextSize
.Width
+ 2*gnHorizontalBorder
),
311 sal_Int32(0.5 + aTextSize
.Height
+ 2*gnVerticalBorder
));
314 void PresenterButton::RenderButton (
315 const Reference
<rendering::XCanvas
>& rxCanvas
,
316 const geometry::IntegerSize2D
& rSize
,
317 const PresenterTheme::SharedFontDescriptor
& rpFont
,
318 const PresenterBitmapDescriptor::Mode eMode
,
319 const SharedBitmapDescriptor
& rpLeft
,
320 const SharedBitmapDescriptor
& rpCenter
,
321 const SharedBitmapDescriptor
& rpRight
)
323 if ( ! rxCanvas
.is())
326 const awt::Rectangle
aBox(0,0, rSize
.Width
, rSize
.Height
);
328 PresenterUIPainter::PaintHorizontalBitmapComposite (
332 GetBitmap(rpLeft
, eMode
),
333 GetBitmap(rpCenter
, eMode
),
334 GetBitmap(rpRight
, eMode
));
336 if (rpFont
.get()==nullptr || ! rpFont
->mxFont
.is())
339 const rendering::StringContext
aContext (msText
, 0, msText
.getLength());
340 const Reference
<rendering::XTextLayout
> xLayout (
341 rpFont
->mxFont
->createTextLayout(aContext
,rendering::TextDirection::WEAK_LEFT_TO_RIGHT
,0));
342 const geometry::RealRectangle2D
aTextBBox (xLayout
->queryTextBounds());
344 rendering::RenderState
aRenderState (geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr,
345 Sequence
<double>(4), rendering::CompositeOperation::SOURCE
);
346 PresenterCanvasHelper::SetDeviceColor(aRenderState
, rpFont
->mnColor
);
348 aRenderState
.AffineTransform
.m02
= (rSize
.Width
- aTextBBox
.X2
+ aTextBBox
.X1
)/2;
349 aRenderState
.AffineTransform
.m12
= (rSize
.Height
- aTextBBox
.Y2
+ aTextBBox
.Y1
)/2 - aTextBBox
.Y1
;
351 /// this is responsible of the close button
352 rxCanvas
->drawTextLayout(
354 rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr),
358 void PresenterButton::Invalidate()
360 mpPresenterController
->GetPaintManager()->Invalidate(mxWindow
);
363 Reference
<rendering::XBitmap
> PresenterButton::GetBitmap (
364 const SharedBitmapDescriptor
& mpIcon
,
365 const PresenterBitmapDescriptor::Mode eMode
)
367 if (mpIcon
.get() != nullptr)
368 return mpIcon
->GetBitmap(eMode
);
371 OSL_ASSERT(mpIcon
.get()!=nullptr);
376 void PresenterButton::SetupButtonBitmaps()
378 if ( ! mxCanvas
.is())
380 if ( ! mxCanvas
->getDevice().is())
383 // Get the bitmaps for the button border.
384 SharedBitmapDescriptor
pLeftBitmap (mpTheme
->GetBitmap("ButtonFrameLeft"));
385 SharedBitmapDescriptor
pCenterBitmap(mpTheme
->GetBitmap("ButtonFrameCenter"));
386 SharedBitmapDescriptor
pRightBitmap(mpTheme
->GetBitmap("ButtonFrameRight"));
388 maButtonSize
= CalculateButtonSize();
390 if (maButtonSize
.Height
<=0 && maButtonSize
.Width
<= 0)
393 mxNormalBitmap
= mxCanvas
->getDevice()->createCompatibleAlphaBitmap(maButtonSize
);
394 Reference
<rendering::XCanvas
> xCanvas (mxNormalBitmap
, UNO_QUERY
);
400 PresenterBitmapDescriptor::Normal
,
405 mxMouseOverBitmap
= mxCanvas
->getDevice()->createCompatibleAlphaBitmap(maButtonSize
);
406 xCanvas
.set(mxMouseOverBitmap
, UNO_QUERY
);
407 if (mpMouseOverFont
.get()!=nullptr && !mpMouseOverFont
->mxFont
.is() && mxCanvas
.is())
408 mpMouseOverFont
->PrepareFont(mxCanvas
);
414 PresenterBitmapDescriptor::MouseOver
,
420 Reference
<beans::XPropertySet
> PresenterButton::GetConfigurationProperties (
421 const css::uno::Reference
<css::uno::XComponentContext
>& rxComponentContext
,
422 const OUString
& rsConfgurationName
)
424 PresenterConfigurationAccess
aConfiguration (
426 PresenterConfigurationAccess::msPresenterScreenRootName
,
427 PresenterConfigurationAccess::READ_ONLY
);
428 return Reference
<beans::XPropertySet
>(
429 PresenterConfigurationAccess::Find (
430 Reference
<container::XNameAccess
>(
431 aConfiguration
.GetConfigurationNode("PresenterScreenSettings/Buttons"),
433 [&rsConfgurationName
](OUString
const&, uno::Reference
<beans::XPropertySet
> const& xProps
) -> bool
435 return PresenterConfigurationAccess::IsStringPropertyEqual(
436 rsConfgurationName
, "Name", xProps
);
441 void PresenterButton::ThrowIfDisposed() const
443 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
445 throw lang::DisposedException (
446 "PresenterButton object has already been disposed",
447 const_cast<uno::XWeak
*>(static_cast<const uno::XWeak
*>(this)));
451 } } // end of namespace sdext::presenter
453 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */