LibreOffice Module sdext (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"
22 #include "PresenterController.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>
31 
32 using namespace ::com::sun::star;
33 using namespace ::com::sun::star::uno;
34 
35 namespace sdext::presenter {
36 
37 const static double gnHorizontalBorder (15);
38 const static double gnVerticalBorder (5);
39 
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)
47 {
49  rxComponentContext,
50  rsConfigurationName));
51  if (xProperties.is())
52  {
53  OUString sText;
54  OUString sAction;
55  PresenterConfigurationAccess::GetProperty(xProperties, "Text") >>= sText;
56  PresenterConfigurationAccess::GetProperty(xProperties, "Action") >>= sAction;
57 
59  if (rpTheme != nullptr)
60  pFont = rpTheme->GetFont("ButtonFont");
61 
63  if (rpTheme != nullptr)
64  pMouseOverFont = rpTheme->GetFont("ButtonMouseOverFont");
65 
67  new PresenterButton(
68  rxComponentContext,
69  rpPresenterController,
70  rpTheme,
71  rxParentWindow,
72  pFont,
73  pMouseOverFont,
74  sText,
75  sAction));
76  pButton->SetCanvas(rxParentCanvas, rxParentWindow);
77  return pButton;
78  }
79  else
80  return nullptr;
81 }
82 
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,
89  const PresenterTheme::SharedFontDescriptor& rpMouseOverFont,
90  const OUString& rsText,
91  const OUString& rsAction)
93  mpPresenterController(rpPresenterController),
94  mpTheme(rpTheme),
95  mxWindow(),
96  mxCanvas(),
98  msText(rsText),
99  mpFont(rpFont),
100  mpMouseOverFont(rpMouseOverFont),
101  msAction(rsAction),
102  maCenter(),
103  maButtonSize(-1,-1),
105  mxNormalBitmap(),
106  mxMouseOverBitmap()
107 {
108  try
109  {
110  Reference<lang::XMultiComponentFactory> xFactory (rxComponentContext->getServiceManager());
111  if ( ! xFactory.is())
112  throw RuntimeException();
113 
114  mxPresenterHelper.set(
115  xFactory->createInstanceWithContext(
116  "com.sun.star.comp.Draw.PresenterHelper",
117  rxComponentContext),
118  UNO_QUERY_THROW);
119 
120  if (mxPresenterHelper.is())
121  mxWindow = mxPresenterHelper->createWindow(rxParentWindow,
122  false,
123  false,
124  false,
125  false);
126 
127  // Make the background transparent.
128  Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY_THROW);
129  xPeer->setBackground(0xff000000);
130 
131  mxWindow->setVisible(true);
132  mxWindow->addPaintListener(this);
133  mxWindow->addMouseListener(this);
134  }
135  catch (RuntimeException&)
136  {
137  }
138 }
139 
141 {
142 }
143 
145 {
146  if (mxCanvas.is())
147  {
149  mxCanvas = nullptr;
150  if (xComponent.is())
151  xComponent->dispose();
152  }
153 
154  if (mxWindow.is())
155  {
156  mxWindow->removePaintListener(this);
157  mxWindow->removeMouseListener(this);
159  mxWindow = nullptr;
160  if (xComponent.is())
161  xComponent->dispose();
162  }
163 }
164 
165 void PresenterButton::SetCenter (const css::geometry::RealPoint2D& rLocation)
166 {
167  if (mxCanvas.is())
168  {
169  Invalidate();
170 
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),
175  maButtonSize.Width,
176  maButtonSize.Height,
177  awt::PosSize::POSSIZE);
178 
179  Invalidate();
180  }
181  else
182  {
183  // The button can not be painted but we can at least store the new center.
184  maCenter = rLocation;
185  }
186 }
187 
189  const css::uno::Reference<css::rendering::XCanvas>& rxParentCanvas,
190  const css::uno::Reference<css::awt::XWindow>& rxParentWindow)
191 {
192  if (mxCanvas.is())
193  {
195  mxCanvas = nullptr;
196  if (xComponent.is())
197  xComponent->dispose();
198  }
199 
200  if (!(mxPresenterHelper.is() && rxParentCanvas.is() && rxParentWindow.is()))
201  return;
202 
203  mxCanvas = mxPresenterHelper->createSharedCanvas (
204  Reference<rendering::XSpriteCanvas>(rxParentCanvas, UNO_QUERY),
205  rxParentWindow,
206  rxParentCanvas,
207  rxParentWindow,
208  mxWindow);
209  if (mxCanvas.is())
210  {
213  }
214 }
215 
216 css::geometry::IntegerSize2D const & PresenterButton::GetSize()
217 {
218  if (maButtonSize.Width < 0)
220  return maButtonSize;
221 }
222 
223 //----- XPaintListener --------------------------------------------------------
224 
225 void SAL_CALL PresenterButton::windowPaint (const css::awt::PaintEvent& rEvent)
226 {
227  ThrowIfDisposed();
228  if (!(mxWindow.is() && mxCanvas.is()))
229  return;
230 
231  Reference<rendering::XBitmap> xBitmap;
233  xBitmap = mxMouseOverBitmap;
234  else
235  xBitmap = mxNormalBitmap;
236  if ( ! xBitmap.is())
237  return;
238 
239  rendering::ViewState aViewState(
240  geometry::AffineMatrix2D(1,0,0, 0,1,0),
241  nullptr);
242  rendering::RenderState aRenderState(
243  geometry::AffineMatrix2D(1,0,0, 0,1,0),
244  PresenterGeometryHelper::CreatePolygon(rEvent.UpdateRect, mxCanvas->getDevice()),
245  Sequence<double>(4),
246  rendering::CompositeOperation::SOURCE);
247 
248  mxCanvas->drawBitmap(xBitmap, aViewState, aRenderState);
249 
250  Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
251  if (xSpriteCanvas.is())
252  xSpriteCanvas->updateScreen(false);
253 }
254 
255 //----- XMouseListener --------------------------------------------------------
256 
257 void SAL_CALL PresenterButton::mousePressed (const css::awt::MouseEvent&)
258 {
259  ThrowIfDisposed();
261 }
262 
263 void SAL_CALL PresenterButton::mouseReleased (const css::awt::MouseEvent&)
264 {
265  ThrowIfDisposed();
266 
268  {
269  OSL_ASSERT(mpPresenterController.get()!=nullptr);
270  mpPresenterController->DispatchUnoCommand(msAction);
271 
273  Invalidate();
274  }
275 }
276 
277 void SAL_CALL PresenterButton::mouseEntered (const css::awt::MouseEvent&)
278 {
279  ThrowIfDisposed();
281  Invalidate();
282 }
283 
284 void SAL_CALL PresenterButton::mouseExited (const css::awt::MouseEvent&)
285 {
286  ThrowIfDisposed();
288  Invalidate();
289 }
290 
291 //----- lang::XEventListener --------------------------------------------------
292 
293 void SAL_CALL PresenterButton::disposing (const css::lang::EventObject& rEvent)
294 {
295  if (rEvent.Source == mxWindow)
296  mxWindow = nullptr;
297 }
298 
299 
300 css::geometry::IntegerSize2D PresenterButton::CalculateButtonSize()
301 {
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);
306 
307  geometry::RealSize2D aTextSize (PresenterCanvasHelper::GetTextSize(mpFont->mxFont,msText));
308 
309  return geometry::IntegerSize2D (
310  sal_Int32(0.5 + aTextSize.Width + 2*gnHorizontalBorder),
311  sal_Int32(0.5 + aTextSize.Height + 2*gnVerticalBorder));
312 }
313 
315  const Reference<rendering::XCanvas>& rxCanvas,
316  const geometry::IntegerSize2D& rSize,
319  const SharedBitmapDescriptor& rpLeft,
320  const SharedBitmapDescriptor& rpCenter,
321  const SharedBitmapDescriptor& rpRight)
322 {
323  if ( ! rxCanvas.is())
324  return;
325 
326  const awt::Rectangle aBox(0,0, rSize.Width, rSize.Height);
327 
329  rxCanvas,
330  aBox,
331  aBox,
332  GetBitmap(rpLeft, eMode),
333  GetBitmap(rpCenter, eMode),
334  GetBitmap(rpRight, eMode));
335 
336  if (rpFont.get()==nullptr || ! rpFont->mxFont.is())
337  return;
338 
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());
343 
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);
347 
348  aRenderState.AffineTransform.m02 = (rSize.Width - aTextBBox.X2 + aTextBBox.X1)/2;
349  aRenderState.AffineTransform.m12 = (rSize.Height - aTextBBox.Y2 + aTextBBox.Y1)/2 - aTextBBox.Y1;
350 
352  rxCanvas->drawTextLayout(
353  xLayout,
354  rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr),
355  aRenderState);
356 }
357 
359 {
360  mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
361 }
362 
363 Reference<rendering::XBitmap> PresenterButton::GetBitmap (
366 {
367  if (mpIcon.get() != nullptr)
368  return mpIcon->GetBitmap(eMode);
369  else
370  {
371  OSL_ASSERT(mpIcon.get()!=nullptr);
372  return nullptr;
373  }
374 }
375 
377 {
378  if ( ! mxCanvas.is())
379  return;
380  if ( ! mxCanvas->getDevice().is())
381  return;
382 
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"));
387 
389 
390  if (maButtonSize.Height<=0 && maButtonSize.Width<= 0)
391  return;
392 
393  mxNormalBitmap = mxCanvas->getDevice()->createCompatibleAlphaBitmap(maButtonSize);
394  Reference<rendering::XCanvas> xCanvas (mxNormalBitmap, UNO_QUERY);
395  if (xCanvas.is())
396  RenderButton(
397  xCanvas,
398  maButtonSize,
399  mpFont,
401  pLeftBitmap,
402  pCenterBitmap,
403  pRightBitmap);
404 
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);
409  if (xCanvas.is())
410  RenderButton(
411  xCanvas,
412  maButtonSize,
415  pLeftBitmap,
416  pCenterBitmap,
417  pRightBitmap);
418 }
419 
421  const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext,
422  const OUString& rsConfgurationName)
423 {
424  PresenterConfigurationAccess aConfiguration (
425  rxComponentContext,
431  aConfiguration.GetConfigurationNode("PresenterScreenSettings/Buttons"),
432  UNO_QUERY),
433  [&rsConfgurationName](OUString const&, uno::Reference<beans::XPropertySet> const& xProps) -> bool
434  {
436  rsConfgurationName, "Name", xProps);
437  }),
438  UNO_QUERY);
439 }
440 
442 {
443  if (rBHelper.bDisposed || rBHelper.bInDispose)
444  {
445  throw lang::DisposedException (
446  "PresenterButton object has already been disposed",
447  const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
448  }
449 }
450 
451 } // end of namespace sdext::presenter
452 
453 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::rendering::XBitmap > mxNormalBitmap
Reference< rendering::XCanvas > mxCanvas
There is one bitmap for the normal state, one for a mouse over effect and one to show that a button h...
static const double gnHorizontalBorder(15)
std::shared_ptr< FontDescriptor > SharedFontDescriptor
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...
osl::Mutex m_aMutex
const PresenterTheme::SharedFontDescriptor mpFont
css::uno::Reference< css::rendering::XBitmap > mxMouseOverBitmap
PresenterButton(const PresenterButton &)=delete
css::uno::Reference< css::rendering::XCanvas > mxCanvas
::rtl::Reference< PresenterController > mpPresenterController
::cppu::WeakComponentImplHelper< css::awt::XPaintListener, css::awt::XMouseListener > PresenterButtonInterfaceBase
const PresenterTheme::SharedFontDescriptor mpMouseOverFont
PresenterBitmapDescriptor::Mode meState
css::geometry::IntegerSize2D maButtonSize
SharedBitmapDescriptor mpIcon
virtual void SAL_CALL windowPaint(const css::awt::PaintEvent &rEvent) override
css::uno::Reference< css::drawing::XPresenterHelper > mxPresenterHelper
std::shared_ptr< PresenterBitmapContainer::BitmapDescriptor > SharedBitmapDescriptor
Reference< drawing::XPresenterHelper > mxPresenterHelper
This class gives access to the configuration.
virtual void SAL_CALL mouseExited(const css::awt::MouseEvent &rEvent) override
void SetCenter(const css::geometry::RealPoint2D &rLocation)
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)
virtual void SAL_CALL disposing() override
css::uno::Reference< css::lang::XComponent > xComponent
static const double gnVerticalBorder(5)
static css::uno::Reference< css::rendering::XBitmap > GetBitmap(const SharedBitmapDescriptor &mpIcon, const PresenterBitmapDescriptor::Mode eMode)
static css::uno::Any Find(const css::uno::Reference< css::container::XNameAccess > &rxContainer, const Predicate &rPredicate)
css::geometry::IntegerSize2D const & GetSize()
css::geometry::RealPoint2D maCenter
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::Any GetConfigurationNode(const OUString &rsPathToNode)
Return a configuration node below the root of the called object.
void SetCanvas(const css::uno::Reference< css::rendering::XCanvas > &rxParentCanvas, const css::uno::Reference< css::awt::XWindow > &rxParentWindow)
static css::uno::Reference< css::rendering::XPolyPolygon2D > CreatePolygon(const css::awt::Rectangle &rBox, const css::uno::Reference< css::rendering::XGraphicDevice > &rxDevice)
virtual void SAL_CALL mousePressed(const css::awt::MouseEvent &rEvent) override
css::geometry::IntegerSize2D CalculateButtonSize()
PresenterTheme::SharedFontDescriptor mpFont
rtl::Reference< PresenterController > mpPresenterController
const OUString msText
OUString msAction
virtual void SAL_CALL mouseReleased(const css::awt::MouseEvent &rEvent) override
css::uno::Reference< css::awt::XWindow > mxWindow
static void SetDeviceColor(css::rendering::RenderState &rRenderState, const css::util::Color aColor)
static css::uno::Reference< css::beans::XPropertySet > GetConfigurationProperties(const css::uno::Reference< css::uno::XComponentContext > &rxComponentContext, const OUString &rsConfgurationName)
static css::geometry::RealSize2D GetTextSize(const css::uno::Reference< css::rendering::XCanvasFont > &rxFont, const OUString &rsText)
static bool IsStringPropertyEqual(const OUString &rsValue, const OUString &rsPropertyName, const css::uno::Reference< css::beans::XPropertySet > &rxNode)
Reference< XSingleServiceFactory > xFactory
virtual void SAL_CALL mouseEntered(const css::awt::MouseEvent &rEvent) override
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)
std::shared_ptr< PresenterTheme > mpTheme