/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: PresenterButton.cxx,v $ * * $Revision: 1.6 $ * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sdext.hxx" #include "PresenterButton.hxx" #include "PresenterCanvasHelper.hxx" #include "PresenterController.hxx" #include "PresenterGeometryHelper.hxx" #include "PresenterPaintManager.hxx" #include "PresenterUIPainter.hxx" #include #include #include #include #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using ::rtl::OUString; #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) namespace sdext { namespace presenter { const static double gnHorizontalBorder (15); const static double gnVerticalBorder (5); ::rtl::Reference PresenterButton::Create ( const css::uno::Reference& rxComponentContext, const ::rtl::Reference& rpPresenterController, const ::boost::shared_ptr& rpTheme, const css::uno::Reference& rxParentWindow, const css::uno::Reference& rxParentCanvas, const OUString& rsConfigurationName) { Reference xProperties (GetConfigurationProperties( rxComponentContext, rsConfigurationName)); if (xProperties.is()) { OUString sText; OUString sAction; PresenterConfigurationAccess::GetProperty(xProperties, A2S("Text")) >>= sText; PresenterConfigurationAccess::GetProperty(xProperties, A2S("Action")) >>= sAction; PresenterTheme::SharedFontDescriptor pFont; if (rpTheme.get() != NULL) pFont = rpTheme->GetFont(A2S("ButtonFont")); PresenterTheme::SharedFontDescriptor pMouseOverFont; if (rpTheme.get() != NULL) pMouseOverFont = rpTheme->GetFont(A2S("ButtonMouseOverFont")); rtl::Reference pButton ( new PresenterButton( rxComponentContext, rpPresenterController, rpTheme, rxParentWindow, pFont, pMouseOverFont, sText, sAction)); pButton->SetCanvas(rxParentCanvas, rxParentWindow); return pButton; } else return NULL; } PresenterButton::PresenterButton ( const css::uno::Reference& rxComponentContext, const ::rtl::Reference& rpPresenterController, const ::boost::shared_ptr& rpTheme, const css::uno::Reference& rxParentWindow, const PresenterTheme::SharedFontDescriptor& rpFont, const PresenterTheme::SharedFontDescriptor& rpMouseOverFont, const OUString& rsText, const OUString& rsAction) : PresenterButtonInterfaceBase(m_aMutex), mpPresenterController(rpPresenterController), mpTheme(rpTheme), mxWindow(), mxCanvas(), mxPresenterHelper(), msText(rsText), mpFont(rpFont), mpMouseOverFont(rpMouseOverFont), msAction(rsAction), maCenter(), maButtonSize(-1,-1), meState(PresenterBitmapDescriptor::Normal), mxNormalBitmap(), mxMouseOverBitmap() { try { Reference xFactory (rxComponentContext->getServiceManager()); if ( ! xFactory.is()) throw RuntimeException(); mxPresenterHelper = Reference( xFactory->createInstanceWithContext( OUString::createFromAscii("com.sun.star.comp.Draw.PresenterHelper"), rxComponentContext), UNO_QUERY_THROW); if (mxPresenterHelper.is()) mxWindow = mxPresenterHelper->createWindow(rxParentWindow, sal_False, sal_False, sal_False, sal_False); // Make the background transparent. Reference xPeer (mxWindow, UNO_QUERY_THROW); if (xPeer.is()) { xPeer->setBackground(0xff000000); } mxWindow->setVisible(sal_True); mxWindow->addWindowListener(this); mxWindow->addPaintListener(this); mxWindow->addMouseListener(this); mxWindow->addMouseMotionListener(this); } catch (RuntimeException&) { } } PresenterButton::~PresenterButton (void) { } void SAL_CALL PresenterButton::disposing (void) { if (mxCanvas.is()) { Reference xComponent (mxCanvas, UNO_QUERY); mxCanvas = NULL; if (xComponent.is()) xComponent->dispose(); } if (mxWindow.is()) { mxWindow->removeWindowListener(this); mxWindow->removePaintListener(this); mxWindow->removeMouseListener(this); mxWindow->removeMouseMotionListener(this); Reference xComponent (mxWindow, UNO_QUERY); mxWindow = NULL; if (xComponent.is()) xComponent->dispose(); } } void PresenterButton::SetCenter (const css::geometry::RealPoint2D& rLocation) { if (mxCanvas.is()) { Invalidate(); maCenter = rLocation; mxWindow->setPosSize( sal_Int32(0.5 + maCenter.X - maButtonSize.Width/2), sal_Int32(0.5 + maCenter.Y - maButtonSize.Height/2), maButtonSize.Width, maButtonSize.Height, awt::PosSize::POSSIZE); Invalidate(); } else { // The button can not be painted but we can at least store the new center. maCenter = rLocation; } } void PresenterButton::SetCanvas ( const css::uno::Reference& rxParentCanvas, const css::uno::Reference& rxParentWindow) { if (mxCanvas.is()) { Reference xComponent (mxCanvas, UNO_QUERY); mxCanvas = NULL; if (xComponent.is()) xComponent->dispose(); } if (mxPresenterHelper.is() && rxParentCanvas.is() && rxParentWindow.is()) { mxCanvas = mxPresenterHelper->createSharedCanvas ( Reference(rxParentCanvas, UNO_QUERY), rxParentWindow, rxParentCanvas, rxParentWindow, mxWindow); if (mxCanvas.is()) { SetupButtonBitmaps(); SetCenter(maCenter); } } } css::geometry::IntegerSize2D PresenterButton::GetSize (void) { if (maButtonSize.Width < 0) CalculateButtonSize(); return maButtonSize; } //----- XWindowListener ------------------------------------------------------- void SAL_CALL PresenterButton::windowResized (const css::awt::WindowEvent& rEvent) throw (css::uno::RuntimeException) { (void)rEvent; ThrowIfDisposed(); } void SAL_CALL PresenterButton::windowMoved (const css::awt::WindowEvent& rEvent) throw (css::uno::RuntimeException) { (void)rEvent; ThrowIfDisposed(); } void SAL_CALL PresenterButton::windowShown (const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException) { (void)rEvent; ThrowIfDisposed(); } void SAL_CALL PresenterButton::windowHidden (const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException) { (void)rEvent; ThrowIfDisposed(); } //----- XPaintListener -------------------------------------------------------- void SAL_CALL PresenterButton::windowPaint (const css::awt::PaintEvent& rEvent) throw (css::uno::RuntimeException) { ThrowIfDisposed(); if (mxWindow.is() && mxCanvas.is()) { Reference xBitmap; if (meState == PresenterBitmapDescriptor::MouseOver) xBitmap = mxMouseOverBitmap; else xBitmap = mxNormalBitmap; if ( ! xBitmap.is()) return; rendering::ViewState aViewState( geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL); rendering::RenderState aRenderState( geometry::AffineMatrix2D(1,0,0, 0,1,0), PresenterGeometryHelper::CreatePolygon(rEvent.UpdateRect, mxCanvas->getDevice()), Sequence(4), rendering::CompositeOperation::SOURCE); mxCanvas->drawBitmap(xBitmap, aViewState, aRenderState); Reference xSpriteCanvas (mxCanvas, UNO_QUERY); if (xSpriteCanvas.is()) xSpriteCanvas->updateScreen(sal_False); } } //----- XMouseListener -------------------------------------------------------- void SAL_CALL PresenterButton::mousePressed (const css::awt::MouseEvent& rEvent) throw(css::uno::RuntimeException) { (void)rEvent; ThrowIfDisposed(); meState = PresenterBitmapDescriptor::ButtonDown; } void SAL_CALL PresenterButton::mouseReleased (const css::awt::MouseEvent& rEvent) throw(css::uno::RuntimeException) { (void)rEvent; ThrowIfDisposed(); if (meState == PresenterBitmapDescriptor::ButtonDown) { OSL_ASSERT(mpPresenterController.get()!=NULL); mpPresenterController->DispatchUnoCommand(msAction); meState = PresenterBitmapDescriptor::Normal; Invalidate(); } } void SAL_CALL PresenterButton::mouseEntered (const css::awt::MouseEvent& rEvent) throw(css::uno::RuntimeException) { (void)rEvent; ThrowIfDisposed(); meState = PresenterBitmapDescriptor::MouseOver; Invalidate(); } void SAL_CALL PresenterButton::mouseExited (const css::awt::MouseEvent& rEvent) throw(css::uno::RuntimeException) { (void)rEvent; ThrowIfDisposed(); meState = PresenterBitmapDescriptor::Normal; Invalidate(); } //----- XMouseMotionListener -------------------------------------------------- void SAL_CALL PresenterButton::mouseMoved (const css::awt::MouseEvent& rEvent) throw (css::uno::RuntimeException) { (void)rEvent; ThrowIfDisposed(); } void SAL_CALL PresenterButton::mouseDragged (const css::awt::MouseEvent& rEvent) throw (css::uno::RuntimeException) { (void)rEvent; ThrowIfDisposed(); } //----- lang::XEventListener -------------------------------------------------- void SAL_CALL PresenterButton::disposing (const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException) { if (rEvent.Source == mxWindow) mxWindow = NULL; } //----------------------------------------------------------------------------- css::geometry::IntegerSize2D PresenterButton::CalculateButtonSize (void) { if (mpFont.get()!=NULL && !mpFont->mxFont.is() && mxCanvas.is()) mpFont->PrepareFont(mxCanvas); if (mpFont.get()==NULL || !mpFont->mxFont.is()) return geometry::IntegerSize2D(-1,-1); geometry::RealSize2D aTextSize (PresenterCanvasHelper::GetTextSize(mpFont->mxFont,msText)); return geometry::IntegerSize2D ( sal_Int32(0.5 + aTextSize.Width + 2*gnHorizontalBorder), sal_Int32(0.5 + aTextSize.Height + 2*gnVerticalBorder)); } void PresenterButton::RenderButton ( const Reference& rxCanvas, const geometry::IntegerSize2D& rSize, const PresenterTheme::SharedFontDescriptor& rpFont, const PresenterBitmapDescriptor::Mode eMode, const SharedBitmapDescriptor& rpLeft, const SharedBitmapDescriptor& rpCenter, const SharedBitmapDescriptor& rpRight) { if ( ! rxCanvas.is()) return; const awt::Rectangle aBox(0,0, rSize.Width, rSize.Height); PresenterUIPainter::PaintHorizontalBitmapComposite ( rxCanvas, aBox, aBox, GetBitmap(rpLeft, eMode), GetBitmap(rpCenter, eMode), GetBitmap(rpRight, eMode)); if (rpFont.get()==NULL || ! rpFont->mxFont.is()) return; const rendering::StringContext aContext (msText, 0, msText.getLength()); const Reference xLayout ( rpFont->mxFont->createTextLayout(aContext,rendering::TextDirection::WEAK_LEFT_TO_RIGHT,0)); const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds()); rendering::RenderState aRenderState (geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL, Sequence(4), rendering::CompositeOperation::SOURCE); PresenterCanvasHelper::SetDeviceColor(aRenderState, rpFont->mnColor); aRenderState.AffineTransform.m02 = (rSize.Width - aTextBBox.X2 + aTextBBox.X1)/2; aRenderState.AffineTransform.m12 = (rSize.Height - aTextBBox.Y2 + aTextBBox.Y1)/2 - aTextBBox.Y1; rxCanvas->drawText( aContext, rpFont->mxFont, rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL), aRenderState, rendering::TextDirection::WEAK_LEFT_TO_RIGHT); } void PresenterButton::Invalidate (void) { mpPresenterController->GetPaintManager()->Invalidate(mxWindow); } Reference PresenterButton::GetBitmap ( const SharedBitmapDescriptor& mpIcon, const PresenterBitmapDescriptor::Mode eMode) { if (mpIcon.get() != NULL) return mpIcon->GetBitmap(eMode); else { OSL_ASSERT(mpIcon.get()!=NULL); return NULL; } } void PresenterButton::SetupButtonBitmaps (void) { if ( ! mxCanvas.is()) return; if ( ! mxCanvas->getDevice().is()) return; // Get the bitmaps for the button border. SharedBitmapDescriptor pLeftBitmap (mpTheme->GetBitmap(A2S("ButtonFrameLeft"))); SharedBitmapDescriptor pCenterBitmap(mpTheme->GetBitmap(A2S("ButtonFrameCenter"))); SharedBitmapDescriptor pRightBitmap(mpTheme->GetBitmap(A2S("ButtonFrameRight"))); maButtonSize = CalculateButtonSize(); if (maButtonSize.Height<=0 && maButtonSize.Width<= 0) return; mxNormalBitmap = mxCanvas->getDevice()->createCompatibleAlphaBitmap(maButtonSize); Reference xCanvas (mxNormalBitmap, UNO_QUERY); if (xCanvas.is()) RenderButton( xCanvas, maButtonSize, mpFont, PresenterBitmapDescriptor::Normal, pLeftBitmap, pCenterBitmap, pRightBitmap); mxMouseOverBitmap = mxCanvas->getDevice()->createCompatibleAlphaBitmap(maButtonSize); xCanvas = Reference(mxMouseOverBitmap, UNO_QUERY); if (mpMouseOverFont.get()!=NULL && !mpMouseOverFont->mxFont.is() && mxCanvas.is()) mpMouseOverFont->PrepareFont(mxCanvas); if (xCanvas.is()) RenderButton( xCanvas, maButtonSize, mpMouseOverFont, PresenterBitmapDescriptor::MouseOver, pLeftBitmap, pCenterBitmap, pRightBitmap); } Reference PresenterButton::GetConfigurationProperties ( const css::uno::Reference& rxComponentContext, const OUString& rsConfgurationName) { PresenterConfigurationAccess aConfiguration ( rxComponentContext, PresenterConfigurationAccess::msPresenterScreenRootName, PresenterConfigurationAccess::READ_ONLY); return Reference( PresenterConfigurationAccess::Find ( Reference( aConfiguration.GetConfigurationNode(A2S("PresenterScreenSettings/Buttons")), UNO_QUERY), ::boost::bind(&PresenterConfigurationAccess::IsStringPropertyEqual, rsConfgurationName, A2S("Name"), _2)), UNO_QUERY); } void PresenterButton::ThrowIfDisposed (void) const throw (::com::sun::star::lang::DisposedException) { if (rBHelper.bDisposed || rBHelper.bInDispose) { throw lang::DisposedException ( OUString(RTL_CONSTASCII_USTRINGPARAM( "PresenterButton object has already been disposed")), const_cast(static_cast(this))); } } } } // end of namespace sdext::presenter