bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sdext / source / presenter / PresenterButton.cxx
blob26206dbc28ecad84d1c7646a433aab544852a4b8
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 <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(
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 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),
95 mpTheme(rpTheme),
96 mxWindow(),
97 mxCanvas(),
98 mxPresenterHelper(),
99 msText(rsText),
100 mpFont(rpFont),
101 mpMouseOverFont(rpMouseOverFont),
102 msAction(rsAction),
103 maCenter(),
104 maButtonSize(-1,-1),
105 meState(PresenterBitmapDescriptor::Normal),
106 mxNormalBitmap(),
107 mxMouseOverBitmap()
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",
118 rxComponentContext),
119 UNO_QUERY_THROW);
121 if (mxPresenterHelper.is())
122 mxWindow = mxPresenterHelper->createWindow(rxParentWindow,
123 false,
124 false,
125 false,
126 false);
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()
149 if (mxCanvas.is())
151 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
152 mxCanvas = nullptr;
153 if (xComponent.is())
154 xComponent->dispose();
157 if (mxWindow.is())
159 mxWindow->removeWindowListener(this);
160 mxWindow->removePaintListener(this);
161 mxWindow->removeMouseListener(this);
162 mxWindow->removeMouseMotionListener(this);
163 Reference<lang::XComponent> xComponent (mxWindow, UNO_QUERY);
164 mxWindow = nullptr;
165 if (xComponent.is())
166 xComponent->dispose();
170 void PresenterButton::SetCenter (const css::geometry::RealPoint2D& rLocation)
172 if (mxCanvas.is())
174 Invalidate();
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),
180 maButtonSize.Width,
181 maButtonSize.Height,
182 awt::PosSize::POSSIZE);
184 Invalidate();
186 else
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)
197 if (mxCanvas.is())
199 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
200 mxCanvas = nullptr;
201 if (xComponent.is())
202 xComponent->dispose();
205 if (!(mxPresenterHelper.is() && rxParentCanvas.is() && rxParentWindow.is()))
206 return;
208 mxCanvas = mxPresenterHelper->createSharedCanvas (
209 Reference<rendering::XSpriteCanvas>(rxParentCanvas, UNO_QUERY),
210 rxParentWindow,
211 rxParentCanvas,
212 rxParentWindow,
213 mxWindow);
214 if (mxCanvas.is())
216 SetupButtonBitmaps();
217 SetCenter(maCenter);
221 css::geometry::IntegerSize2D const & PresenterButton::GetSize()
223 if (maButtonSize.Width < 0)
224 CalculateButtonSize();
225 return maButtonSize;
228 //----- XWindowListener -------------------------------------------------------
230 void SAL_CALL PresenterButton::windowResized (const css::awt::WindowEvent&)
232 ThrowIfDisposed();
235 void SAL_CALL PresenterButton::windowMoved (const css::awt::WindowEvent&)
237 ThrowIfDisposed();
240 void SAL_CALL PresenterButton::windowShown (const css::lang::EventObject&)
242 ThrowIfDisposed();
245 void SAL_CALL PresenterButton::windowHidden (const css::lang::EventObject&)
247 ThrowIfDisposed();
250 //----- XPaintListener --------------------------------------------------------
252 void SAL_CALL PresenterButton::windowPaint (const css::awt::PaintEvent& rEvent)
254 ThrowIfDisposed();
255 if (!(mxWindow.is() && mxCanvas.is()))
256 return;
258 Reference<rendering::XBitmap> xBitmap;
259 if (meState == PresenterBitmapDescriptor::MouseOver)
260 xBitmap = mxMouseOverBitmap;
261 else
262 xBitmap = mxNormalBitmap;
263 if ( ! xBitmap.is())
264 return;
266 rendering::ViewState aViewState(
267 geometry::AffineMatrix2D(1,0,0, 0,1,0),
268 nullptr);
269 rendering::RenderState aRenderState(
270 geometry::AffineMatrix2D(1,0,0, 0,1,0),
271 PresenterGeometryHelper::CreatePolygon(rEvent.UpdateRect, mxCanvas->getDevice()),
272 Sequence<double>(4),
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&)
286 ThrowIfDisposed();
287 meState = PresenterBitmapDescriptor::ButtonDown;
290 void SAL_CALL PresenterButton::mouseReleased (const css::awt::MouseEvent&)
292 ThrowIfDisposed();
294 if (meState == PresenterBitmapDescriptor::ButtonDown)
296 OSL_ASSERT(mpPresenterController.get()!=nullptr);
297 mpPresenterController->DispatchUnoCommand(msAction);
299 meState = PresenterBitmapDescriptor::Normal;
300 Invalidate();
304 void SAL_CALL PresenterButton::mouseEntered (const css::awt::MouseEvent&)
306 ThrowIfDisposed();
307 meState = PresenterBitmapDescriptor::MouseOver;
308 Invalidate();
311 void SAL_CALL PresenterButton::mouseExited (const css::awt::MouseEvent&)
313 ThrowIfDisposed();
314 meState = PresenterBitmapDescriptor::Normal;
315 Invalidate();
318 //----- XMouseMotionListener --------------------------------------------------
320 void SAL_CALL PresenterButton::mouseMoved (const css::awt::MouseEvent&)
322 ThrowIfDisposed();
325 void SAL_CALL PresenterButton::mouseDragged (const css::awt::MouseEvent&)
327 ThrowIfDisposed();
330 //----- lang::XEventListener --------------------------------------------------
332 void SAL_CALL PresenterButton::disposing (const css::lang::EventObject& rEvent)
334 if (rEvent.Source == mxWindow)
335 mxWindow = nullptr;
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())
363 return;
365 const awt::Rectangle aBox(0,0, rSize.Width, rSize.Height);
367 PresenterUIPainter::PaintHorizontalBitmapComposite (
368 rxCanvas,
369 aBox,
370 aBox,
371 GetBitmap(rpLeft, eMode),
372 GetBitmap(rpCenter, eMode),
373 GetBitmap(rpRight, eMode));
375 if (rpFont.get()==nullptr || ! rpFont->mxFont.is())
376 return;
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(
392 xLayout,
393 rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), nullptr),
394 aRenderState);
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);
408 else
410 OSL_ASSERT(mpIcon.get()!=nullptr);
411 return nullptr;
415 void PresenterButton::SetupButtonBitmaps()
417 if ( ! mxCanvas.is())
418 return;
419 if ( ! mxCanvas->getDevice().is())
420 return;
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)
430 return;
432 mxNormalBitmap = mxCanvas->getDevice()->createCompatibleAlphaBitmap(maButtonSize);
433 Reference<rendering::XCanvas> xCanvas (mxNormalBitmap, UNO_QUERY);
434 if (xCanvas.is())
435 RenderButton(
436 xCanvas,
437 maButtonSize,
438 mpFont,
439 PresenterBitmapDescriptor::Normal,
440 pLeftBitmap,
441 pCenterBitmap,
442 pRightBitmap);
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);
448 if (xCanvas.is())
449 RenderButton(
450 xCanvas,
451 maButtonSize,
452 mpMouseOverFont,
453 PresenterBitmapDescriptor::MouseOver,
454 pLeftBitmap,
455 pCenterBitmap,
456 pRightBitmap);
459 Reference<beans::XPropertySet> PresenterButton::GetConfigurationProperties (
460 const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext,
461 const OUString& rsConfgurationName)
463 PresenterConfigurationAccess aConfiguration (
464 rxComponentContext,
465 PresenterConfigurationAccess::msPresenterScreenRootName,
466 PresenterConfigurationAccess::READ_ONLY);
467 return Reference<beans::XPropertySet>(
468 PresenterConfigurationAccess::Find (
469 Reference<container::XNameAccess>(
470 aConfiguration.GetConfigurationNode("PresenterScreenSettings/Buttons"),
471 UNO_QUERY),
472 [&rsConfgurationName](OUString const&, uno::Reference<beans::XPropertySet> const& xProps) -> bool
474 return PresenterConfigurationAccess::IsStringPropertyEqual(
475 rsConfgurationName, "Name", xProps);
477 UNO_QUERY);
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: */