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 <vcl/svapp.hxx>
21 #include "PresenterButton.hxx"
22 #include "PresenterCanvasHelper.hxx"
23 #include "PresenterController.hxx"
24 #include "PresenterGeometryHelper.hxx"
25 #include "PresenterPaintManager.hxx"
26 #include "PresenterUIPainter.hxx"
27 #include <com/sun/star/awt/PosSize.hpp>
28 #include <com/sun/star/awt/XWindowPeer.hpp>
29 #include <com/sun/star/drawing/XPresenterHelper.hpp>
30 #include <com/sun/star/rendering/CompositeOperation.hpp>
31 #include <com/sun/star/rendering/TextDirection.hpp>
33 using namespace ::com::sun::star
;
34 using namespace ::com::sun::star::uno
;
36 namespace sdext
{ namespace presenter
{
38 const static double gnHorizontalBorder (15);
39 const static 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 const ::rtl::Reference
<PresenterController
>& rpPresenterController
,
87 const std::shared_ptr
<PresenterTheme
>& rpTheme
,
88 const css::uno::Reference
<css::awt::XWindow
>& rxParentWindow
,
89 const PresenterTheme::SharedFontDescriptor
& rpFont
,
90 const PresenterTheme::SharedFontDescriptor
& rpMouseOverFont
,
91 const OUString
& rsText
,
92 const OUString
& rsAction
)
93 : PresenterButtonInterfaceBase(m_aMutex
),
94 mpPresenterController(rpPresenterController
),
101 mpMouseOverFont(rpMouseOverFont
),
105 meState(PresenterBitmapDescriptor::Normal
),
111 Reference
<lang::XMultiComponentFactory
> xFactory (rxComponentContext
->getServiceManager());
112 if ( ! xFactory
.is())
113 throw RuntimeException();
115 mxPresenterHelper
.set(
116 xFactory
->createInstanceWithContext(
117 "com.sun.star.comp.Draw.PresenterHelper",
121 if (mxPresenterHelper
.is())
122 mxWindow
= mxPresenterHelper
->createWindow(rxParentWindow
,
128 // Make the background transparent.
129 Reference
<awt::XWindowPeer
> xPeer (mxWindow
, UNO_QUERY_THROW
);
130 xPeer
->setBackground(0xff000000);
132 mxWindow
->setVisible(true);
133 mxWindow
->addWindowListener(this);
134 mxWindow
->addPaintListener(this);
135 mxWindow
->addMouseListener(this);
136 mxWindow
->addMouseMotionListener(this);
138 catch (RuntimeException
&)
143 PresenterButton::~PresenterButton()
147 void SAL_CALL
PresenterButton::disposing()
151 Reference
<lang::XComponent
> xComponent (mxCanvas
, UNO_QUERY
);
154 xComponent
->dispose();
159 mxWindow
->removeWindowListener(this);
160 mxWindow
->removePaintListener(this);
161 mxWindow
->removeMouseListener(this);
162 mxWindow
->removeMouseMotionListener(this);
163 Reference
<lang::XComponent
> xComponent (mxWindow
, UNO_QUERY
);
166 xComponent
->dispose();
170 void PresenterButton::SetCenter (const css::geometry::RealPoint2D
& rLocation
)
176 maCenter
= rLocation
;
177 mxWindow
->setPosSize(
178 sal_Int32(0.5 + maCenter
.X
- maButtonSize
.Width
/2),
179 sal_Int32(0.5 + maCenter
.Y
- maButtonSize
.Height
/2),
182 awt::PosSize::POSSIZE
);
188 // The button can not be painted but we can at least store the new center.
189 maCenter
= rLocation
;
193 void PresenterButton::SetCanvas (
194 const css::uno::Reference
<css::rendering::XCanvas
>& rxParentCanvas
,
195 const css::uno::Reference
<css::awt::XWindow
>& rxParentWindow
)
199 Reference
<lang::XComponent
> xComponent (mxCanvas
, UNO_QUERY
);
202 xComponent
->dispose();
205 if (!(mxPresenterHelper
.is() && rxParentCanvas
.is() && rxParentWindow
.is()))
208 mxCanvas
= mxPresenterHelper
->createSharedCanvas (
209 Reference
<rendering::XSpriteCanvas
>(rxParentCanvas
, UNO_QUERY
),
216 SetupButtonBitmaps();
221 css::geometry::IntegerSize2D
const & PresenterButton::GetSize()
223 if (maButtonSize
.Width
< 0)
224 CalculateButtonSize();
228 //----- XWindowListener -------------------------------------------------------
230 void SAL_CALL
PresenterButton::windowResized (const css::awt::WindowEvent
&)
235 void SAL_CALL
PresenterButton::windowMoved (const css::awt::WindowEvent
&)
240 void SAL_CALL
PresenterButton::windowShown (const css::lang::EventObject
&)
245 void SAL_CALL
PresenterButton::windowHidden (const css::lang::EventObject
&)
250 //----- XPaintListener --------------------------------------------------------
252 void SAL_CALL
PresenterButton::windowPaint (const css::awt::PaintEvent
& rEvent
)
255 if (!(mxWindow
.is() && mxCanvas
.is()))
258 Reference
<rendering::XBitmap
> xBitmap
;
259 if (meState
== PresenterBitmapDescriptor::MouseOver
)
260 xBitmap
= mxMouseOverBitmap
;
262 xBitmap
= mxNormalBitmap
;
266 rendering::ViewState
aViewState(
267 geometry::AffineMatrix2D(1,0,0, 0,1,0),
269 rendering::RenderState
aRenderState(
270 geometry::AffineMatrix2D(1,0,0, 0,1,0),
271 PresenterGeometryHelper::CreatePolygon(rEvent
.UpdateRect
, mxCanvas
->getDevice()),
273 rendering::CompositeOperation::SOURCE
);
275 mxCanvas
->drawBitmap(xBitmap
, aViewState
, aRenderState
);
277 Reference
<rendering::XSpriteCanvas
> xSpriteCanvas (mxCanvas
, UNO_QUERY
);
278 if (xSpriteCanvas
.is())
279 xSpriteCanvas
->updateScreen(false);
282 //----- XMouseListener --------------------------------------------------------
284 void SAL_CALL
PresenterButton::mousePressed (const css::awt::MouseEvent
&)
287 meState
= PresenterBitmapDescriptor::ButtonDown
;
290 void SAL_CALL
PresenterButton::mouseReleased (const css::awt::MouseEvent
&)
294 if (meState
== PresenterBitmapDescriptor::ButtonDown
)
296 OSL_ASSERT(mpPresenterController
.get()!=nullptr);
297 mpPresenterController
->DispatchUnoCommand(msAction
);
299 meState
= PresenterBitmapDescriptor::Normal
;
304 void SAL_CALL
PresenterButton::mouseEntered (const css::awt::MouseEvent
&)
307 meState
= PresenterBitmapDescriptor::MouseOver
;
311 void SAL_CALL
PresenterButton::mouseExited (const css::awt::MouseEvent
&)
314 meState
= PresenterBitmapDescriptor::Normal
;
318 //----- XMouseMotionListener --------------------------------------------------
320 void SAL_CALL
PresenterButton::mouseMoved (const css::awt::MouseEvent
&)
325 void SAL_CALL
PresenterButton::mouseDragged (const css::awt::MouseEvent
&)
330 //----- lang::XEventListener --------------------------------------------------
332 void SAL_CALL
PresenterButton::disposing (const css::lang::EventObject
& rEvent
)
334 if (rEvent
.Source
== mxWindow
)
339 css::geometry::IntegerSize2D
PresenterButton::CalculateButtonSize()
341 if (mpFont
.get()!=nullptr && !mpFont
->mxFont
.is() && mxCanvas
.is())
342 mpFont
->PrepareFont(mxCanvas
);
343 if (mpFont
.get()==nullptr || !mpFont
->mxFont
.is())
344 return geometry::IntegerSize2D(-1,-1);
346 geometry::RealSize2D
aTextSize (PresenterCanvasHelper::GetTextSize(mpFont
->mxFont
,msText
));
348 return geometry::IntegerSize2D (
349 sal_Int32(0.5 + aTextSize
.Width
+ 2*gnHorizontalBorder
),
350 sal_Int32(0.5 + aTextSize
.Height
+ 2*gnVerticalBorder
));
353 void PresenterButton::RenderButton (
354 const Reference
<rendering::XCanvas
>& rxCanvas
,
355 const geometry::IntegerSize2D
& rSize
,
356 const PresenterTheme::SharedFontDescriptor
& rpFont
,
357 const PresenterBitmapDescriptor::Mode eMode
,
358 const SharedBitmapDescriptor
& rpLeft
,
359 const SharedBitmapDescriptor
& rpCenter
,
360 const SharedBitmapDescriptor
& rpRight
)
362 if ( ! rxCanvas
.is())
365 const awt::Rectangle
aBox(0,0, rSize
.Width
, rSize
.Height
);
367 PresenterUIPainter::PaintHorizontalBitmapComposite (
371 GetBitmap(rpLeft
, eMode
),
372 GetBitmap(rpCenter
, eMode
),
373 GetBitmap(rpRight
, eMode
));
375 if (rpFont
.get()==nullptr || ! rpFont
->mxFont
.is())
378 const rendering::StringContext
aContext (msText
, 0, msText
.getLength());
379 const Reference
<rendering::XTextLayout
> xLayout (
380 rpFont
->mxFont
->createTextLayout(aContext
,rendering::TextDirection::WEAK_LEFT_TO_RIGHT
,0));
381 const geometry::RealRectangle2D
aTextBBox (xLayout
->queryTextBounds());
383 rendering::RenderState
aRenderState (geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr,
384 Sequence
<double>(4), rendering::CompositeOperation::SOURCE
);
385 PresenterCanvasHelper::SetDeviceColor(aRenderState
, rpFont
->mnColor
);
387 aRenderState
.AffineTransform
.m02
= (rSize
.Width
- aTextBBox
.X2
+ aTextBBox
.X1
)/2;
388 aRenderState
.AffineTransform
.m12
= (rSize
.Height
- aTextBBox
.Y2
+ aTextBBox
.Y1
)/2 - aTextBBox
.Y1
;
390 /// this is responsible of the close button
391 rxCanvas
->drawTextLayout(
393 rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr),
397 void PresenterButton::Invalidate()
399 mpPresenterController
->GetPaintManager()->Invalidate(mxWindow
);
402 Reference
<rendering::XBitmap
> PresenterButton::GetBitmap (
403 const SharedBitmapDescriptor
& mpIcon
,
404 const PresenterBitmapDescriptor::Mode eMode
)
406 if (mpIcon
.get() != nullptr)
407 return mpIcon
->GetBitmap(eMode
);
410 OSL_ASSERT(mpIcon
.get()!=nullptr);
415 void PresenterButton::SetupButtonBitmaps()
417 if ( ! mxCanvas
.is())
419 if ( ! mxCanvas
->getDevice().is())
422 // Get the bitmaps for the button border.
423 SharedBitmapDescriptor
pLeftBitmap (mpTheme
->GetBitmap("ButtonFrameLeft"));
424 SharedBitmapDescriptor
pCenterBitmap(mpTheme
->GetBitmap("ButtonFrameCenter"));
425 SharedBitmapDescriptor
pRightBitmap(mpTheme
->GetBitmap("ButtonFrameRight"));
427 maButtonSize
= CalculateButtonSize();
429 if (maButtonSize
.Height
<=0 && maButtonSize
.Width
<= 0)
432 mxNormalBitmap
= mxCanvas
->getDevice()->createCompatibleAlphaBitmap(maButtonSize
);
433 Reference
<rendering::XCanvas
> xCanvas (mxNormalBitmap
, UNO_QUERY
);
439 PresenterBitmapDescriptor::Normal
,
444 mxMouseOverBitmap
= mxCanvas
->getDevice()->createCompatibleAlphaBitmap(maButtonSize
);
445 xCanvas
.set(mxMouseOverBitmap
, UNO_QUERY
);
446 if (mpMouseOverFont
.get()!=nullptr && !mpMouseOverFont
->mxFont
.is() && mxCanvas
.is())
447 mpMouseOverFont
->PrepareFont(mxCanvas
);
453 PresenterBitmapDescriptor::MouseOver
,
459 Reference
<beans::XPropertySet
> PresenterButton::GetConfigurationProperties (
460 const css::uno::Reference
<css::uno::XComponentContext
>& rxComponentContext
,
461 const OUString
& rsConfgurationName
)
463 PresenterConfigurationAccess
aConfiguration (
465 PresenterConfigurationAccess::msPresenterScreenRootName
,
466 PresenterConfigurationAccess::READ_ONLY
);
467 return Reference
<beans::XPropertySet
>(
468 PresenterConfigurationAccess::Find (
469 Reference
<container::XNameAccess
>(
470 aConfiguration
.GetConfigurationNode("PresenterScreenSettings/Buttons"),
472 [&rsConfgurationName
](OUString
const&, uno::Reference
<beans::XPropertySet
> const& xProps
) -> bool
474 return PresenterConfigurationAccess::IsStringPropertyEqual(
475 rsConfgurationName
, "Name", xProps
);
480 void PresenterButton::ThrowIfDisposed() const
482 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
484 throw lang::DisposedException (
485 "PresenterButton object has already been disposed",
486 const_cast<uno::XWeak
*>(static_cast<const uno::XWeak
*>(this)));
490 } } // end of namespace sdext::presenter
492 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */