Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sd / source / console / PresenterButton.cxx
blobd0fa61a09c940bfd9dd06c1eefa17a3568039d04
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
31 #include <utility>
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(
50 rxComponentContext,
51 rsConfigurationName));
52 if (xProperties.is())
54 OUString sText;
55 OUString sAction;
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 (
68 new PresenterButton(
69 rxComponentContext,
70 rpPresenterController,
71 rpTheme,
72 rxParentWindow,
73 pFont,
74 pMouseOverFont,
75 sText,
76 sAction));
77 pButton->SetCanvas(rxParentCanvas, rxParentWindow);
78 return pButton;
80 else
81 return nullptr;
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,
91 OUString sText,
92 OUString sAction)
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)),
100 maButtonSize(-1,-1),
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",
112 rxComponentContext),
113 UNO_QUERY_THROW);
115 if (mxPresenterHelper.is())
116 mxWindow = mxPresenterHelper->createWindow(rxParentWindow,
117 false,
118 false,
119 false,
120 false);
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()
141 if (mxCanvas.is())
143 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
144 mxCanvas = nullptr;
145 if (xComponent.is())
146 xComponent->dispose();
149 if (mxWindow.is())
151 mxWindow->removePaintListener(this);
152 mxWindow->removeMouseListener(this);
153 Reference<lang::XComponent> xComponent = mxWindow;
154 mxWindow = nullptr;
155 if (xComponent.is())
156 xComponent->dispose();
160 void PresenterButton::SetCenter (const css::geometry::RealPoint2D& rLocation)
162 if (mxCanvas.is())
164 Invalidate();
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);
174 Invalidate();
176 else
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)
187 if (mxCanvas.is())
189 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
190 mxCanvas = nullptr;
191 if (xComponent.is())
192 xComponent->dispose();
195 if (!(mxPresenterHelper.is() && rxParentCanvas.is() && rxParentWindow.is()))
196 return;
198 mxCanvas = mxPresenterHelper->createSharedCanvas (
199 Reference<rendering::XSpriteCanvas>(rxParentCanvas, UNO_QUERY),
200 rxParentWindow,
201 rxParentCanvas,
202 rxParentWindow,
203 mxWindow);
204 if (mxCanvas.is())
206 SetupButtonBitmaps();
207 SetCenter(maCenter);
211 css::geometry::IntegerSize2D const & PresenterButton::GetSize()
213 if (maButtonSize.Width < 0)
214 CalculateButtonSize();
215 return maButtonSize;
218 //----- XPaintListener --------------------------------------------------------
220 void SAL_CALL PresenterButton::windowPaint (const css::awt::PaintEvent& rEvent)
222 ThrowIfDisposed();
223 if (!(mxWindow.is() && mxCanvas.is()))
224 return;
226 Reference<rendering::XBitmap> xBitmap;
227 if (meState == PresenterBitmapDescriptor::MouseOver)
228 xBitmap = mxMouseOverBitmap;
229 else
230 xBitmap = mxNormalBitmap;
231 if ( ! xBitmap.is())
232 return;
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);
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&)
254 ThrowIfDisposed();
255 meState = PresenterBitmapDescriptor::ButtonDown;
258 void SAL_CALL PresenterButton::mouseReleased (const css::awt::MouseEvent&)
260 ThrowIfDisposed();
262 if (meState == PresenterBitmapDescriptor::ButtonDown)
264 OSL_ASSERT(mpPresenterController);
265 mpPresenterController->DispatchUnoCommand(msAction);
267 meState = PresenterBitmapDescriptor::Normal;
268 Invalidate();
272 void SAL_CALL PresenterButton::mouseEntered (const css::awt::MouseEvent&)
274 ThrowIfDisposed();
275 meState = PresenterBitmapDescriptor::MouseOver;
276 Invalidate();
279 void SAL_CALL PresenterButton::mouseExited (const css::awt::MouseEvent&)
281 ThrowIfDisposed();
282 meState = PresenterBitmapDescriptor::Normal;
283 Invalidate();
286 //----- lang::XEventListener --------------------------------------------------
288 void SAL_CALL PresenterButton::disposing (const css::lang::EventObject& rEvent)
290 if (rEvent.Source == mxWindow)
291 mxWindow = nullptr;
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())
319 return;
321 const awt::Rectangle aBox(0,0, rSize.Width, rSize.Height);
323 PresenterUIPainter::PaintHorizontalBitmapComposite (
324 rxCanvas,
325 aBox,
326 aBox,
327 GetBitmap(rpLeft, eMode),
328 GetBitmap(rpCenter, eMode),
329 GetBitmap(rpRight, eMode));
331 if (!rpFont || ! rpFont->mxFont.is())
332 return;
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(
348 xLayout,
349 rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr),
350 aRenderState);
353 void PresenterButton::Invalidate()
355 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
358 Reference<rendering::XBitmap> PresenterButton::GetBitmap (
359 const SharedBitmapDescriptor& mpIcon,
360 const PresenterBitmapDescriptor::Mode eMode)
362 if (mpIcon)
363 return mpIcon->GetBitmap(eMode);
364 else
366 OSL_ASSERT(mpIcon);
367 return nullptr;
371 void PresenterButton::SetupButtonBitmaps()
373 if ( ! mxCanvas.is())
374 return;
375 if ( ! mxCanvas->getDevice().is())
376 return;
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)
386 return;
388 mxNormalBitmap = mxCanvas->getDevice()->createCompatibleAlphaBitmap(maButtonSize);
389 Reference<rendering::XCanvas> xCanvas (mxNormalBitmap, UNO_QUERY);
390 if (xCanvas.is())
391 RenderButton(
392 xCanvas,
393 maButtonSize,
394 mpFont,
395 PresenterBitmapDescriptor::Normal,
396 pLeftBitmap,
397 pCenterBitmap,
398 pRightBitmap);
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())
405 RenderButton(
406 xCanvas,
407 maButtonSize,
408 mpMouseOverFont,
409 PresenterBitmapDescriptor::MouseOver,
410 pLeftBitmap,
411 pCenterBitmap,
412 pRightBitmap);
415 Reference<beans::XPropertySet> PresenterButton::GetConfigurationProperties (
416 const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext,
417 const OUString& rsConfigurationName)
419 PresenterConfigurationAccess aConfiguration (
420 rxComponentContext,
421 PresenterConfigurationAccess::msPresenterScreenRootName,
422 PresenterConfigurationAccess::READ_ONLY);
423 return Reference<beans::XPropertySet>(
424 PresenterConfigurationAccess::Find (
425 Reference<container::XNameAccess>(
426 aConfiguration.GetConfigurationNode("PresenterScreenSettings/Buttons"),
427 UNO_QUERY),
428 [&rsConfigurationName](OUString const&, uno::Reference<beans::XPropertySet> const& xProps) -> bool
430 return PresenterConfigurationAccess::IsStringPropertyEqual(
431 rsConfigurationName, "Name", xProps);
433 UNO_QUERY);
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: */