LibreOffice Module sd (master) 1
PresenterButton.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include "PresenterButton.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>
31#include <utility>
32
33using namespace ::com::sun::star;
34using namespace ::com::sun::star::uno;
35
36namespace sdext::presenter {
37
38const double gnHorizontalBorder (15);
39const double gnVerticalBorder (5);
40
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)
48{
49 Reference<beans::XPropertySet> xProperties (GetConfigurationProperties(
50 rxComponentContext,
51 rsConfigurationName));
52 if (xProperties.is())
53 {
54 OUString sText;
55 OUString sAction;
56 PresenterConfigurationAccess::GetProperty(xProperties, "Text") >>= sText;
57 PresenterConfigurationAccess::GetProperty(xProperties, "Action") >>= sAction;
58
60 if (rpTheme != nullptr)
61 pFont = rpTheme->GetFont("ButtonFont");
62
64 if (rpTheme != nullptr)
65 pMouseOverFont = rpTheme->GetFont("ButtonMouseOverFont");
66
69 rxComponentContext,
70 rpPresenterController,
71 rpTheme,
72 rxParentWindow,
73 pFont,
74 pMouseOverFont,
75 sText,
76 sAction));
77 pButton->SetCanvas(rxParentCanvas, rxParentWindow);
78 return pButton;
79 }
80 else
81 return nullptr;
82}
83
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,
91 OUString sText,
92 OUString sAction)
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)),
100 maButtonSize(-1,-1),
102{
103 try
104 {
105 Reference<lang::XMultiComponentFactory> xFactory (rxComponentContext->getServiceManager());
106 if ( ! xFactory.is())
107 throw RuntimeException();
108
110 xFactory->createInstanceWithContext(
111 "com.sun.star.comp.Draw.PresenterHelper",
112 rxComponentContext),
113 UNO_QUERY_THROW);
114
115 if (mxPresenterHelper.is())
116 mxWindow = mxPresenterHelper->createWindow(rxParentWindow,
117 false,
118 false,
119 false,
120 false);
121
122 // Make the background transparent.
123 Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY_THROW);
124 xPeer->setBackground(0xff000000);
125
126 mxWindow->setVisible(true);
127 mxWindow->addPaintListener(this);
128 mxWindow->addMouseListener(this);
129 }
130 catch (RuntimeException&)
131 {
132 }
133}
134
136{
137}
138
140{
141 if (mxCanvas.is())
142 {
143 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
144 mxCanvas = nullptr;
145 if (xComponent.is())
146 xComponent->dispose();
147 }
148
149 if (mxWindow.is())
150 {
151 mxWindow->removePaintListener(this);
152 mxWindow->removeMouseListener(this);
153 Reference<lang::XComponent> xComponent = mxWindow;
154 mxWindow = nullptr;
155 if (xComponent.is())
156 xComponent->dispose();
157 }
158}
159
160void PresenterButton::SetCenter (const css::geometry::RealPoint2D& rLocation)
161{
162 if (mxCanvas.is())
163 {
164 Invalidate();
165
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),
170 maButtonSize.Width,
171 maButtonSize.Height,
172 awt::PosSize::POSSIZE);
173
174 Invalidate();
175 }
176 else
177 {
178 // The button can not be painted but we can at least store the new center.
179 maCenter = rLocation;
180 }
181}
182
184 const css::uno::Reference<css::rendering::XCanvas>& rxParentCanvas,
185 const css::uno::Reference<css::awt::XWindow>& rxParentWindow)
186{
187 if (mxCanvas.is())
188 {
189 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
190 mxCanvas = nullptr;
191 if (xComponent.is())
192 xComponent->dispose();
193 }
194
195 if (!(mxPresenterHelper.is() && rxParentCanvas.is() && rxParentWindow.is()))
196 return;
197
198 mxCanvas = mxPresenterHelper->createSharedCanvas (
199 Reference<rendering::XSpriteCanvas>(rxParentCanvas, UNO_QUERY),
200 rxParentWindow,
201 rxParentCanvas,
202 rxParentWindow,
203 mxWindow);
204 if (mxCanvas.is())
205 {
208 }
209}
210
211css::geometry::IntegerSize2D const & PresenterButton::GetSize()
212{
213 if (maButtonSize.Width < 0)
215 return maButtonSize;
216}
217
218//----- XPaintListener --------------------------------------------------------
219
220void SAL_CALL PresenterButton::windowPaint (const css::awt::PaintEvent& rEvent)
221{
223 if (!(mxWindow.is() && mxCanvas.is()))
224 return;
225
226 Reference<rendering::XBitmap> xBitmap;
228 xBitmap = mxMouseOverBitmap;
229 else
230 xBitmap = mxNormalBitmap;
231 if ( ! xBitmap.is())
232 return;
233
234 rendering::ViewState aViewState(
235 geometry::AffineMatrix2D(1,0,0, 0,1,0),
236 nullptr);
237 rendering::RenderState aRenderState(
238 geometry::AffineMatrix2D(1,0,0, 0,1,0),
239 PresenterGeometryHelper::CreatePolygon(rEvent.UpdateRect, mxCanvas->getDevice()),
240 Sequence<double>(4),
241 rendering::CompositeOperation::SOURCE);
242
243 mxCanvas->drawBitmap(xBitmap, aViewState, aRenderState);
244
245 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
246 if (xSpriteCanvas.is())
247 xSpriteCanvas->updateScreen(false);
248}
249
250//----- XMouseListener --------------------------------------------------------
251
252void SAL_CALL PresenterButton::mousePressed (const css::awt::MouseEvent&)
253{
256}
257
258void SAL_CALL PresenterButton::mouseReleased (const css::awt::MouseEvent&)
259{
261
263 {
264 OSL_ASSERT(mpPresenterController);
265 mpPresenterController->DispatchUnoCommand(msAction);
266
268 Invalidate();
269 }
270}
271
272void SAL_CALL PresenterButton::mouseEntered (const css::awt::MouseEvent&)
273{
276 Invalidate();
277}
278
279void SAL_CALL PresenterButton::mouseExited (const css::awt::MouseEvent&)
280{
283 Invalidate();
284}
285
286//----- lang::XEventListener --------------------------------------------------
287
288void SAL_CALL PresenterButton::disposing (const css::lang::EventObject& rEvent)
289{
290 if (rEvent.Source == mxWindow)
291 mxWindow = nullptr;
292}
293
294
295css::geometry::IntegerSize2D PresenterButton::CalculateButtonSize()
296{
297 if (mpFont && !mpFont->mxFont.is() && mxCanvas.is())
298 mpFont->PrepareFont(mxCanvas);
299 if (!mpFont || !mpFont->mxFont.is())
300 return geometry::IntegerSize2D(-1,-1);
301
302 geometry::RealSize2D aTextSize (PresenterCanvasHelper::GetTextSize(mpFont->mxFont,msText));
303
304 return geometry::IntegerSize2D (
305 sal_Int32(0.5 + aTextSize.Width + 2*gnHorizontalBorder),
306 sal_Int32(0.5 + aTextSize.Height + 2*gnVerticalBorder));
307}
308
310 const Reference<rendering::XCanvas>& rxCanvas,
311 const geometry::IntegerSize2D& rSize,
314 const SharedBitmapDescriptor& rpLeft,
315 const SharedBitmapDescriptor& rpCenter,
316 const SharedBitmapDescriptor& rpRight)
317{
318 if ( ! rxCanvas.is())
319 return;
320
321 const awt::Rectangle aBox(0,0, rSize.Width, rSize.Height);
322
324 rxCanvas,
325 aBox,
326 aBox,
327 GetBitmap(rpLeft, eMode),
328 GetBitmap(rpCenter, eMode),
329 GetBitmap(rpRight, eMode));
330
331 if (!rpFont || ! rpFont->mxFont.is())
332 return;
333
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());
338
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);
342
343 aRenderState.AffineTransform.m02 = (rSize.Width - aTextBBox.X2 + aTextBBox.X1)/2;
344 aRenderState.AffineTransform.m12 = (rSize.Height - aTextBBox.Y2 + aTextBBox.Y1)/2 - aTextBBox.Y1;
345
347 rxCanvas->drawTextLayout(
348 xLayout,
349 rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr),
350 aRenderState);
351}
352
354{
355 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
356}
357
358Reference<rendering::XBitmap> PresenterButton::GetBitmap (
361{
362 if (mpIcon)
363 return mpIcon->GetBitmap(eMode);
364 else
365 {
366 OSL_ASSERT(mpIcon);
367 return nullptr;
368 }
369}
370
372{
373 if ( ! mxCanvas.is())
374 return;
375 if ( ! mxCanvas->getDevice().is())
376 return;
377
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"));
382
384
385 if (maButtonSize.Height<=0 && maButtonSize.Width<= 0)
386 return;
387
388 mxNormalBitmap = mxCanvas->getDevice()->createCompatibleAlphaBitmap(maButtonSize);
389 Reference<rendering::XCanvas> xCanvas (mxNormalBitmap, UNO_QUERY);
390 if (xCanvas.is())
392 xCanvas,
394 mpFont,
396 pLeftBitmap,
397 pCenterBitmap,
398 pRightBitmap);
399
400 mxMouseOverBitmap = mxCanvas->getDevice()->createCompatibleAlphaBitmap(maButtonSize);
401 xCanvas.set(mxMouseOverBitmap, UNO_QUERY);
402 if (mpMouseOverFont && !mpMouseOverFont->mxFont.is() && mxCanvas.is())
403 mpMouseOverFont->PrepareFont(mxCanvas);
404 if (xCanvas.is())
406 xCanvas,
410 pLeftBitmap,
411 pCenterBitmap,
412 pRightBitmap);
413}
414
415Reference<beans::XPropertySet> PresenterButton::GetConfigurationProperties (
416 const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext,
417 const OUString& rsConfigurationName)
418{
419 PresenterConfigurationAccess aConfiguration (
420 rxComponentContext,
423 return Reference<beans::XPropertySet>(
425 Reference<container::XNameAccess>(
426 aConfiguration.GetConfigurationNode("PresenterScreenSettings/Buttons"),
427 UNO_QUERY),
428 [&rsConfigurationName](OUString const&, uno::Reference<beans::XPropertySet> const& xProps) -> bool
429 {
430 return PresenterConfigurationAccess::IsStringPropertyEqual(
431 rsConfigurationName, "Name", xProps);
432 }),
433 UNO_QUERY);
434}
435
437{
438 if (rBHelper.bDisposed || rBHelper.bInDispose)
439 {
440 throw lang::DisposedException (
441 "PresenterButton object has already been disposed",
442 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
443 }
444}
445
446} // end of namespace sdext::presenter
447
448/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const OUString msText
PresenterTheme::SharedFontDescriptor mpFont
rtl::Reference< PresenterController > mpPresenterController
SharedBitmapDescriptor mpIcon
OUString msAction
There is one bitmap for the normal state, one for a mouse over effect and one to show that a button h...
css::uno::Reference< css::rendering::XCanvas > mxCanvas
PresenterButton(const PresenterButton &)=delete
virtual void SAL_CALL mousePressed(const css::awt::MouseEvent &rEvent) override
virtual void SAL_CALL disposing() override
static css::uno::Reference< css::rendering::XBitmap > GetBitmap(const SharedBitmapDescriptor &mpIcon, const PresenterBitmapDescriptor::Mode eMode)
static ::rtl::Reference< PresenterButton > Create(const css::uno::Reference< css::uno::XComponentContext > &rxComponentContext, const ::rtl::Reference< PresenterController > &rpPresenterController, const std::shared_ptr< PresenterTheme > &rpTheme, const css::uno::Reference< css::awt::XWindow > &rxParentWindow, const css::uno::Reference< css::rendering::XCanvas > &rxParentCanvas, const OUString &rsConfigurationName)
css::uno::Reference< css::awt::XWindow > mxWindow
css::uno::Reference< css::rendering::XBitmap > mxMouseOverBitmap
css::geometry::RealPoint2D maCenter
::rtl::Reference< PresenterController > mpPresenterController
const PresenterTheme::SharedFontDescriptor mpFont
static css::uno::Reference< css::beans::XPropertySet > GetConfigurationProperties(const css::uno::Reference< css::uno::XComponentContext > &rxComponentContext, const OUString &rsConfigurationName)
css::uno::Reference< css::drawing::XPresenterHelper > mxPresenterHelper
void RenderButton(const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const css::geometry::IntegerSize2D &rSize, const PresenterTheme::SharedFontDescriptor &rFont, const PresenterBitmapDescriptor::Mode eMode, const SharedBitmapDescriptor &rpLeft, const SharedBitmapDescriptor &rpCenter, const SharedBitmapDescriptor &rpRight)
css::uno::Reference< css::rendering::XBitmap > mxNormalBitmap
void SetCenter(const css::geometry::RealPoint2D &rLocation)
virtual void SAL_CALL mouseEntered(const css::awt::MouseEvent &rEvent) override
std::shared_ptr< PresenterTheme > mpTheme
void SetCanvas(const css::uno::Reference< css::rendering::XCanvas > &rxParentCanvas, const css::uno::Reference< css::awt::XWindow > &rxParentWindow)
css::geometry::IntegerSize2D const & GetSize()
virtual void SAL_CALL mouseExited(const css::awt::MouseEvent &rEvent) override
virtual void SAL_CALL mouseReleased(const css::awt::MouseEvent &rEvent) override
virtual void SAL_CALL windowPaint(const css::awt::PaintEvent &rEvent) override
css::geometry::IntegerSize2D CalculateButtonSize()
PresenterBitmapDescriptor::Mode meState
const PresenterTheme::SharedFontDescriptor mpMouseOverFont
css::geometry::IntegerSize2D maButtonSize
static css::geometry::RealSize2D GetTextSize(const css::uno::Reference< css::rendering::XCanvasFont > &rxFont, const OUString &rsText)
static void SetDeviceColor(css::rendering::RenderState &rRenderState, const css::util::Color aColor)
This class gives access to the configuration.
css::uno::Any GetConfigurationNode(const OUString &rsPathToNode)
Return a configuration node below the root of the called object.
static css::uno::Any GetProperty(const css::uno::Reference< css::beans::XPropertySet > &rxProperties, const OUString &rsKey)
This method wraps a call to getPropertyValue() and returns an empty Any instead of throwing an except...
static css::uno::Any Find(const css::uno::Reference< css::container::XNameAccess > &rxContainer, const Predicate &rPredicate)
static css::uno::Reference< css::rendering::XPolyPolygon2D > CreatePolygon(const css::awt::Rectangle &rBox, const css::uno::Reference< css::rendering::XGraphicDevice > &rxDevice)
std::shared_ptr< FontDescriptor > SharedFontDescriptor
static void PaintHorizontalBitmapComposite(const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const css::awt::Rectangle &rRepaintBox, const css::awt::Rectangle &rBoundingBox, const css::uno::Reference< css::rendering::XBitmap > &rxLeftBitmap, const css::uno::Reference< css::rendering::XBitmap > &rxRepeatableCenterBitmap, const css::uno::Reference< css::rendering::XBitmap > &rxRightBitmap)
Reference< XSingleServiceFactory > xFactory
std::mutex m_aMutex
Mode eMode
::cppu::WeakComponentImplHelper< css::awt::XPaintListener, css::awt::XMouseListener > PresenterButtonInterfaceBase
const double gnHorizontalBorder(15)
std::shared_ptr< PresenterBitmapContainer::BitmapDescriptor > SharedBitmapDescriptor
const double gnVerticalBorder(5)