| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sdext.hxx" |
| |
| #include "PresenterSlidePreview.hxx" |
| #include "PresenterCanvasHelper.hxx" |
| #include "PresenterGeometryHelper.hxx" |
| #include "PresenterPaintManager.hxx" |
| #include <com/sun/star/awt/XWindow.hpp> |
| #include <com/sun/star/awt/XWindowPeer.hpp> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <com/sun/star/drawing/framework/XConfigurationController.hpp> |
| #include <com/sun/star/drawing/framework/XControllerManager.hpp> |
| #include <com/sun/star/drawing/framework/XPane.hpp> |
| #include <com/sun/star/rendering/CompositeOperation.hpp> |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::drawing::framework; |
| using ::rtl::OUString; |
| |
| namespace |
| { |
| // Use a super sample factor greater than 1 to achive a poor mans |
| // antialiasing effect for slide previews. |
| const sal_Int16 gnSuperSampleFactor = 2; |
| } |
| |
| namespace sdext { namespace presenter { |
| |
| //===== PresenterSlidePreview ================================================= |
| |
| PresenterSlidePreview::PresenterSlidePreview ( |
| const Reference<XComponentContext>& rxContext, |
| const Reference<XResourceId>& rxViewId, |
| const Reference<XPane>& rxAnchorPane, |
| const ::rtl::Reference<PresenterController>& rpPresenterController) |
| : PresenterSlidePreviewInterfaceBase(m_aMutex), |
| mpPresenterController(rpPresenterController), |
| mxPane(rxAnchorPane), |
| mxViewId(rxViewId), |
| mxPreviewRenderer(), |
| mxPreview(), |
| mxCurrentSlide(), |
| mnSlideAspectRatio(28.0 / 21.0), |
| mxWindow(), |
| mxCanvas() |
| { |
| if ( ! rxContext.is() |
| || ! rxViewId.is() |
| || ! rxAnchorPane.is() |
| || ! rpPresenterController.is()) |
| { |
| throw RuntimeException( |
| OUString::createFromAscii( |
| "PresenterSlidePreview can not be constructed due to empty argument"), |
| static_cast<XWeak*>(this)); |
| } |
| |
| mxWindow = rxAnchorPane->getWindow(); |
| mxCanvas = rxAnchorPane->getCanvas(); |
| |
| if (mxWindow.is()) |
| { |
| mxWindow->addWindowListener(this); |
| mxWindow->addPaintListener(this); |
| |
| Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY); |
| if (xPeer.is()) |
| xPeer->setBackground(util::Color(0xff000000)); |
| |
| mxWindow->setVisible(sal_True); |
| } |
| |
| if (mpPresenterController.get() != NULL) |
| mnSlideAspectRatio = mpPresenterController->GetSlideAspectRatio(); |
| |
| Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager(), UNO_QUERY); |
| if (xFactory.is()) |
| mxPreviewRenderer = Reference<drawing::XSlideRenderer>( |
| xFactory->createInstanceWithContext( |
| OUString::createFromAscii("com.sun.star.drawing.SlideRenderer"), |
| rxContext), |
| UNO_QUERY); |
| |
| Resize(); |
| } |
| |
| |
| |
| |
| PresenterSlidePreview::~PresenterSlidePreview (void) |
| { |
| } |
| |
| |
| |
| |
| void SAL_CALL PresenterSlidePreview::disposing (void) |
| { |
| if (mxWindow.is()) |
| { |
| mxWindow->removeWindowListener(this); |
| mxWindow->removePaintListener(this); |
| mxWindow = NULL; |
| mxCanvas = NULL; |
| } |
| |
| Reference<lang::XComponent> xComponent (mxPreviewRenderer, UNO_QUERY); |
| if (xComponent.is()) |
| xComponent->dispose(); |
| } |
| |
| |
| |
| |
| //----- XResourceId ----------------------------------------------------------- |
| |
| Reference<XResourceId> SAL_CALL PresenterSlidePreview::getResourceId (void) |
| throw (RuntimeException) |
| { |
| return mxViewId; |
| } |
| |
| |
| |
| |
| sal_Bool SAL_CALL PresenterSlidePreview::isAnchorOnly (void) |
| throw (RuntimeException) |
| { |
| return false; |
| } |
| |
| |
| |
| |
| //----- XWindowListener ------------------------------------------------------- |
| |
| void SAL_CALL PresenterSlidePreview::windowResized (const awt::WindowEvent& rEvent) |
| throw (RuntimeException) |
| { |
| (void)rEvent; |
| ThrowIfDisposed(); |
| ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex()); |
| Resize(); |
| } |
| |
| |
| |
| |
| |
| void SAL_CALL PresenterSlidePreview::windowMoved (const awt::WindowEvent& rEvent) |
| throw (RuntimeException) |
| { |
| (void)rEvent; |
| } |
| |
| |
| |
| |
| void SAL_CALL PresenterSlidePreview::windowShown (const lang::EventObject& rEvent) |
| throw (RuntimeException) |
| { |
| (void)rEvent; |
| ThrowIfDisposed(); |
| ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex()); |
| Resize(); |
| } |
| |
| |
| |
| |
| void SAL_CALL PresenterSlidePreview::windowHidden (const lang::EventObject& rEvent) |
| throw (RuntimeException) |
| { |
| (void)rEvent; |
| } |
| |
| |
| |
| |
| //----- XPaintListener -------------------------------------------------------- |
| |
| void SAL_CALL PresenterSlidePreview::windowPaint (const awt::PaintEvent& rEvent) |
| throw (RuntimeException) |
| { |
| ThrowIfDisposed(); |
| |
| ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex()); |
| if (mxWindow.is()) |
| Paint(awt::Rectangle( |
| rEvent.UpdateRect.X, |
| rEvent.UpdateRect.Y, |
| rEvent.UpdateRect.Width, |
| rEvent.UpdateRect.Height)); |
| } |
| |
| |
| |
| |
| //----- lang::XEventListener -------------------------------------------------- |
| |
| void SAL_CALL PresenterSlidePreview::disposing (const lang::EventObject& rEvent) |
| throw (RuntimeException) |
| { |
| if (rEvent.Source == mxWindow) |
| { |
| mxWindow = NULL; |
| mxCanvas = NULL; |
| mxPreview = NULL; |
| } |
| } |
| |
| |
| |
| |
| //----- XDrawView ------------------------------------------------------------- |
| |
| void SAL_CALL PresenterSlidePreview::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide) |
| throw (RuntimeException) |
| { |
| ThrowIfDisposed(); |
| ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex()); |
| SetSlide(rxSlide); |
| } |
| |
| |
| |
| |
| Reference<drawing::XDrawPage> SAL_CALL PresenterSlidePreview::getCurrentPage (void) |
| throw (RuntimeException) |
| { |
| ThrowIfDisposed(); |
| return NULL; |
| } |
| |
| |
| |
| |
| //----------------------------------------------------------------------------- |
| |
| void PresenterSlidePreview::SetSlide (const Reference<drawing::XDrawPage>& rxPage) |
| { |
| mxCurrentSlide = rxPage; |
| mxPreview = NULL; |
| |
| Reference<beans::XPropertySet> xPropertySet (mxCurrentSlide, UNO_QUERY); |
| if (xPropertySet.is()) |
| { |
| awt::Size aSlideSize; |
| try |
| { |
| xPropertySet->getPropertyValue( |
| OUString::createFromAscii("Width")) >>= aSlideSize.Width; |
| xPropertySet->getPropertyValue( |
| OUString::createFromAscii("Height")) >>= aSlideSize.Height; |
| } |
| catch (beans::UnknownPropertyException&) |
| { |
| OSL_ASSERT(false); |
| } |
| } |
| |
| // The preview is not transparent, therefore only this window, not its |
| // parent, has to be invalidated. |
| mpPresenterController->GetPaintManager()->Invalidate(mxWindow); |
| } |
| |
| |
| |
| |
| void PresenterSlidePreview::Paint (const awt::Rectangle& rBoundingBox) |
| { |
| (void)rBoundingBox; |
| if ( ! mxWindow.is()) |
| return; |
| if ( ! mxCanvas.is()) |
| return; |
| if ( ! mxPreviewRenderer.is()) |
| return; |
| |
| // Make sure that a preview in the correct size exists. |
| awt::Rectangle aWindowBox (mxWindow->getPosSize()); |
| |
| if ( ! mxPreview.is() && mxCurrentSlide.is()) |
| { |
| // Create a new preview bitmap. |
| mxPreview = mxPreviewRenderer->createPreviewForCanvas( |
| mxCurrentSlide, |
| awt::Size(aWindowBox.Width, aWindowBox.Height), |
| gnSuperSampleFactor, |
| mxCanvas); |
| } |
| |
| // Determine the bounding box of the preview. |
| awt::Rectangle aPreviewBox; |
| if (mxPreview.is()) |
| { |
| const geometry::IntegerSize2D aPreviewSize (mxPreview->getSize()); |
| aPreviewBox = awt::Rectangle( |
| (aWindowBox.Width - aPreviewSize.Width)/2, |
| (aWindowBox.Height - aPreviewSize.Height)/2, |
| aPreviewSize.Width, |
| aPreviewSize.Height); |
| } |
| else |
| { |
| if (mnSlideAspectRatio > 0) |
| { |
| const awt::Size aPreviewSize (mxPreviewRenderer->calculatePreviewSize( |
| mnSlideAspectRatio,awt::Size(aWindowBox.Width, aWindowBox.Height))); |
| aPreviewBox = awt::Rectangle( |
| (aWindowBox.Width - aPreviewSize.Width)/2, |
| (aWindowBox.Height - aPreviewSize.Height)/2, |
| aPreviewSize.Width, |
| aPreviewSize.Height); |
| } |
| } |
| |
| // Paint the background. |
| mpPresenterController->GetCanvasHelper()->Paint( |
| mpPresenterController->GetViewBackground(mxViewId->getResourceURL()), |
| mxCanvas, |
| rBoundingBox, |
| awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height), |
| aPreviewBox); |
| |
| // Paint the preview. |
| const rendering::ViewState aViewState( |
| geometry::AffineMatrix2D(1,0,0, 0,1,0), |
| NULL); |
| |
| Sequence<double> aBackgroundColor(4); |
| rendering::RenderState aRenderState ( |
| geometry::AffineMatrix2D(1, 0, aPreviewBox.X, 0, 1, aPreviewBox.Y), |
| NULL, |
| aBackgroundColor, |
| rendering::CompositeOperation::SOURCE); |
| PresenterCanvasHelper::SetDeviceColor(aRenderState, 0x00000000); |
| if (mxPreview.is()) |
| { |
| mxCanvas->drawBitmap(mxPreview, aViewState, aRenderState); |
| } |
| else |
| { |
| if (mnSlideAspectRatio > 0) |
| { |
| Reference<rendering::XPolyPolygon2D> xPolygon ( |
| PresenterGeometryHelper::CreatePolygon(aPreviewBox, mxCanvas->getDevice())); |
| if (xPolygon.is()) |
| mxCanvas->fillPolyPolygon(xPolygon, aViewState, aRenderState); |
| } |
| } |
| |
| Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); |
| if (xSpriteCanvas.is()) |
| xSpriteCanvas->updateScreen(sal_False); |
| } |
| |
| |
| |
| |
| void PresenterSlidePreview::Resize (void) |
| { |
| if (mxPreviewRenderer.is() && mxPreview.is()) |
| { |
| const awt::Rectangle aWindowBox (mxWindow->getPosSize()); |
| const awt::Size aNewPreviewSize (mxPreviewRenderer->calculatePreviewSize( |
| mnSlideAspectRatio, |
| awt::Size(aWindowBox.Width, aWindowBox.Height))); |
| const geometry::IntegerSize2D aPreviewSize (mxPreview->getSize()); |
| if (aNewPreviewSize.Width==aPreviewSize.Width |
| && aNewPreviewSize.Height==aPreviewSize.Height) |
| { |
| // The size of the window may have changed but the preview would |
| // be painted in the same size (but not necessarily at the same |
| // position.) |
| return; |
| } |
| } |
| SetSlide(mxCurrentSlide); |
| } |
| |
| |
| |
| |
| void PresenterSlidePreview::ThrowIfDisposed (void) |
| throw (::com::sun::star::lang::DisposedException) |
| { |
| if (PresenterSlidePreviewInterfaceBase::rBHelper.bDisposed || PresenterSlidePreviewInterfaceBase::rBHelper.bInDispose) |
| { |
| throw lang::DisposedException ( |
| ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( |
| "PresenterSlidePreview object has already been disposed")), |
| static_cast<uno::XWeak*>(this)); |
| } |
| } |
| |
| |
| } } // end of namespace ::sd::presenter |
| |