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>
33 using namespace ::com::sun::star
;
34 using namespace ::com::sun::star::uno
;
36 namespace sdext::presenter
{
38 const double gnHorizontalBorder (15);
39 const double gnVerticalBorder (5);
41 ::rtl::Reference
<PresenterButton
> PresenterButton::Create (
42 const css::uno::Reference
<css::uno::XComponentContext
>& rxComponentContext
,
43 const ::rtl::Reference
<PresenterController
>& rpPresenterController
,
44 const std::shared_ptr
<PresenterTheme
>& rpTheme
,
45 const css::uno::Reference
<css::awt::XWindow
>& rxParentWindow
,
46 const css::uno::Reference
<css::rendering::XCanvas
>& rxParentCanvas
,
47 const OUString
& rsConfigurationName
)
49 Reference
<beans::XPropertySet
> xProperties (GetConfigurationProperties(
51 rsConfigurationName
));
56 PresenterConfigurationAccess::GetProperty(xProperties
, "Text") >>= sText
;
57 PresenterConfigurationAccess::GetProperty(xProperties
, "Action") >>= sAction
;
59 PresenterTheme::SharedFontDescriptor pFont
;
60 if (rpTheme
!= nullptr)
61 pFont
= rpTheme
->GetFont("ButtonFont");
63 PresenterTheme::SharedFontDescriptor pMouseOverFont
;
64 if (rpTheme
!= nullptr)
65 pMouseOverFont
= rpTheme
->GetFont("ButtonMouseOverFont");
67 rtl::Reference
<PresenterButton
> pButton (
70 rpPresenterController
,
77 pButton
->SetCanvas(rxParentCanvas
, rxParentWindow
);
84 PresenterButton::PresenterButton (
85 const css::uno::Reference
<css::uno::XComponentContext
>& rxComponentContext
,
86 ::rtl::Reference
<PresenterController
> xPresenterController
,
87 std::shared_ptr
<PresenterTheme
> xTheme
,
88 const css::uno::Reference
<css::awt::XWindow
>& rxParentWindow
,
89 PresenterTheme::SharedFontDescriptor xFont
,
90 PresenterTheme::SharedFontDescriptor xMouseOverFont
,
93 : PresenterButtonInterfaceBase(m_aMutex
),
94 mpPresenterController(std::move(xPresenterController
)),
95 mpTheme(std::move(xTheme
)),
96 msText(std::move(sText
)),
97 mpFont(std::move(xFont
)),
98 mpMouseOverFont(std::move(xMouseOverFont
)),
99 msAction(std::move(sAction
)),
101 meState(PresenterBitmapDescriptor::Normal
)
105 Reference
<lang::XMultiComponentFactory
> xFactory (rxComponentContext
->getServiceManager());
106 if ( ! xFactory
.is())
107 throw RuntimeException();
109 mxPresenterHelper
.set(
110 xFactory
->createInstanceWithContext(
111 "com.sun.star.comp.Draw.PresenterHelper",
115 if (mxPresenterHelper
.is())
116 mxWindow
= mxPresenterHelper
->createWindow(rxParentWindow
,
122 // Make the background transparent.
123 Reference
<awt::XWindowPeer
> xPeer (mxWindow
, UNO_QUERY_THROW
);
124 xPeer
->setBackground(0xff000000);
126 mxWindow
->setVisible(true);
127 mxWindow
->addPaintListener(this);
128 mxWindow
->addMouseListener(this);
130 catch (RuntimeException
&)
135 PresenterButton::~PresenterButton()
139 void SAL_CALL
PresenterButton::disposing()
143 Reference
<lang::XComponent
> xComponent (mxCanvas
, UNO_QUERY
);
146 xComponent
->dispose();
151 mxWindow
->removePaintListener(this);
152 mxWindow
->removeMouseListener(this);
153 Reference
<lang::XComponent
> xComponent
= mxWindow
;
156 xComponent
->dispose();
160 void PresenterButton::SetCenter (const css::geometry::RealPoint2D
& rLocation
)
166 maCenter
= rLocation
;
167 mxWindow
->setPosSize(
168 sal_Int32(0.5 + maCenter
.X
- maButtonSize
.Width
/2),
169 sal_Int32(0.5 + maCenter
.Y
- maButtonSize
.Height
/2),
172 awt::PosSize::POSSIZE
);
178 // The button can not be painted but we can at least store the new center.
179 maCenter
= rLocation
;
183 void PresenterButton::SetCanvas (
184 const css::uno::Reference
<css::rendering::XCanvas
>& rxParentCanvas
,
185 const css::uno::Reference
<css::awt::XWindow
>& rxParentWindow
)
189 Reference
<lang::XComponent
> xComponent (mxCanvas
, UNO_QUERY
);
192 xComponent
->dispose();
195 if (!(mxPresenterHelper
.is() && rxParentCanvas
.is() && rxParentWindow
.is()))
198 mxCanvas
= mxPresenterHelper
->createSharedCanvas (
199 Reference
<rendering::XSpriteCanvas
>(rxParentCanvas
, UNO_QUERY
),
206 SetupButtonBitmaps();
211 css::geometry::IntegerSize2D
const & PresenterButton::GetSize()
213 if (maButtonSize
.Width
< 0)
214 CalculateButtonSize();
218 //----- XPaintListener --------------------------------------------------------
220 void SAL_CALL
PresenterButton::windowPaint (const css::awt::PaintEvent
& rEvent
)
223 if (!(mxWindow
.is() && mxCanvas
.is()))
226 Reference
<rendering::XBitmap
> xBitmap
;
227 if (meState
== PresenterBitmapDescriptor::MouseOver
)
228 xBitmap
= mxMouseOverBitmap
;
230 xBitmap
= mxNormalBitmap
;
234 rendering::ViewState
aViewState(
235 geometry::AffineMatrix2D(1,0,0, 0,1,0),
237 rendering::RenderState
aRenderState(
238 geometry::AffineMatrix2D(1,0,0, 0,1,0),
239 PresenterGeometryHelper::CreatePolygon(rEvent
.UpdateRect
, mxCanvas
->getDevice()),
241 rendering::CompositeOperation::SOURCE
);
243 mxCanvas
->drawBitmap(xBitmap
, aViewState
, aRenderState
);
245 Reference
<rendering::XSpriteCanvas
> xSpriteCanvas (mxCanvas
, UNO_QUERY
);
246 if (xSpriteCanvas
.is())
247 xSpriteCanvas
->updateScreen(false);
250 //----- XMouseListener --------------------------------------------------------
252 void SAL_CALL
PresenterButton::mousePressed (const css::awt::MouseEvent
&)
255 meState
= PresenterBitmapDescriptor::ButtonDown
;
258 void SAL_CALL
PresenterButton::mouseReleased (const css::awt::MouseEvent
&)
262 if (meState
== PresenterBitmapDescriptor::ButtonDown
)
264 OSL_ASSERT(mpPresenterController
);
265 mpPresenterController
->DispatchUnoCommand(msAction
);
267 meState
= PresenterBitmapDescriptor::Normal
;
272 void SAL_CALL
PresenterButton::mouseEntered (const css::awt::MouseEvent
&)
275 meState
= PresenterBitmapDescriptor::MouseOver
;
279 void SAL_CALL
PresenterButton::mouseExited (const css::awt::MouseEvent
&)
282 meState
= PresenterBitmapDescriptor::Normal
;
286 //----- lang::XEventListener --------------------------------------------------
288 void SAL_CALL
PresenterButton::disposing (const css::lang::EventObject
& rEvent
)
290 if (rEvent
.Source
== mxWindow
)
295 css::geometry::IntegerSize2D
PresenterButton::CalculateButtonSize()
297 if (mpFont
&& !mpFont
->mxFont
.is() && mxCanvas
.is())
298 mpFont
->PrepareFont(mxCanvas
);
299 if (!mpFont
|| !mpFont
->mxFont
.is())
300 return geometry::IntegerSize2D(-1,-1);
302 geometry::RealSize2D
aTextSize (PresenterCanvasHelper::GetTextSize(mpFont
->mxFont
,msText
));
304 return geometry::IntegerSize2D (
305 sal_Int32(0.5 + aTextSize
.Width
+ 2*gnHorizontalBorder
),
306 sal_Int32(0.5 + aTextSize
.Height
+ 2*gnVerticalBorder
));
309 void PresenterButton::RenderButton (
310 const Reference
<rendering::XCanvas
>& rxCanvas
,
311 const geometry::IntegerSize2D
& rSize
,
312 const PresenterTheme::SharedFontDescriptor
& rpFont
,
313 const PresenterBitmapDescriptor::Mode eMode
,
314 const SharedBitmapDescriptor
& rpLeft
,
315 const SharedBitmapDescriptor
& rpCenter
,
316 const SharedBitmapDescriptor
& rpRight
)
318 if ( ! rxCanvas
.is())
321 const awt::Rectangle
aBox(0,0, rSize
.Width
, rSize
.Height
);
323 PresenterUIPainter::PaintHorizontalBitmapComposite (
327 GetBitmap(rpLeft
, eMode
),
328 GetBitmap(rpCenter
, eMode
),
329 GetBitmap(rpRight
, eMode
));
331 if (!rpFont
|| ! rpFont
->mxFont
.is())
334 const rendering::StringContext
aContext (msText
, 0, msText
.getLength());
335 const Reference
<rendering::XTextLayout
> xLayout (
336 rpFont
->mxFont
->createTextLayout(aContext
,rendering::TextDirection::WEAK_LEFT_TO_RIGHT
,0));
337 const geometry::RealRectangle2D
aTextBBox (xLayout
->queryTextBounds());
339 rendering::RenderState
aRenderState (geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr,
340 Sequence
<double>(4), rendering::CompositeOperation::SOURCE
);
341 PresenterCanvasHelper::SetDeviceColor(aRenderState
, rpFont
->mnColor
);
343 aRenderState
.AffineTransform
.m02
= (rSize
.Width
- aTextBBox
.X2
+ aTextBBox
.X1
)/2;
344 aRenderState
.AffineTransform
.m12
= (rSize
.Height
- aTextBBox
.Y2
+ aTextBBox
.Y1
)/2 - aTextBBox
.Y1
;
346 /// this is responsible of the close button
347 rxCanvas
->drawTextLayout(
349 rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr),
353 void PresenterButton::Invalidate()
355 mpPresenterController
->GetPaintManager()->Invalidate(mxWindow
);
358 Reference
<rendering::XBitmap
> PresenterButton::GetBitmap (
359 const SharedBitmapDescriptor
& mpIcon
,
360 const PresenterBitmapDescriptor::Mode eMode
)
363 return mpIcon
->GetBitmap(eMode
);
371 void PresenterButton::SetupButtonBitmaps()
373 if ( ! mxCanvas
.is())
375 if ( ! mxCanvas
->getDevice().is())
378 // Get the bitmaps for the button border.
379 SharedBitmapDescriptor
pLeftBitmap (mpTheme
->GetBitmap("ButtonFrameLeft"));
380 SharedBitmapDescriptor
pCenterBitmap(mpTheme
->GetBitmap("ButtonFrameCenter"));
381 SharedBitmapDescriptor
pRightBitmap(mpTheme
->GetBitmap("ButtonFrameRight"));
383 maButtonSize
= CalculateButtonSize();
385 if (maButtonSize
.Height
<=0 && maButtonSize
.Width
<= 0)
388 mxNormalBitmap
= mxCanvas
->getDevice()->createCompatibleAlphaBitmap(maButtonSize
);
389 Reference
<rendering::XCanvas
> xCanvas (mxNormalBitmap
, UNO_QUERY
);
395 PresenterBitmapDescriptor::Normal
,
400 mxMouseOverBitmap
= mxCanvas
->getDevice()->createCompatibleAlphaBitmap(maButtonSize
);
401 xCanvas
.set(mxMouseOverBitmap
, UNO_QUERY
);
402 if (mpMouseOverFont
&& !mpMouseOverFont
->mxFont
.is() && mxCanvas
.is())
403 mpMouseOverFont
->PrepareFont(mxCanvas
);
409 PresenterBitmapDescriptor::MouseOver
,
415 Reference
<beans::XPropertySet
> PresenterButton::GetConfigurationProperties (
416 const css::uno::Reference
<css::uno::XComponentContext
>& rxComponentContext
,
417 const OUString
& rsConfigurationName
)
419 PresenterConfigurationAccess
aConfiguration (
421 PresenterConfigurationAccess::msPresenterScreenRootName
,
422 PresenterConfigurationAccess::READ_ONLY
);
423 return Reference
<beans::XPropertySet
>(
424 PresenterConfigurationAccess::Find (
425 Reference
<container::XNameAccess
>(
426 aConfiguration
.GetConfigurationNode("PresenterScreenSettings/Buttons"),
428 [&rsConfigurationName
](OUString
const&, uno::Reference
<beans::XPropertySet
> const& xProps
) -> bool
430 return PresenterConfigurationAccess::IsStringPropertyEqual(
431 rsConfigurationName
, "Name", xProps
);
436 void PresenterButton::ThrowIfDisposed() const
438 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
440 throw lang::DisposedException (
441 "PresenterButton object has already been disposed",
442 const_cast<uno::XWeak
*>(static_cast<const uno::XWeak
*>(this)));
446 } // end of namespace sdext::presenter
448 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */