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