Line data Source code
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 "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>
32 : #include <boost/bind.hpp>
33 :
34 : using namespace ::com::sun::star;
35 : using namespace ::com::sun::star::uno;
36 :
37 : namespace sdext { namespace presenter {
38 :
39 : const static double gnHorizontalBorder (15);
40 : const static double gnVerticalBorder (5);
41 :
42 0 : ::rtl::Reference<PresenterButton> PresenterButton::Create (
43 : const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext,
44 : const ::rtl::Reference<PresenterController>& rpPresenterController,
45 : const ::boost::shared_ptr<PresenterTheme>& rpTheme,
46 : const css::uno::Reference<css::awt::XWindow>& rxParentWindow,
47 : const css::uno::Reference<css::rendering::XCanvas>& rxParentCanvas,
48 : const OUString& rsConfigurationName)
49 : {
50 : Reference<beans::XPropertySet> xProperties (GetConfigurationProperties(
51 : rxComponentContext,
52 0 : rsConfigurationName));
53 0 : if (xProperties.is())
54 : {
55 0 : OUString sText;
56 0 : OUString sAction;
57 0 : PresenterConfigurationAccess::GetProperty(xProperties, "Text") >>= sText;
58 0 : PresenterConfigurationAccess::GetProperty(xProperties, "Action") >>= sAction;
59 :
60 0 : PresenterTheme::SharedFontDescriptor pFont;
61 0 : if (rpTheme.get() != NULL)
62 0 : pFont = rpTheme->GetFont("ButtonFont");
63 :
64 0 : PresenterTheme::SharedFontDescriptor pMouseOverFont;
65 0 : if (rpTheme.get() != NULL)
66 0 : pMouseOverFont = rpTheme->GetFont("ButtonMouseOverFont");
67 :
68 : rtl::Reference<PresenterButton> pButton (
69 : new PresenterButton(
70 : rxComponentContext,
71 : rpPresenterController,
72 : rpTheme,
73 : rxParentWindow,
74 : pFont,
75 : pMouseOverFont,
76 : sText,
77 0 : sAction));
78 0 : pButton->SetCanvas(rxParentCanvas, rxParentWindow);
79 0 : return pButton;
80 : }
81 : else
82 0 : return NULL;
83 : }
84 :
85 0 : PresenterButton::PresenterButton (
86 : const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext,
87 : const ::rtl::Reference<PresenterController>& rpPresenterController,
88 : const ::boost::shared_ptr<PresenterTheme>& rpTheme,
89 : const css::uno::Reference<css::awt::XWindow>& rxParentWindow,
90 : const PresenterTheme::SharedFontDescriptor& rpFont,
91 : const PresenterTheme::SharedFontDescriptor& rpMouseOverFont,
92 : const OUString& rsText,
93 : const OUString& rsAction)
94 : : PresenterButtonInterfaceBase(m_aMutex),
95 : mpPresenterController(rpPresenterController),
96 : mpTheme(rpTheme),
97 : mxWindow(),
98 : mxCanvas(),
99 : mxPresenterHelper(),
100 : msText(rsText),
101 : mpFont(rpFont),
102 : mpMouseOverFont(rpMouseOverFont),
103 : msAction(rsAction),
104 : maCenter(),
105 : maButtonSize(-1,-1),
106 : meState(PresenterBitmapDescriptor::Normal),
107 : mxNormalBitmap(),
108 0 : mxMouseOverBitmap()
109 : {
110 : try
111 : {
112 0 : Reference<lang::XMultiComponentFactory> xFactory (rxComponentContext->getServiceManager());
113 0 : if ( ! xFactory.is())
114 0 : throw RuntimeException();
115 :
116 0 : mxPresenterHelper = Reference<drawing::XPresenterHelper>(
117 0 : xFactory->createInstanceWithContext(
118 : OUString("com.sun.star.comp.Draw.PresenterHelper"),
119 0 : rxComponentContext),
120 0 : UNO_QUERY_THROW);
121 :
122 0 : if (mxPresenterHelper.is())
123 0 : mxWindow = mxPresenterHelper->createWindow(rxParentWindow,
124 : sal_False,
125 : sal_False,
126 : sal_False,
127 0 : sal_False);
128 :
129 : // Make the background transparent.
130 0 : Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY_THROW);
131 0 : if (xPeer.is())
132 : {
133 0 : xPeer->setBackground(0xff000000);
134 : }
135 :
136 0 : mxWindow->setVisible(sal_True);
137 0 : mxWindow->addWindowListener(this);
138 0 : mxWindow->addPaintListener(this);
139 0 : mxWindow->addMouseListener(this);
140 0 : mxWindow->addMouseMotionListener(this);
141 : }
142 0 : catch (RuntimeException&)
143 : {
144 : }
145 0 : }
146 :
147 0 : PresenterButton::~PresenterButton()
148 : {
149 0 : }
150 :
151 0 : void SAL_CALL PresenterButton::disposing()
152 : {
153 0 : if (mxCanvas.is())
154 : {
155 0 : Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
156 0 : mxCanvas = NULL;
157 0 : if (xComponent.is())
158 0 : xComponent->dispose();
159 : }
160 :
161 0 : if (mxWindow.is())
162 : {
163 0 : mxWindow->removeWindowListener(this);
164 0 : mxWindow->removePaintListener(this);
165 0 : mxWindow->removeMouseListener(this);
166 0 : mxWindow->removeMouseMotionListener(this);
167 0 : Reference<lang::XComponent> xComponent (mxWindow, UNO_QUERY);
168 0 : mxWindow = NULL;
169 0 : if (xComponent.is())
170 0 : xComponent->dispose();
171 : }
172 0 : }
173 :
174 0 : void PresenterButton::SetCenter (const css::geometry::RealPoint2D& rLocation)
175 : {
176 0 : if (mxCanvas.is())
177 : {
178 0 : Invalidate();
179 :
180 0 : maCenter = rLocation;
181 0 : mxWindow->setPosSize(
182 0 : sal_Int32(0.5 + maCenter.X - maButtonSize.Width/2),
183 0 : sal_Int32(0.5 + maCenter.Y - maButtonSize.Height/2),
184 : maButtonSize.Width,
185 : maButtonSize.Height,
186 0 : awt::PosSize::POSSIZE);
187 :
188 0 : Invalidate();
189 : }
190 : else
191 : {
192 : // The button can not be painted but we can at least store the new center.
193 0 : maCenter = rLocation;
194 : }
195 0 : }
196 :
197 0 : void PresenterButton::SetCanvas (
198 : const css::uno::Reference<css::rendering::XCanvas>& rxParentCanvas,
199 : const css::uno::Reference<css::awt::XWindow>& rxParentWindow)
200 : {
201 0 : if (mxCanvas.is())
202 : {
203 0 : Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
204 0 : mxCanvas = NULL;
205 0 : if (xComponent.is())
206 0 : xComponent->dispose();
207 : }
208 :
209 0 : if (mxPresenterHelper.is() && rxParentCanvas.is() && rxParentWindow.is())
210 : {
211 0 : mxCanvas = mxPresenterHelper->createSharedCanvas (
212 : Reference<rendering::XSpriteCanvas>(rxParentCanvas, UNO_QUERY),
213 : rxParentWindow,
214 : rxParentCanvas,
215 : rxParentWindow,
216 0 : mxWindow);
217 0 : if (mxCanvas.is())
218 : {
219 0 : SetupButtonBitmaps();
220 0 : SetCenter(maCenter);
221 : }
222 : }
223 0 : }
224 :
225 0 : css::geometry::IntegerSize2D PresenterButton::GetSize()
226 : {
227 0 : if (maButtonSize.Width < 0)
228 0 : CalculateButtonSize();
229 0 : return maButtonSize;
230 : }
231 :
232 : //----- XWindowListener -------------------------------------------------------
233 :
234 0 : void SAL_CALL PresenterButton::windowResized (const css::awt::WindowEvent& rEvent)
235 : throw (css::uno::RuntimeException, std::exception)
236 : {
237 : (void)rEvent;
238 0 : ThrowIfDisposed();
239 0 : }
240 :
241 0 : void SAL_CALL PresenterButton::windowMoved (const css::awt::WindowEvent& rEvent)
242 : throw (css::uno::RuntimeException, std::exception)
243 : {
244 : (void)rEvent;
245 0 : ThrowIfDisposed();
246 0 : }
247 :
248 0 : void SAL_CALL PresenterButton::windowShown (const css::lang::EventObject& rEvent)
249 : throw (css::uno::RuntimeException, std::exception)
250 : {
251 : (void)rEvent;
252 0 : ThrowIfDisposed();
253 0 : }
254 :
255 0 : void SAL_CALL PresenterButton::windowHidden (const css::lang::EventObject& rEvent)
256 : throw (css::uno::RuntimeException, std::exception)
257 : {
258 : (void)rEvent;
259 0 : ThrowIfDisposed();
260 0 : }
261 :
262 : //----- XPaintListener --------------------------------------------------------
263 :
264 0 : void SAL_CALL PresenterButton::windowPaint (const css::awt::PaintEvent& rEvent)
265 : throw (css::uno::RuntimeException, std::exception)
266 : {
267 0 : ThrowIfDisposed();
268 0 : if (mxWindow.is() && mxCanvas.is())
269 : {
270 0 : Reference<rendering::XBitmap> xBitmap;
271 0 : if (meState == PresenterBitmapDescriptor::MouseOver)
272 0 : xBitmap = mxMouseOverBitmap;
273 : else
274 0 : xBitmap = mxNormalBitmap;
275 0 : if ( ! xBitmap.is())
276 0 : return;
277 :
278 : rendering::ViewState aViewState(
279 : geometry::AffineMatrix2D(1,0,0, 0,1,0),
280 0 : NULL);
281 : rendering::RenderState aRenderState(
282 : geometry::AffineMatrix2D(1,0,0, 0,1,0),
283 0 : PresenterGeometryHelper::CreatePolygon(rEvent.UpdateRect, mxCanvas->getDevice()),
284 : Sequence<double>(4),
285 0 : rendering::CompositeOperation::SOURCE);
286 :
287 0 : mxCanvas->drawBitmap(xBitmap, aViewState, aRenderState);
288 :
289 0 : Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
290 0 : if (xSpriteCanvas.is())
291 0 : xSpriteCanvas->updateScreen(sal_False);
292 : }
293 : }
294 :
295 : //----- XMouseListener --------------------------------------------------------
296 :
297 0 : void SAL_CALL PresenterButton::mousePressed (const css::awt::MouseEvent& rEvent)
298 : throw(css::uno::RuntimeException, std::exception)
299 : {
300 : (void)rEvent;
301 0 : ThrowIfDisposed();
302 0 : meState = PresenterBitmapDescriptor::ButtonDown;
303 0 : }
304 :
305 0 : void SAL_CALL PresenterButton::mouseReleased (const css::awt::MouseEvent& rEvent)
306 : throw(css::uno::RuntimeException, std::exception)
307 : {
308 : (void)rEvent;
309 0 : ThrowIfDisposed();
310 :
311 0 : if (meState == PresenterBitmapDescriptor::ButtonDown)
312 : {
313 : OSL_ASSERT(mpPresenterController.get()!=NULL);
314 0 : mpPresenterController->DispatchUnoCommand(msAction);
315 :
316 0 : meState = PresenterBitmapDescriptor::Normal;
317 0 : Invalidate();
318 : }
319 0 : }
320 :
321 0 : void SAL_CALL PresenterButton::mouseEntered (const css::awt::MouseEvent& rEvent)
322 : throw(css::uno::RuntimeException, std::exception)
323 : {
324 : (void)rEvent;
325 0 : ThrowIfDisposed();
326 0 : meState = PresenterBitmapDescriptor::MouseOver;
327 0 : Invalidate();
328 0 : }
329 :
330 0 : void SAL_CALL PresenterButton::mouseExited (const css::awt::MouseEvent& rEvent)
331 : throw(css::uno::RuntimeException, std::exception)
332 : {
333 : (void)rEvent;
334 0 : ThrowIfDisposed();
335 0 : meState = PresenterBitmapDescriptor::Normal;
336 0 : Invalidate();
337 0 : }
338 :
339 : //----- XMouseMotionListener --------------------------------------------------
340 :
341 0 : void SAL_CALL PresenterButton::mouseMoved (const css::awt::MouseEvent& rEvent)
342 : throw (css::uno::RuntimeException, std::exception)
343 : {
344 : (void)rEvent;
345 0 : ThrowIfDisposed();
346 0 : }
347 :
348 0 : void SAL_CALL PresenterButton::mouseDragged (const css::awt::MouseEvent& rEvent)
349 : throw (css::uno::RuntimeException, std::exception)
350 : {
351 : (void)rEvent;
352 0 : ThrowIfDisposed();
353 0 : }
354 :
355 : //----- lang::XEventListener --------------------------------------------------
356 :
357 0 : void SAL_CALL PresenterButton::disposing (const css::lang::EventObject& rEvent)
358 : throw (css::uno::RuntimeException, std::exception)
359 : {
360 0 : if (rEvent.Source == mxWindow)
361 0 : mxWindow = NULL;
362 0 : }
363 :
364 :
365 :
366 0 : css::geometry::IntegerSize2D PresenterButton::CalculateButtonSize()
367 : {
368 0 : if (mpFont.get()!=NULL && !mpFont->mxFont.is() && mxCanvas.is())
369 0 : mpFont->PrepareFont(mxCanvas);
370 0 : if (mpFont.get()==NULL || !mpFont->mxFont.is())
371 0 : return geometry::IntegerSize2D(-1,-1);
372 :
373 0 : geometry::RealSize2D aTextSize (PresenterCanvasHelper::GetTextSize(mpFont->mxFont,msText));
374 :
375 : return geometry::IntegerSize2D (
376 0 : sal_Int32(0.5 + aTextSize.Width + 2*gnHorizontalBorder),
377 0 : sal_Int32(0.5 + aTextSize.Height + 2*gnVerticalBorder));
378 : }
379 :
380 0 : void PresenterButton::RenderButton (
381 : const Reference<rendering::XCanvas>& rxCanvas,
382 : const geometry::IntegerSize2D& rSize,
383 : const PresenterTheme::SharedFontDescriptor& rpFont,
384 : const PresenterBitmapDescriptor::Mode eMode,
385 : const SharedBitmapDescriptor& rpLeft,
386 : const SharedBitmapDescriptor& rpCenter,
387 : const SharedBitmapDescriptor& rpRight)
388 : {
389 0 : if ( ! rxCanvas.is())
390 0 : return;
391 :
392 0 : const awt::Rectangle aBox(0,0, rSize.Width, rSize.Height);
393 :
394 : PresenterUIPainter::PaintHorizontalBitmapComposite (
395 : rxCanvas,
396 : aBox,
397 : aBox,
398 : GetBitmap(rpLeft, eMode),
399 : GetBitmap(rpCenter, eMode),
400 0 : GetBitmap(rpRight, eMode));
401 :
402 0 : if (rpFont.get()==NULL || ! rpFont->mxFont.is())
403 0 : return;
404 :
405 0 : const rendering::StringContext aContext (msText, 0, msText.getLength());
406 : const Reference<rendering::XTextLayout> xLayout (
407 0 : rpFont->mxFont->createTextLayout(aContext,rendering::TextDirection::WEAK_LEFT_TO_RIGHT,0));
408 0 : const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds());
409 :
410 : rendering::RenderState aRenderState (geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL,
411 0 : Sequence<double>(4), rendering::CompositeOperation::SOURCE);
412 0 : PresenterCanvasHelper::SetDeviceColor(aRenderState, rpFont->mnColor);
413 :
414 0 : aRenderState.AffineTransform.m02 = (rSize.Width - aTextBBox.X2 + aTextBBox.X1)/2;
415 0 : aRenderState.AffineTransform.m12 = (rSize.Height - aTextBBox.Y2 + aTextBBox.Y1)/2 - aTextBBox.Y1;
416 :
417 : /// this is responsible of the close button
418 0 : rxCanvas->drawTextLayout(
419 : xLayout,
420 : rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL),
421 0 : aRenderState);
422 : }
423 :
424 0 : void PresenterButton::Invalidate()
425 : {
426 0 : mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
427 0 : }
428 :
429 0 : Reference<rendering::XBitmap> PresenterButton::GetBitmap (
430 : const SharedBitmapDescriptor& mpIcon,
431 : const PresenterBitmapDescriptor::Mode eMode)
432 : {
433 0 : if (mpIcon.get() != NULL)
434 0 : return mpIcon->GetBitmap(eMode);
435 : else
436 : {
437 : OSL_ASSERT(mpIcon.get()!=NULL);
438 0 : return NULL;
439 : }
440 : }
441 :
442 0 : void PresenterButton::SetupButtonBitmaps()
443 : {
444 0 : if ( ! mxCanvas.is())
445 0 : return;
446 0 : if ( ! mxCanvas->getDevice().is())
447 0 : return;
448 :
449 : // Get the bitmaps for the button border.
450 0 : SharedBitmapDescriptor pLeftBitmap (mpTheme->GetBitmap("ButtonFrameLeft"));
451 0 : SharedBitmapDescriptor pCenterBitmap(mpTheme->GetBitmap("ButtonFrameCenter"));
452 0 : SharedBitmapDescriptor pRightBitmap(mpTheme->GetBitmap("ButtonFrameRight"));
453 :
454 0 : maButtonSize = CalculateButtonSize();
455 :
456 0 : if (maButtonSize.Height<=0 && maButtonSize.Width<= 0)
457 0 : return;
458 :
459 0 : mxNormalBitmap = mxCanvas->getDevice()->createCompatibleAlphaBitmap(maButtonSize);
460 0 : Reference<rendering::XCanvas> xCanvas (mxNormalBitmap, UNO_QUERY);
461 0 : if (xCanvas.is())
462 : RenderButton(
463 : xCanvas,
464 : maButtonSize,
465 : mpFont,
466 : PresenterBitmapDescriptor::Normal,
467 : pLeftBitmap,
468 : pCenterBitmap,
469 0 : pRightBitmap);
470 :
471 0 : mxMouseOverBitmap = mxCanvas->getDevice()->createCompatibleAlphaBitmap(maButtonSize);
472 0 : xCanvas = Reference<rendering::XCanvas>(mxMouseOverBitmap, UNO_QUERY);
473 0 : if (mpMouseOverFont.get()!=NULL && !mpMouseOverFont->mxFont.is() && mxCanvas.is())
474 0 : mpMouseOverFont->PrepareFont(mxCanvas);
475 0 : if (xCanvas.is())
476 : RenderButton(
477 : xCanvas,
478 : maButtonSize,
479 : mpMouseOverFont,
480 : PresenterBitmapDescriptor::MouseOver,
481 : pLeftBitmap,
482 : pCenterBitmap,
483 0 : pRightBitmap);
484 : }
485 :
486 0 : Reference<beans::XPropertySet> PresenterButton::GetConfigurationProperties (
487 : const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext,
488 : const OUString& rsConfgurationName)
489 : {
490 : PresenterConfigurationAccess aConfiguration (
491 : rxComponentContext,
492 : PresenterConfigurationAccess::msPresenterScreenRootName,
493 0 : PresenterConfigurationAccess::READ_ONLY);
494 : return Reference<beans::XPropertySet>(
495 : PresenterConfigurationAccess::Find (
496 : Reference<container::XNameAccess>(
497 : aConfiguration.GetConfigurationNode("PresenterScreenSettings/Buttons"),
498 : UNO_QUERY),
499 : ::boost::bind(&PresenterConfigurationAccess::IsStringPropertyEqual,
500 : rsConfgurationName,
501 : OUString("Name"),
502 : _2)),
503 0 : UNO_QUERY);
504 : }
505 :
506 0 : void PresenterButton::ThrowIfDisposed() const
507 : throw (::com::sun::star::lang::DisposedException)
508 : {
509 0 : if (rBHelper.bDisposed || rBHelper.bInDispose)
510 : {
511 : throw lang::DisposedException (
512 : OUString( "PresenterButton object has already been disposed"),
513 0 : const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
514 : }
515 0 : }
516 :
517 18 : } } // end of namespace sdext::presenter
518 :
519 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|