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