1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sdext.hxx"
26
27 #include "PresenterButton.hxx"
28 #include "PresenterCanvasHelper.hxx"
29 #include "PresenterController.hxx"
30 #include "PresenterGeometryHelper.hxx"
31 #include "PresenterPaintManager.hxx"
32 #include "PresenterUIPainter.hxx"
33 #include <com/sun/star/awt/PosSize.hpp>
34 #include <com/sun/star/awt/XWindowPeer.hpp>
35 #include <com/sun/star/drawing/XPresenterHelper.hpp>
36 #include <com/sun/star/rendering/CompositeOperation.hpp>
37 #include <com/sun/star/rendering/TextDirection.hpp>
38 #include <boost/bind.hpp>
39
40 using namespace ::com::sun::star;
41 using namespace ::com::sun::star::uno;
42 using ::rtl::OUString;
43
44 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
45
46 namespace sdext { namespace presenter {
47
48 const static double gnHorizontalBorder (15);
49 const static double gnVerticalBorder (5);
50
51
52
Create(const css::uno::Reference<css::uno::XComponentContext> & rxComponentContext,const::rtl::Reference<PresenterController> & rpPresenterController,const::boost::shared_ptr<PresenterTheme> & rpTheme,const css::uno::Reference<css::awt::XWindow> & rxParentWindow,const css::uno::Reference<css::rendering::XCanvas> & rxParentCanvas,const OUString & rsConfigurationName)53 ::rtl::Reference<PresenterButton> PresenterButton::Create (
54 const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext,
55 const ::rtl::Reference<PresenterController>& rpPresenterController,
56 const ::boost::shared_ptr<PresenterTheme>& rpTheme,
57 const css::uno::Reference<css::awt::XWindow>& rxParentWindow,
58 const css::uno::Reference<css::rendering::XCanvas>& rxParentCanvas,
59 const OUString& rsConfigurationName)
60 {
61 Reference<beans::XPropertySet> xProperties (GetConfigurationProperties(
62 rxComponentContext,
63 rsConfigurationName));
64 if (xProperties.is())
65 {
66 OUString sText;
67 OUString sAction;
68 PresenterConfigurationAccess::GetProperty(xProperties, A2S("Text")) >>= sText;
69 PresenterConfigurationAccess::GetProperty(xProperties, A2S("Action")) >>= sAction;
70
71 PresenterTheme::SharedFontDescriptor pFont;
72 if (rpTheme.get() != NULL)
73 pFont = rpTheme->GetFont(A2S("ButtonFont"));
74
75 PresenterTheme::SharedFontDescriptor pMouseOverFont;
76 if (rpTheme.get() != NULL)
77 pMouseOverFont = rpTheme->GetFont(A2S("ButtonMouseOverFont"));
78
79 rtl::Reference<PresenterButton> pButton (
80 new PresenterButton(
81 rxComponentContext,
82 rpPresenterController,
83 rpTheme,
84 rxParentWindow,
85 pFont,
86 pMouseOverFont,
87 sText,
88 sAction));
89 pButton->SetCanvas(rxParentCanvas, rxParentWindow);
90 return pButton;
91 }
92 else
93 return NULL;
94 }
95
96
97
98
PresenterButton(const css::uno::Reference<css::uno::XComponentContext> & rxComponentContext,const::rtl::Reference<PresenterController> & rpPresenterController,const::boost::shared_ptr<PresenterTheme> & rpTheme,const css::uno::Reference<css::awt::XWindow> & rxParentWindow,const PresenterTheme::SharedFontDescriptor & rpFont,const PresenterTheme::SharedFontDescriptor & rpMouseOverFont,const OUString & rsText,const OUString & rsAction)99 PresenterButton::PresenterButton (
100 const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext,
101 const ::rtl::Reference<PresenterController>& rpPresenterController,
102 const ::boost::shared_ptr<PresenterTheme>& rpTheme,
103 const css::uno::Reference<css::awt::XWindow>& rxParentWindow,
104 const PresenterTheme::SharedFontDescriptor& rpFont,
105 const PresenterTheme::SharedFontDescriptor& rpMouseOverFont,
106 const OUString& rsText,
107 const OUString& rsAction)
108 : PresenterButtonInterfaceBase(m_aMutex),
109 mpPresenterController(rpPresenterController),
110 mpTheme(rpTheme),
111 mxWindow(),
112 mxCanvas(),
113 mxPresenterHelper(),
114 msText(rsText),
115 mpFont(rpFont),
116 mpMouseOverFont(rpMouseOverFont),
117 msAction(rsAction),
118 maCenter(),
119 maButtonSize(-1,-1),
120 meState(PresenterBitmapDescriptor::Normal),
121 mxNormalBitmap(),
122 mxMouseOverBitmap()
123 {
124 try
125 {
126 Reference<lang::XMultiComponentFactory> xFactory (rxComponentContext->getServiceManager());
127 if ( ! xFactory.is())
128 throw RuntimeException();
129
130 mxPresenterHelper = Reference<drawing::XPresenterHelper>(
131 xFactory->createInstanceWithContext(
132 OUString::createFromAscii("com.sun.star.comp.Draw.PresenterHelper"),
133 rxComponentContext),
134 UNO_QUERY_THROW);
135
136 if (mxPresenterHelper.is())
137 mxWindow = mxPresenterHelper->createWindow(rxParentWindow,
138 sal_False,
139 sal_False,
140 sal_False,
141 sal_False);
142
143 // Make the background transparent.
144 Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY_THROW);
145 if (xPeer.is())
146 {
147 xPeer->setBackground(0xff000000);
148 }
149
150 mxWindow->setVisible(sal_True);
151 mxWindow->addWindowListener(this);
152 mxWindow->addPaintListener(this);
153 mxWindow->addMouseListener(this);
154 mxWindow->addMouseMotionListener(this);
155 }
156 catch (RuntimeException&)
157 {
158 }
159 }
160
161
162
163
~PresenterButton(void)164 PresenterButton::~PresenterButton (void)
165 {
166 }
167
168
169
170
disposing(void)171 void SAL_CALL PresenterButton::disposing (void)
172 {
173 if (mxCanvas.is())
174 {
175 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
176 mxCanvas = NULL;
177 if (xComponent.is())
178 xComponent->dispose();
179 }
180
181 if (mxWindow.is())
182 {
183 mxWindow->removeWindowListener(this);
184 mxWindow->removePaintListener(this);
185 mxWindow->removeMouseListener(this);
186 mxWindow->removeMouseMotionListener(this);
187 Reference<lang::XComponent> xComponent (mxWindow, UNO_QUERY);
188 mxWindow = NULL;
189 if (xComponent.is())
190 xComponent->dispose();
191 }
192 }
193
194
195
196
SetCenter(const css::geometry::RealPoint2D & rLocation)197 void PresenterButton::SetCenter (const css::geometry::RealPoint2D& rLocation)
198 {
199 if (mxCanvas.is())
200 {
201 Invalidate();
202
203 maCenter = rLocation;
204 mxWindow->setPosSize(
205 sal_Int32(0.5 + maCenter.X - maButtonSize.Width/2),
206 sal_Int32(0.5 + maCenter.Y - maButtonSize.Height/2),
207 maButtonSize.Width,
208 maButtonSize.Height,
209 awt::PosSize::POSSIZE);
210
211 Invalidate();
212 }
213 else
214 {
215 // The button can not be painted but we can at least store the new center.
216 maCenter = rLocation;
217 }
218 }
219
220
221
222
SetCanvas(const css::uno::Reference<css::rendering::XCanvas> & rxParentCanvas,const css::uno::Reference<css::awt::XWindow> & rxParentWindow)223 void PresenterButton::SetCanvas (
224 const css::uno::Reference<css::rendering::XCanvas>& rxParentCanvas,
225 const css::uno::Reference<css::awt::XWindow>& rxParentWindow)
226 {
227 if (mxCanvas.is())
228 {
229 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
230 mxCanvas = NULL;
231 if (xComponent.is())
232 xComponent->dispose();
233 }
234
235 if (mxPresenterHelper.is() && rxParentCanvas.is() && rxParentWindow.is())
236 {
237 mxCanvas = mxPresenterHelper->createSharedCanvas (
238 Reference<rendering::XSpriteCanvas>(rxParentCanvas, UNO_QUERY),
239 rxParentWindow,
240 rxParentCanvas,
241 rxParentWindow,
242 mxWindow);
243 if (mxCanvas.is())
244 {
245 SetupButtonBitmaps();
246 SetCenter(maCenter);
247 }
248 }
249 }
250
251
252
253
GetSize(void)254 css::geometry::IntegerSize2D PresenterButton::GetSize (void)
255 {
256 if (maButtonSize.Width < 0)
257 CalculateButtonSize();
258 return maButtonSize;
259 }
260
261
262
263
264 //----- XWindowListener -------------------------------------------------------
265
windowResized(const css::awt::WindowEvent & rEvent)266 void SAL_CALL PresenterButton::windowResized (const css::awt::WindowEvent& rEvent)
267 throw (css::uno::RuntimeException)
268 {
269 (void)rEvent;
270 ThrowIfDisposed();
271 }
272
273
274
275
276
windowMoved(const css::awt::WindowEvent & rEvent)277 void SAL_CALL PresenterButton::windowMoved (const css::awt::WindowEvent& rEvent)
278 throw (css::uno::RuntimeException)
279 {
280 (void)rEvent;
281 ThrowIfDisposed();
282 }
283
284
285
286
windowShown(const css::lang::EventObject & rEvent)287 void SAL_CALL PresenterButton::windowShown (const css::lang::EventObject& rEvent)
288 throw (css::uno::RuntimeException)
289 {
290 (void)rEvent;
291 ThrowIfDisposed();
292 }
293
294
295
296
windowHidden(const css::lang::EventObject & rEvent)297 void SAL_CALL PresenterButton::windowHidden (const css::lang::EventObject& rEvent)
298 throw (css::uno::RuntimeException)
299 {
300 (void)rEvent;
301 ThrowIfDisposed();
302 }
303
304
305
306
307 //----- XPaintListener --------------------------------------------------------
308
windowPaint(const css::awt::PaintEvent & rEvent)309 void SAL_CALL PresenterButton::windowPaint (const css::awt::PaintEvent& rEvent)
310 throw (css::uno::RuntimeException)
311 {
312 ThrowIfDisposed();
313 if (mxWindow.is() && mxCanvas.is())
314 {
315 Reference<rendering::XBitmap> xBitmap;
316 if (meState == PresenterBitmapDescriptor::MouseOver)
317 xBitmap = mxMouseOverBitmap;
318 else
319 xBitmap = mxNormalBitmap;
320 if ( ! xBitmap.is())
321 return;
322
323 rendering::ViewState aViewState(
324 geometry::AffineMatrix2D(1,0,0, 0,1,0),
325 NULL);
326 rendering::RenderState aRenderState(
327 geometry::AffineMatrix2D(1,0,0, 0,1,0),
328 PresenterGeometryHelper::CreatePolygon(rEvent.UpdateRect, mxCanvas->getDevice()),
329 Sequence<double>(4),
330 rendering::CompositeOperation::SOURCE);
331
332 mxCanvas->drawBitmap(xBitmap, aViewState, aRenderState);
333
334 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
335 if (xSpriteCanvas.is())
336 xSpriteCanvas->updateScreen(sal_False);
337 }
338 }
339
340
341
342
343 //----- XMouseListener --------------------------------------------------------
344
mousePressed(const css::awt::MouseEvent & rEvent)345 void SAL_CALL PresenterButton::mousePressed (const css::awt::MouseEvent& rEvent)
346 throw(css::uno::RuntimeException)
347 {
348 (void)rEvent;
349 ThrowIfDisposed();
350
351 meState = PresenterBitmapDescriptor::ButtonDown;
352 }
353
354
355
356
mouseReleased(const css::awt::MouseEvent & rEvent)357 void SAL_CALL PresenterButton::mouseReleased (const css::awt::MouseEvent& rEvent)
358 throw(css::uno::RuntimeException)
359 {
360 (void)rEvent;
361 ThrowIfDisposed();
362
363 if (meState == PresenterBitmapDescriptor::ButtonDown)
364 {
365 OSL_ASSERT(mpPresenterController.get()!=NULL);
366 mpPresenterController->DispatchUnoCommand(msAction);
367
368 meState = PresenterBitmapDescriptor::Normal;
369 Invalidate();
370 }
371 }
372
373
374
375
mouseEntered(const css::awt::MouseEvent & rEvent)376 void SAL_CALL PresenterButton::mouseEntered (const css::awt::MouseEvent& rEvent)
377 throw(css::uno::RuntimeException)
378 {
379 (void)rEvent;
380 ThrowIfDisposed();
381 meState = PresenterBitmapDescriptor::MouseOver;
382 Invalidate();
383 }
384
385
386
387
mouseExited(const css::awt::MouseEvent & rEvent)388 void SAL_CALL PresenterButton::mouseExited (const css::awt::MouseEvent& rEvent)
389 throw(css::uno::RuntimeException)
390 {
391 (void)rEvent;
392 ThrowIfDisposed();
393 meState = PresenterBitmapDescriptor::Normal;
394 Invalidate();
395 }
396
397
398
399
400
401 //----- XMouseMotionListener --------------------------------------------------
402
mouseMoved(const css::awt::MouseEvent & rEvent)403 void SAL_CALL PresenterButton::mouseMoved (const css::awt::MouseEvent& rEvent)
404 throw (css::uno::RuntimeException)
405 {
406 (void)rEvent;
407 ThrowIfDisposed();
408 }
409
410
411
412
mouseDragged(const css::awt::MouseEvent & rEvent)413 void SAL_CALL PresenterButton::mouseDragged (const css::awt::MouseEvent& rEvent)
414 throw (css::uno::RuntimeException)
415 {
416 (void)rEvent;
417 ThrowIfDisposed();
418 }
419
420
421
422
423 //----- lang::XEventListener --------------------------------------------------
424
disposing(const css::lang::EventObject & rEvent)425 void SAL_CALL PresenterButton::disposing (const css::lang::EventObject& rEvent)
426 throw (css::uno::RuntimeException)
427 {
428 if (rEvent.Source == mxWindow)
429 mxWindow = NULL;
430 }
431
432
433
434
435 //-----------------------------------------------------------------------------
436
CalculateButtonSize(void)437 css::geometry::IntegerSize2D PresenterButton::CalculateButtonSize (void)
438 {
439 if (mpFont.get()!=NULL && !mpFont->mxFont.is() && mxCanvas.is())
440 mpFont->PrepareFont(mxCanvas);
441 if (mpFont.get()==NULL || !mpFont->mxFont.is())
442 return geometry::IntegerSize2D(-1,-1);
443
444 geometry::RealSize2D aTextSize (PresenterCanvasHelper::GetTextSize(mpFont->mxFont,msText));
445
446 return geometry::IntegerSize2D (
447 sal_Int32(0.5 + aTextSize.Width + 2*gnHorizontalBorder),
448 sal_Int32(0.5 + aTextSize.Height + 2*gnVerticalBorder));
449 }
450
451
452
453
RenderButton(const Reference<rendering::XCanvas> & rxCanvas,const geometry::IntegerSize2D & rSize,const PresenterTheme::SharedFontDescriptor & rpFont,const PresenterBitmapDescriptor::Mode eMode,const SharedBitmapDescriptor & rpLeft,const SharedBitmapDescriptor & rpCenter,const SharedBitmapDescriptor & rpRight)454 void PresenterButton::RenderButton (
455 const Reference<rendering::XCanvas>& rxCanvas,
456 const geometry::IntegerSize2D& rSize,
457 const PresenterTheme::SharedFontDescriptor& rpFont,
458 const PresenterBitmapDescriptor::Mode eMode,
459 const SharedBitmapDescriptor& rpLeft,
460 const SharedBitmapDescriptor& rpCenter,
461 const SharedBitmapDescriptor& rpRight)
462 {
463 if ( ! rxCanvas.is())
464 return;
465
466 const awt::Rectangle aBox(0,0, rSize.Width, rSize.Height);
467
468 PresenterUIPainter::PaintHorizontalBitmapComposite (
469 rxCanvas,
470 aBox,
471 aBox,
472 GetBitmap(rpLeft, eMode),
473 GetBitmap(rpCenter, eMode),
474 GetBitmap(rpRight, eMode));
475
476 if (rpFont.get()==NULL || ! rpFont->mxFont.is())
477 return;
478
479 const rendering::StringContext aContext (msText, 0, msText.getLength());
480 const Reference<rendering::XTextLayout> xLayout (
481 rpFont->mxFont->createTextLayout(aContext,rendering::TextDirection::WEAK_LEFT_TO_RIGHT,0));
482 const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds());
483
484 rendering::RenderState aRenderState (geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL,
485 Sequence<double>(4), rendering::CompositeOperation::SOURCE);
486 PresenterCanvasHelper::SetDeviceColor(aRenderState, rpFont->mnColor);
487 aRenderState.AffineTransform.m02 = (rSize.Width - aTextBBox.X2 + aTextBBox.X1)/2;
488 aRenderState.AffineTransform.m12 = (rSize.Height - aTextBBox.Y2 + aTextBBox.Y1)/2 - aTextBBox.Y1;
489
490 rxCanvas->drawText(
491 aContext,
492 rpFont->mxFont,
493 rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL),
494 aRenderState,
495 rendering::TextDirection::WEAK_LEFT_TO_RIGHT);
496 }
497
498
499
500
Invalidate(void)501 void PresenterButton::Invalidate (void)
502 {
503 mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
504 }
505
506
507
508
GetBitmap(const SharedBitmapDescriptor & mpIcon,const PresenterBitmapDescriptor::Mode eMode)509 Reference<rendering::XBitmap> PresenterButton::GetBitmap (
510 const SharedBitmapDescriptor& mpIcon,
511 const PresenterBitmapDescriptor::Mode eMode)
512 {
513 if (mpIcon.get() != NULL)
514 return mpIcon->GetBitmap(eMode);
515 else
516 {
517 OSL_ASSERT(mpIcon.get()!=NULL);
518 return NULL;
519 }
520 }
521
522
523
524
SetupButtonBitmaps(void)525 void PresenterButton::SetupButtonBitmaps (void)
526 {
527 if ( ! mxCanvas.is())
528 return;
529 if ( ! mxCanvas->getDevice().is())
530 return;
531
532 // Get the bitmaps for the button border.
533 SharedBitmapDescriptor pLeftBitmap (mpTheme->GetBitmap(A2S("ButtonFrameLeft")));
534 SharedBitmapDescriptor pCenterBitmap(mpTheme->GetBitmap(A2S("ButtonFrameCenter")));
535 SharedBitmapDescriptor pRightBitmap(mpTheme->GetBitmap(A2S("ButtonFrameRight")));
536
537 maButtonSize = CalculateButtonSize();
538
539 if (maButtonSize.Height<=0 && maButtonSize.Width<= 0)
540 return;
541
542 mxNormalBitmap = mxCanvas->getDevice()->createCompatibleAlphaBitmap(maButtonSize);
543 Reference<rendering::XCanvas> xCanvas (mxNormalBitmap, UNO_QUERY);
544 if (xCanvas.is())
545 RenderButton(
546 xCanvas,
547 maButtonSize,
548 mpFont,
549 PresenterBitmapDescriptor::Normal,
550 pLeftBitmap,
551 pCenterBitmap,
552 pRightBitmap);
553
554 mxMouseOverBitmap = mxCanvas->getDevice()->createCompatibleAlphaBitmap(maButtonSize);
555 xCanvas = Reference<rendering::XCanvas>(mxMouseOverBitmap, UNO_QUERY);
556 if (mpMouseOverFont.get()!=NULL && !mpMouseOverFont->mxFont.is() && mxCanvas.is())
557 mpMouseOverFont->PrepareFont(mxCanvas);
558 if (xCanvas.is())
559 RenderButton(
560 xCanvas,
561 maButtonSize,
562 mpMouseOverFont,
563 PresenterBitmapDescriptor::MouseOver,
564 pLeftBitmap,
565 pCenterBitmap,
566 pRightBitmap);
567 }
568
569
570
571
GetConfigurationProperties(const css::uno::Reference<css::uno::XComponentContext> & rxComponentContext,const OUString & rsConfgurationName)572 Reference<beans::XPropertySet> PresenterButton::GetConfigurationProperties (
573 const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext,
574 const OUString& rsConfgurationName)
575 {
576 PresenterConfigurationAccess aConfiguration (
577 rxComponentContext,
578 PresenterConfigurationAccess::msPresenterScreenRootName,
579 PresenterConfigurationAccess::READ_ONLY);
580 return Reference<beans::XPropertySet>(
581 PresenterConfigurationAccess::Find (
582 Reference<container::XNameAccess>(
583 aConfiguration.GetConfigurationNode(A2S("PresenterScreenSettings/Buttons")),
584 UNO_QUERY),
585 ::boost::bind(&PresenterConfigurationAccess::IsStringPropertyEqual,
586 rsConfgurationName,
587 A2S("Name"),
588 _2)),
589 UNO_QUERY);
590 }
591
592
593
594
ThrowIfDisposed(void) const595 void PresenterButton::ThrowIfDisposed (void) const
596 throw (::com::sun::star::lang::DisposedException)
597 {
598 if (rBHelper.bDisposed || rBHelper.bInDispose)
599 {
600 throw lang::DisposedException (
601 OUString(RTL_CONSTASCII_USTRINGPARAM(
602 "PresenterButton object has already been disposed")),
603 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
604 }
605 }
606
607
608 } } // end of namespace sdext::presenter
609