diff options
Diffstat (limited to 'sdext/source/presenter')
181 files changed, 40657 insertions, 0 deletions
diff --git a/sdext/source/presenter/PresenterAccessibility.cxx b/sdext/source/presenter/PresenterAccessibility.cxx new file mode 100644 index 000000000000..35c17c0da0bd --- /dev/null +++ b/sdext/source/presenter/PresenterAccessibility.cxx @@ -0,0 +1,2495 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_sdext.hxx" + +#include "PresenterAccessibility.hxx" +#include "PresenterTextView.hxx" +#include "PresenterConfigurationAccess.hxx" +#include "PresenterNotesView.hxx" +#include "PresenterPaneBase.hxx" +#include "PresenterPaneContainer.hxx" +#include "PresenterPaneFactory.hxx" +#include "PresenterViewFactory.hxx" + +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleRelationType.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/XAccessibleComponent.hpp> +#include <com/sun/star/accessibility/XAccessibleContext.hpp> +#include <com/sun/star/accessibility/XAccessibleEditableText.hpp> +#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp> +#include <com/sun/star/accessibility/XAccessibleText.hpp> +#include <com/sun/star/drawing/framework/ResourceId.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/drawing/framework/XView.hpp> +#include <cppuhelper/compbase1.hxx> +#include <cppuhelper/compbase5.hxx> +#include <cppuhelper/implbase1.hxx> +#include <boost/bind.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +#define A2S(s) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))) + +#define VERBOSE + +//===== PresenterAccessibleObject ============================================= + +namespace sdext { namespace presenter { + +namespace { + typedef ::cppu::PartialWeakComponentImplHelper5 < + cssa::XAccessible, + cssa::XAccessibleContext, + cssa::XAccessibleComponent, + cssa::XAccessibleEventBroadcaster, + css::awt::XWindowListener + > PresenterAccessibleObjectInterfaceBase; +} + +class PresenterAccessible::AccessibleObject + : public ::cppu::BaseMutex, + public PresenterAccessibleObjectInterfaceBase +{ +public: + AccessibleObject ( + const css::lang::Locale aLocale, + const sal_Int16 nRole, + const ::rtl::OUString& rsName); + void LateInitialization (void); + + virtual ~AccessibleObject (void); + + virtual void SetWindow ( + const cssu::Reference<css::awt::XWindow>& rxContentWindow, + const cssu::Reference<css::awt::XWindow>& rxBorderWindow); + void SetAccessibleParent (const cssu::Reference<cssa::XAccessible>& rxAccessibleParent); + + virtual void SAL_CALL disposing (void); + + void NotifyCurrentSlideChange (const sal_Int32 nCurrentSlideIndex); + + void AddChild (const ::rtl::Reference<AccessibleObject>& rpChild); + void RemoveChild (const ::rtl::Reference<AccessibleObject>& rpChild); + + void SetIsFocused (const bool bIsFocused); + void SetAccessibleName (const ::rtl::OUString& rsName); + + void FireAccessibleEvent ( + const sal_Int16 nEventId, + const cssu::Any& rOldValue, + const cssu::Any& rNewValue); + + void UpdateStateSet (void); + + //----- XComponent --------------------------------------------------- + + virtual void SAL_CALL dispose()throw (cssu::RuntimeException) + { WeakComponentImplHelperBase::dispose(); } + virtual void SAL_CALL addEventListener(const cssu::Reference< ::com::sun::star::lang::XEventListener > & xListener)throw (cssu::RuntimeException) + { WeakComponentImplHelperBase::addEventListener(xListener); } + virtual void SAL_CALL removeEventListener(const cssu::Reference< ::com::sun::star::lang::XEventListener > & xListener)throw (cssu::RuntimeException) + { WeakComponentImplHelperBase::removeEventListener(xListener); } + + //----- XAccessible ------------------------------------------------------- + + virtual cssu::Reference<cssa::XAccessibleContext> SAL_CALL + getAccessibleContext (void) + throw (cssu::RuntimeException); + + + //----- XAccessibleContext ---------------------------------------------- + + virtual sal_Int32 SAL_CALL getAccessibleChildCount (void) + throw (cssu::RuntimeException); + + virtual cssu::Reference< cssa::XAccessible> SAL_CALL + getAccessibleChild (sal_Int32 nIndex) + throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException); + + virtual cssu::Reference< cssa::XAccessible> SAL_CALL getAccessibleParent (void) + throw (cssu::RuntimeException); + + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent (void) + throw (cssu::RuntimeException); + + virtual sal_Int16 SAL_CALL getAccessibleRole (void) + throw (cssu::RuntimeException); + + virtual ::rtl::OUString SAL_CALL getAccessibleDescription (void) + throw (cssu::RuntimeException); + + virtual ::rtl::OUString SAL_CALL getAccessibleName (void) + throw (cssu::RuntimeException); + + virtual cssu::Reference<cssa::XAccessibleRelationSet> SAL_CALL + getAccessibleRelationSet (void) + throw (cssu::RuntimeException); + + virtual cssu::Reference<cssa::XAccessibleStateSet> SAL_CALL + getAccessibleStateSet (void) + throw (cssu::RuntimeException); + + virtual css::lang::Locale SAL_CALL getLocale (void) + throw (cssu::RuntimeException, + cssa::IllegalAccessibleComponentStateException); + + + //----- XAccessibleComponent -------------------------------------------- + + virtual sal_Bool SAL_CALL containsPoint ( + const css::awt::Point& aPoint) + throw (cssu::RuntimeException); + + virtual cssu::Reference<cssa::XAccessible> SAL_CALL + getAccessibleAtPoint ( + const css::awt::Point& aPoint) + throw (cssu::RuntimeException); + + virtual css::awt::Rectangle SAL_CALL getBounds (void) + throw (cssu::RuntimeException); + + virtual css::awt::Point SAL_CALL getLocation (void) + throw (cssu::RuntimeException); + + virtual css::awt::Point SAL_CALL getLocationOnScreen (void) + throw (cssu::RuntimeException); + + virtual css::awt::Size SAL_CALL getSize (void) + throw (cssu::RuntimeException); + + virtual void SAL_CALL grabFocus (void) + throw (cssu::RuntimeException); + + virtual sal_Int32 SAL_CALL getForeground (void) + throw (cssu::RuntimeException); + + virtual sal_Int32 SAL_CALL getBackground (void) + throw (cssu::RuntimeException); + + + //----- XAccessibleEventBroadcaster -------------------------------------- + + virtual void SAL_CALL addEventListener ( + const cssu::Reference<cssa::XAccessibleEventListener>& rxListener) + throw (cssu::RuntimeException); + + virtual void SAL_CALL removeEventListener ( + const cssu::Reference<cssa::XAccessibleEventListener>& rxListener) + throw (cssu::RuntimeException); + + //----- XWindowListener --------------------------------------------------- + + virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) + throw (cssu::RuntimeException); + + virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) + throw (cssu::RuntimeException); + + virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) + throw (cssu::RuntimeException); + + virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) + throw (cssu::RuntimeException); + + + //----- XEventListener ---------------------------------------------------- + + virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) + throw (cssu::RuntimeException); + + +protected: + ::rtl::OUString msName; + cssu::Reference<css::awt::XWindow2> mxContentWindow; + cssu::Reference<css::awt::XWindow2> mxBorderWindow; + const css::lang::Locale maLocale; + const sal_Int16 mnRole; + sal_uInt32 mnStateSet; + bool mbIsFocused; + cssu::Reference<cssa::XAccessible> mxParentAccessible; + ::std::vector<rtl::Reference<AccessibleObject> > maChildren; + ::std::vector<Reference<XAccessibleEventListener> > maListeners; + + virtual awt::Point GetRelativeLocation (void); + virtual awt::Size GetSize (void); + virtual awt::Point GetAbsoluteParentLocation (void); + + virtual bool GetWindowState (const sal_Int16 nType) const; + + void UpdateState (const sal_Int16 aState, const bool bValue); + + sal_Bool IsDisposed (void) const; + + void ThrowIfDisposed (void) const + throw (css::lang::DisposedException); + + enum ExceptionType { ET_Runtime, ET_Disposed, ET_IndexOutOfBounds }; + void ThrowException (const sal_Char* pMessage, const ExceptionType eExceptionType) const; +}; + + + + +//===== AccessibleStateSet ==================================================== + +namespace { +typedef ::cppu::WeakComponentImplHelper1 < + cssa::XAccessibleStateSet + > AccessibleStateSetInterfaceBase; +} + +class AccessibleStateSet + : public ::cppu::BaseMutex, + public AccessibleStateSetInterfaceBase +{ +public: + AccessibleStateSet (const sal_Int32 nStateSet); + virtual ~AccessibleStateSet (void); + + static sal_uInt32 GetStateMask (const sal_Int16 nType); + + //----- XAccessibleStateSet ----------------------------------------------- + + virtual sal_Bool SAL_CALL isEmpty (void) + throw (cssu::RuntimeException); + + virtual sal_Bool SAL_CALL contains (sal_Int16 nState) + throw (cssu::RuntimeException); + + virtual sal_Bool SAL_CALL containsAll (const cssu::Sequence<sal_Int16>& rStateSet) + throw (cssu::RuntimeException); + + virtual cssu::Sequence<sal_Int16> SAL_CALL getStates (void) + throw (cssu::RuntimeException); + +private: + const sal_Int32 mnStateSet; +}; + + + + +//===== AccessibleRelationSet ================================================= + +namespace { +typedef ::cppu::WeakComponentImplHelper1 < + cssa::XAccessibleRelationSet + > AccessibleRelationSetInterfaceBase; +} + +class AccessibleRelationSet + : public ::cppu::BaseMutex, + public AccessibleRelationSetInterfaceBase +{ +public: + AccessibleRelationSet (void); + virtual ~AccessibleRelationSet (void); + + void AddRelation ( + const sal_Int16 nRelationType, + const Reference<XInterface>& rxObject); + + + //----- XAccessibleRelationSet -------------------------------------------- + + virtual sal_Int32 SAL_CALL getRelationCount (void) + throw (cssu::RuntimeException); + + virtual AccessibleRelation SAL_CALL getRelation (sal_Int32 nIndex) + throw (cssu::RuntimeException, css::lang::IndexOutOfBoundsException); + + virtual sal_Bool SAL_CALL containsRelation (sal_Int16 nRelationType) + throw (cssu::RuntimeException); + + virtual AccessibleRelation SAL_CALL getRelationByType (sal_Int16 nRelationType) + throw (cssu::RuntimeException); + +private: + ::std::vector<AccessibleRelation> maRelations; +}; + + + + +//===== PresenterAccessibleParagraph ========================================== + +namespace { +typedef ::cppu::ImplInheritanceHelper1 < + PresenterAccessible::AccessibleObject, + cssa::XAccessibleText + > PresenterAccessibleParagraphInterfaceBase; +} + + + + +class PresenterAccessible::AccessibleParagraph + : public PresenterAccessibleParagraphInterfaceBase +{ +public: + AccessibleParagraph ( + const css::lang::Locale aLocale, + const sal_Int16 nRole, + const ::rtl::OUString& rsName, + const SharedPresenterTextParagraph& rpParagraph, + const sal_Int32 nParagraphIndex); + + virtual ~AccessibleParagraph (void); + + + //----- XAccessibleContext ------------------------------------------------ + + virtual cssu::Reference<cssa::XAccessibleRelationSet> SAL_CALL + getAccessibleRelationSet (void) + throw (cssu::RuntimeException); + + + //----- XAccessibleText --------------------------------------------------- + + virtual sal_Int32 SAL_CALL getCaretPosition (void) + throw (cssu::RuntimeException); + + virtual sal_Bool SAL_CALL setCaretPosition (sal_Int32 nIndex) + throw (::com::sun::star::lang::IndexOutOfBoundsException, cssu::RuntimeException); + + virtual sal_Unicode SAL_CALL getCharacter (sal_Int32 nIndex) + throw (::com::sun::star::lang::IndexOutOfBoundsException, cssu::RuntimeException); + + virtual cssu::Sequence<css::beans::PropertyValue> SAL_CALL + getCharacterAttributes ( + ::sal_Int32 nIndex, + const cssu::Sequence<rtl::OUString>& rRequestedAttributes) + throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException); + + virtual css::awt::Rectangle SAL_CALL getCharacterBounds (sal_Int32 nIndex) + throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException); + + virtual sal_Int32 SAL_CALL getCharacterCount (void) + throw (cssu::RuntimeException); + + virtual sal_Int32 SAL_CALL getIndexAtPoint (const css::awt::Point& rPoint) + throw (cssu::RuntimeException); + + virtual ::rtl::OUString SAL_CALL getSelectedText (void) + throw (cssu::RuntimeException); + + virtual sal_Int32 SAL_CALL getSelectionStart (void) + throw (cssu::RuntimeException); + + virtual sal_Int32 SAL_CALL getSelectionEnd (void) + throw (cssu::RuntimeException); + + virtual sal_Bool SAL_CALL setSelection (sal_Int32 nStartIndex, sal_Int32 nEndIndex) + throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException); + + virtual ::rtl::OUString SAL_CALL getText (void) + throw (cssu::RuntimeException); + + virtual ::rtl::OUString SAL_CALL getTextRange ( + sal_Int32 nStartIndex, + sal_Int32 nEndIndex) + throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException); + + virtual cssa::TextSegment SAL_CALL getTextAtIndex ( + sal_Int32 nIndex, + sal_Int16 nTextType) + throw (css::lang::IndexOutOfBoundsException, + css::lang::IllegalArgumentException, + cssu::RuntimeException); + + virtual cssa::TextSegment SAL_CALL getTextBeforeIndex ( + sal_Int32 nIndex, + sal_Int16 nTextType) + throw (css::lang::IndexOutOfBoundsException, + css::lang::IllegalArgumentException, + cssu::RuntimeException); + + virtual cssa::TextSegment SAL_CALL getTextBehindIndex ( + sal_Int32 nIndex, + sal_Int16 nTextType) + throw (css::lang::IndexOutOfBoundsException, + css::lang::IllegalArgumentException, + cssu::RuntimeException); + + virtual ::sal_Bool SAL_CALL copyText (sal_Int32 nStartIndex, sal_Int32 nEndIndex) + throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException); + + +protected: + virtual awt::Point GetRelativeLocation (void); + virtual awt::Size GetSize (void); + virtual awt::Point GetAbsoluteParentLocation (void); + virtual bool GetWindowState (const sal_Int16 nType) const; + +private: + SharedPresenterTextParagraph mpParagraph; + const sal_Int32 mnParagraphIndex; +}; + + + + +//===== AccessibleConsole ===================================================== + +class AccessibleConsole +{ +public: + static rtl::Reference<PresenterAccessible::AccessibleObject> Create ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const lang::Locale aLocale) + { + OUString sName (A2S("Presenter Console")); + PresenterConfigurationAccess aConfiguration ( + rxContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.extension.PresenterScreen/")), + PresenterConfigurationAccess::READ_ONLY); + aConfiguration.GetConfigurationNode(A2S("Presenter/Accessibility/Console/String")) + >>= sName; + + rtl::Reference<PresenterAccessible::AccessibleObject> pObject ( + new PresenterAccessible::AccessibleObject( + aLocale, AccessibleRole::PANEL, sName)); + pObject->LateInitialization(); + pObject->UpdateStateSet(); + + return pObject; + } +}; + + + + +//===== AccessiblePreview ===================================================== + +class AccessiblePreview +{ +public: + static rtl::Reference<PresenterAccessible::AccessibleObject> Create ( + const Reference<css::uno::XComponentContext>& rxContext, + const lang::Locale aLocale, + const Reference<awt::XWindow>& rxContentWindow, + const Reference<awt::XWindow>& rxBorderWindow) + { + OUString sName (A2S("Presenter Notes Window")); + { + PresenterConfigurationAccess aConfiguration ( + rxContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.extension.PresenterScreen/")), + PresenterConfigurationAccess::READ_ONLY); + aConfiguration.GetConfigurationNode(A2S("Presenter/Accessibility/Preview/String")) + >>= sName; + } + + rtl::Reference<PresenterAccessible::AccessibleObject> pObject ( + new PresenterAccessible::AccessibleObject( + aLocale, + AccessibleRole::LABEL, + sName)); + pObject->LateInitialization(); + pObject->UpdateStateSet(); + pObject->SetWindow(rxContentWindow, rxBorderWindow); + + return pObject; + } +}; + + + + +//===== AccessibleNotes ======================================================= + +class AccessibleNotes : public PresenterAccessible::AccessibleObject +{ +public: + AccessibleNotes ( + const css::lang::Locale aLocale, + const sal_Int16 nRole, + const ::rtl::OUString& rsName); + + + static rtl::Reference<PresenterAccessible::AccessibleObject> Create ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const lang::Locale aLocale, + const Reference<awt::XWindow>& rxContentWindow, + const Reference<awt::XWindow>& rxBorderWindow, + const ::boost::shared_ptr<PresenterTextView>& rpTextView); + + void SetTextView (const ::boost::shared_ptr<PresenterTextView>& rpTextView); + + virtual void SetWindow ( + const cssu::Reference<css::awt::XWindow>& rxContentWindow, + const cssu::Reference<css::awt::XWindow>& rxBorderWindow); + +private: + ::boost::shared_ptr<PresenterTextView> mpTextView; + + void NotifyCaretChange ( + const sal_Int32 nOldParagraphIndex, + const sal_Int32 nOldCharacterIndex, + const sal_Int32 nNewParagraphIndex, + const sal_Int32 nNewCharacterIndex); + void HandleTextChange (void); +}; + + + + +//===== AccessibleFocusManager ================================================ + +/** A singleton class that makes sure that only one accessibility object in + the PresenterConsole hierarchy has the focus. +*/ +class AccessibleFocusManager +{ +public: + static ::boost::shared_ptr<AccessibleFocusManager> Instance (void); + + void AddFocusableObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject); + void RemoveFocusableObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject); + + void FocusObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject); + +private: + static ::boost::shared_ptr<AccessibleFocusManager> mpInstance; + ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> > maFocusableObjects; + + AccessibleFocusManager (void); +}; + + + + +//===== PresenterAccessible =================================================== + +PresenterAccessible::PresenterAccessible ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const Reference<drawing::framework::XPane>& rxMainPane) + : PresenterAccessibleInterfaceBase(m_aMutex), + mxComponentContext(rxContext), + mpPresenterController(rpPresenterController), + mxMainPaneId(rxMainPane.is() ? rxMainPane->getResourceId() : Reference<XResourceId>()), + mxMainPane(rxMainPane, UNO_QUERY), + mxMainWindow(), + mxPreviewContentWindow(), + mxPreviewBorderWindow(), + mxNotesContentWindow(), + mxNotesBorderWindow(), + mpAccessibleConsole(), + mpAccessiblePreview(), + mpAccessibleNotes(), + mxAccessibleParent() +{ + if (mxMainPane.is()) + mxMainPane->setAccessible(this); +} + + + + +PresenterAccessible::~PresenterAccessible (void) +{ +} + + + + +PresenterPaneContainer::SharedPaneDescriptor PresenterAccessible::GetPreviewPane (void) const +{ + PresenterPaneContainer::SharedPaneDescriptor pPreviewPane; + + if ( ! mpPresenterController.is()) + return pPreviewPane; + + rtl::Reference<PresenterPaneContainer> pContainer (mpPresenterController->GetPaneContainer()); + if ( ! pContainer.is()) + return pPreviewPane; + + pPreviewPane = pContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL); + Reference<drawing::framework::XPane> xPreviewPane; + if (pPreviewPane) + xPreviewPane = pPreviewPane->mxPane.get(); + if ( ! xPreviewPane.is()) + { + pPreviewPane = pContainer->FindPaneURL(PresenterPaneFactory::msSlideSorterPaneURL); + } + return pPreviewPane; +} + + + + +void PresenterAccessible::UpdateAccessibilityHierarchy (void) +{ + if ( ! mpPresenterController.is()) + return; + + Reference<drawing::framework::XConfigurationController> xConfigurationController( + mpPresenterController->GetConfigurationController()); + if ( ! xConfigurationController.is()) + return; + + rtl::Reference<PresenterPaneContainer> pPaneContainer ( + mpPresenterController->GetPaneContainer()); + if ( ! pPaneContainer.is()) + return; + + if ( ! mpAccessibleConsole.is()) + return; + + // Get the preview pane (standard or notes view) or the slide overview + // pane. + PresenterPaneContainer::SharedPaneDescriptor pPreviewPane(GetPreviewPane()); + Reference<drawing::framework::XPane> xPreviewPane; + if (pPreviewPane) + xPreviewPane = pPreviewPane->mxPane.get(); + + // Get the notes pane. + PresenterPaneContainer::SharedPaneDescriptor pNotesPane( + pPaneContainer->FindPaneURL(PresenterPaneFactory::msNotesPaneURL)); + Reference<drawing::framework::XPane> xNotesPane; + if (pNotesPane) + xNotesPane = pNotesPane->mxPane.get(); + + // Get the notes view. + Reference<drawing::framework::XView> xNotesView; + if (pNotesPane) + xNotesView = pNotesPane->mxView; + rtl::Reference<PresenterNotesView> pNotesView ( + dynamic_cast<PresenterNotesView*>(xNotesView.get())); + + UpdateAccessibilityHierarchy( + pPreviewPane ? pPreviewPane->mxContentWindow : Reference<awt::XWindow>(), + pPreviewPane ? pPreviewPane->mxBorderWindow : Reference<awt::XWindow>(), + (pPreviewPane&&pPreviewPane->mxPane.is()) ? pPreviewPane->mxPane->GetTitle() : OUString(), + pNotesPane ? pNotesPane->mxContentWindow : Reference<awt::XWindow>(), + pNotesPane ? pNotesPane->mxBorderWindow : Reference<awt::XWindow>(), + pNotesView.is() + ? pNotesView->GetTextView() + : ::boost::shared_ptr<PresenterTextView>()); +} + + + + + +void PresenterAccessible::UpdateAccessibilityHierarchy ( + const Reference<awt::XWindow>& rxPreviewContentWindow, + const Reference<awt::XWindow>& rxPreviewBorderWindow, + const ::rtl::OUString& rsTitle, + const Reference<awt::XWindow>& rxNotesContentWindow, + const Reference<awt::XWindow>& rxNotesBorderWindow, + const ::boost::shared_ptr<PresenterTextView>& rpNotesTextView) +{ + if ( ! mpAccessibleConsole.is()) + return; + + if (mxPreviewContentWindow != rxPreviewContentWindow) + { + if (mpAccessiblePreview.is()) + { + mpAccessibleConsole->RemoveChild(mpAccessiblePreview); + mpAccessiblePreview = NULL; + } + + mxPreviewContentWindow = rxPreviewContentWindow; + mxPreviewBorderWindow = rxPreviewBorderWindow; + + if (mxPreviewContentWindow.is()) + { + mpAccessiblePreview = AccessiblePreview::Create( + mxComponentContext, + lang::Locale(), + mxPreviewContentWindow, + mxPreviewBorderWindow); + mpAccessibleConsole->AddChild(mpAccessiblePreview); + mpAccessiblePreview->SetAccessibleName(rsTitle); + } + } + + if (mxNotesContentWindow != rxNotesContentWindow) + { + if (mpAccessibleNotes.is()) + { + mpAccessibleConsole->RemoveChild(mpAccessibleConsole.get()); + mpAccessibleNotes = NULL; + } + + mxNotesContentWindow = rxNotesContentWindow; + mxNotesBorderWindow = rxNotesBorderWindow; + + if (mxNotesContentWindow.is()) + { + mpAccessibleNotes = AccessibleNotes::Create( + mxComponentContext, + lang::Locale(), + mxNotesContentWindow, + mxNotesBorderWindow, + rpNotesTextView); + mpAccessibleConsole->AddChild(mpAccessibleNotes.get()); + } + } +} + + + + +void PresenterAccessible::NotifyCurrentSlideChange ( + const sal_Int32 nCurrentSlideIndex, + const sal_Int32 nSlideCount) +{ + (void)nCurrentSlideIndex; + (void)nSlideCount; + + if (mpAccessiblePreview.is()) + { + PresenterPaneContainer::SharedPaneDescriptor pPreviewPane (GetPreviewPane()); + mpAccessiblePreview->SetAccessibleName( + (pPreviewPane&&pPreviewPane->mxPane.is() + ? pPreviewPane->mxPane->GetTitle() + : rtl::OUString())); + } + + // Play some focus ping-pong to trigger AT tools. + //AccessibleFocusManager::Instance()->FocusObject(mpAccessibleConsole); + AccessibleFocusManager::Instance()->FocusObject(mpAccessiblePreview); +} + + + + +bool PresenterAccessible::IsAccessibilityActive (void) const +{ + return mpAccessibleConsole.is(); +} + + + + +void SAL_CALL PresenterAccessible::disposing (void) +{ + UpdateAccessibilityHierarchy( + NULL, + NULL, + OUString(), + NULL, + NULL, + ::boost::shared_ptr<PresenterTextView>()); + + if (mxMainWindow.is()) + { + mxMainWindow->removeFocusListener(this); + + if (mxMainPane.is()) + mxMainPane->setAccessible(NULL); + } + + mpAccessiblePreview = NULL; + mpAccessibleNotes = NULL; + mpAccessibleConsole = NULL; +} + + + + +//----- XAccessible ----------------------------------------------------------- + +Reference<XAccessibleContext> SAL_CALL PresenterAccessible::getAccessibleContext (void) + throw (cssu::RuntimeException) +{ + if ( ! mpAccessibleConsole.is()) + { + Reference<XPane> xMainPane (mxMainPane, UNO_QUERY); + if (xMainPane.is()) + { + mxMainWindow = Reference<awt::XWindow>(xMainPane->getWindow(), UNO_QUERY); + mxMainWindow->addFocusListener(this); + } + mpAccessibleConsole = AccessibleConsole::Create( + mxComponentContext, css::lang::Locale()); + mpAccessibleConsole->SetWindow(mxMainWindow, NULL); + mpAccessibleConsole->SetAccessibleParent(mxAccessibleParent); + UpdateAccessibilityHierarchy(); + if (mpPresenterController.is()) + mpPresenterController->SetAccessibilityActiveState(true); + } + return mpAccessibleConsole->getAccessibleContext(); +} + + + + + +//----- XFocusListener ---------------------------------------------------- + +void SAL_CALL PresenterAccessible::focusGained (const css::awt::FocusEvent& rEvent) + throw (cssu::RuntimeException) +{ + (void)rEvent; + +#ifdef VERBOSE + OSL_TRACE("PresenterAccessible::focusGained at %x and window %x\r", this, + mxMainWindow.get()); +#endif + + AccessibleFocusManager::Instance()->FocusObject(mpAccessibleConsole); +} + + + + +void SAL_CALL PresenterAccessible::focusLost (const css::awt::FocusEvent& rEvent) + throw (cssu::RuntimeException) +{ + (void)rEvent; + +#ifdef VERBOSE + OSL_TRACE("PresenterAccessible::focusLost at %x\r", this); +#endif + + AccessibleFocusManager::Instance()->FocusObject(NULL); +} + + + + +//----- XEventListener ---------------------------------------------------- + +void SAL_CALL PresenterAccessible::disposing (const css::lang::EventObject& rEvent) + throw (cssu::RuntimeException) +{ + if (rEvent.Source == mxMainWindow) + mxMainWindow = NULL; +} + + + + +//----- XInitialize ----------------------------------------------------------- + +void SAL_CALL PresenterAccessible::initialize (const cssu::Sequence<cssu::Any>& rArguments) + throw (cssu::RuntimeException) +{ + if (rArguments.getLength() >= 1) + { + mxAccessibleParent = Reference<XAccessible>(rArguments[0], UNO_QUERY); + if (mpAccessibleConsole.is()) + mpAccessibleConsole->SetAccessibleParent(mxAccessibleParent); + } +} + + + + +//===== PresenterAccessible::AccessibleObject ========================================= + +PresenterAccessible::AccessibleObject::AccessibleObject ( + const lang::Locale aLocale, + const sal_Int16 nRole, + const OUString& rsName) + : PresenterAccessibleObjectInterfaceBase(m_aMutex), + msName(rsName), + mxContentWindow(), + mxBorderWindow(), + maLocale(aLocale), + mnRole(nRole), + mnStateSet(0), + mbIsFocused(false), + mxParentAccessible(), + maChildren(), + maListeners() +{ +} + + + + +void PresenterAccessible::AccessibleObject::LateInitialization (void) +{ + AccessibleFocusManager::Instance()->AddFocusableObject(this); +} + + + + +PresenterAccessible::AccessibleObject::~AccessibleObject (void) +{ +} + + + + +void PresenterAccessible::AccessibleObject::SetWindow ( + const Reference<awt::XWindow>& rxContentWindow, + const Reference<awt::XWindow>& rxBorderWindow) +{ + Reference<awt::XWindow2> xContentWindow (rxContentWindow, UNO_QUERY); + + if (mxContentWindow.get() != xContentWindow.get()) + { + if (mxContentWindow.is()) + { + mxContentWindow->removeWindowListener(this); + } + + mxContentWindow = xContentWindow; + mxBorderWindow = Reference<awt::XWindow2>(rxBorderWindow, UNO_QUERY); + + if (mxContentWindow.is()) + { + mxContentWindow->addWindowListener(this); + } + + UpdateStateSet(); + } +} + + + + +void PresenterAccessible::AccessibleObject::SetAccessibleParent ( + const Reference<XAccessible>& rxAccessibleParent) +{ + mxParentAccessible = rxAccessibleParent; +} + + + + +void SAL_CALL PresenterAccessible::AccessibleObject::disposing (void) +{ + AccessibleFocusManager::Instance()->RemoveFocusableObject(this); + SetWindow(NULL, NULL); +} + + + + +//----- XAccessible ------------------------------------------------------- + +Reference<XAccessibleContext> SAL_CALL + PresenterAccessible::AccessibleObject::getAccessibleContext (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + return this; +} + + + + +//----- XAccessibleContext ---------------------------------------------- + +sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleChildCount (void) + throw (cssu::RuntimeException) +{ + ThrowIfDisposed(); + + const sal_Int32 nChildCount (maChildren.size()); + + return nChildCount; +} + + + + +Reference<XAccessible> SAL_CALL + PresenterAccessible::AccessibleObject::getAccessibleChild (sal_Int32 nIndex) + throw (lang::IndexOutOfBoundsException, RuntimeException) +{ + ThrowIfDisposed(); + + if (nIndex<0 || nIndex>=sal_Int32(maChildren.size())) + ThrowException("invalid child index", ET_IndexOutOfBounds); + + return Reference<XAccessible>(maChildren[nIndex].get()); +} + + + + +Reference<XAccessible> SAL_CALL + PresenterAccessible::AccessibleObject::getAccessibleParent (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + return mxParentAccessible; +} + + + + +sal_Int32 SAL_CALL + PresenterAccessible::AccessibleObject::getAccessibleIndexInParent (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + const Reference<XAccessible> xThis (this); + if (mxParentAccessible.is()) + { + const Reference<XAccessibleContext> xContext (mxParentAccessible->getAccessibleContext()); + for (sal_Int32 nIndex=0,nCount=xContext->getAccessibleChildCount(); + nIndex<nCount; + ++nIndex) + { + if (xContext->getAccessibleChild(nIndex) == xThis) + return nIndex; + } + } + + return 0; +} + + + + +sal_Int16 SAL_CALL + PresenterAccessible::AccessibleObject::getAccessibleRole (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + return mnRole; +} + + + + +OUString SAL_CALL + PresenterAccessible::AccessibleObject::getAccessibleDescription (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + return msName; +} + + + + +OUString SAL_CALL + PresenterAccessible::AccessibleObject::getAccessibleName (void) + throw (cssu::RuntimeException) +{ + ThrowIfDisposed(); + + return msName; +} + + + + +Reference<XAccessibleRelationSet> SAL_CALL + PresenterAccessible::AccessibleObject::getAccessibleRelationSet (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + return NULL; +} + + + + +Reference<XAccessibleStateSet> SAL_CALL + PresenterAccessible::AccessibleObject::getAccessibleStateSet (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + return Reference<XAccessibleStateSet>(new AccessibleStateSet(mnStateSet)); +} + + + + +lang::Locale SAL_CALL + PresenterAccessible::AccessibleObject::getLocale (void) + throw (RuntimeException, + IllegalAccessibleComponentStateException) +{ + ThrowIfDisposed(); + + if (mxParentAccessible.is()) + { + Reference<XAccessibleContext> xParentContext (mxParentAccessible->getAccessibleContext()); + if (xParentContext.is()) + return xParentContext->getLocale(); + } + return maLocale; +} + + + + +//----- XAccessibleComponent ------------------------------------------------ + +sal_Bool SAL_CALL PresenterAccessible::AccessibleObject::containsPoint ( + const awt::Point& rPoint) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + if (mxContentWindow.is()) + { + const awt::Rectangle aBox (getBounds()); + return rPoint.X>=aBox.X + && rPoint.Y>=aBox.Y + && rPoint.X<aBox.X+aBox.Width + && rPoint.Y<aBox.Y+aBox.Height; + } + else + return false; +} + + + + +Reference<XAccessible> SAL_CALL + PresenterAccessible::AccessibleObject::getAccessibleAtPoint (const awt::Point& rPoint) + throw (RuntimeException) +{ + (void)rPoint; + ThrowIfDisposed(); + + return Reference<XAccessible>(); +} + + + + +awt::Rectangle SAL_CALL PresenterAccessible::AccessibleObject::getBounds (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + awt::Rectangle aBox; + + const awt::Point aLocation (GetRelativeLocation()); + const awt::Size aSize (GetSize()); + + return awt::Rectangle (aLocation.X, aLocation.Y, aSize.Width, aSize.Height); +} + + + + +awt::Point SAL_CALL PresenterAccessible::AccessibleObject::getLocation (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + const awt::Point aLocation (GetRelativeLocation()); + + return aLocation; +} + + + + +awt::Point SAL_CALL PresenterAccessible::AccessibleObject::getLocationOnScreen (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + awt::Point aRelativeLocation (GetRelativeLocation()); + awt::Point aParentLocationOnScreen (GetAbsoluteParentLocation()); + + return awt::Point( + aRelativeLocation.X + aParentLocationOnScreen.X, + aRelativeLocation.Y + aParentLocationOnScreen.Y); +} + + + + +awt::Size SAL_CALL PresenterAccessible::AccessibleObject::getSize (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + const awt::Size aSize (GetSize()); + + return aSize; +} + + + + +void SAL_CALL PresenterAccessible::AccessibleObject::grabFocus (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + if (mxBorderWindow.is()) + mxBorderWindow->setFocus(); + else if (mxContentWindow.is()) + mxContentWindow->setFocus(); +} + + + + +sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getForeground (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + return 0x00ffffff; +} + + + + +sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getBackground (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + return 0x00000000; +} + + + + +//----- XAccessibleEventBroadcaster ------------------------------------------- + +void SAL_CALL PresenterAccessible::AccessibleObject::addEventListener ( + const Reference<XAccessibleEventListener>& rxListener) + throw (RuntimeException) +{ + if (rxListener.is()) + { + const osl::MutexGuard aGuard(m_aMutex); + + if (IsDisposed()) + { + uno::Reference<uno::XInterface> xThis (static_cast<XWeak*>(this), UNO_QUERY); + rxListener->disposing (lang::EventObject(xThis)); + } + else + { + maListeners.push_back(rxListener); + } + } +} + + + + +void SAL_CALL PresenterAccessible::AccessibleObject::removeEventListener ( + const Reference<XAccessibleEventListener>& rxListener) + throw (RuntimeException) +{ + ThrowIfDisposed(); + if (rxListener.is()) + { + const osl::MutexGuard aGuard(m_aMutex); + + maListeners.erase(std::remove(maListeners.begin(), maListeners.end(), rxListener)); + } +} + + + + +//----- XWindowListener --------------------------------------------------- + +void SAL_CALL PresenterAccessible::AccessibleObject::windowResized ( + const css::awt::WindowEvent& rEvent) + throw (cssu::RuntimeException) +{ + (void)rEvent; + + FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any()); +} + + + + +void SAL_CALL PresenterAccessible::AccessibleObject::windowMoved ( + const css::awt::WindowEvent& rEvent) + throw (cssu::RuntimeException) +{ + (void)rEvent; + + FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any()); +} + + + + +void SAL_CALL PresenterAccessible::AccessibleObject::windowShown ( + const css::lang::EventObject& rEvent) + throw (cssu::RuntimeException) +{ + (void)rEvent; + UpdateStateSet(); +} + + + + +void SAL_CALL PresenterAccessible::AccessibleObject::windowHidden ( + const css::lang::EventObject& rEvent) + throw (cssu::RuntimeException) +{ + (void)rEvent; + UpdateStateSet(); +} + + + + +//----- XEventListener -------------------------------------------------------- + +void SAL_CALL PresenterAccessible::AccessibleObject::disposing (const css::lang::EventObject& rEvent) + throw (cssu::RuntimeException) +{ + if (rEvent.Source == mxContentWindow) + { + mxContentWindow = NULL; + mxBorderWindow = NULL; + } + else + { + SetWindow(NULL, NULL); + } +} + + + + +//----- private --------------------------------------------------------------- + +bool PresenterAccessible::AccessibleObject::GetWindowState (const sal_Int16 nType) const +{ + switch (nType) + { + case AccessibleStateType::ENABLED: + return mxContentWindow.is() && mxContentWindow->isEnabled(); + + case AccessibleStateType::FOCUSABLE: + return true; + + case AccessibleStateType::FOCUSED: + return mbIsFocused; + + case AccessibleStateType::SHOWING: + return mxContentWindow.is() && mxContentWindow->isVisible(); + + default: + return false; + } +} + + + + +void PresenterAccessible::AccessibleObject::UpdateStateSet (void) +{ + UpdateState(AccessibleStateType::FOCUSABLE, true); + UpdateState(AccessibleStateType::VISIBLE, true); + UpdateState(AccessibleStateType::ENABLED, true); + UpdateState(AccessibleStateType::MULTI_LINE, true); + UpdateState(AccessibleStateType::SENSITIVE, true); + + UpdateState(AccessibleStateType::ENABLED, GetWindowState(AccessibleStateType::ENABLED)); + UpdateState(AccessibleStateType::FOCUSED, GetWindowState(AccessibleStateType::FOCUSED)); + UpdateState(AccessibleStateType::SHOWING, GetWindowState(AccessibleStateType::SHOWING)); + // UpdateState(AccessibleStateType::ACTIVE, GetWindowState(AccessibleStateType::ACTIVE)); +} + + + + +void PresenterAccessible::AccessibleObject::UpdateState( + const sal_Int16 nState, + const bool bValue) +{ + const sal_uInt32 nStateMask (AccessibleStateSet::GetStateMask(nState)); + if (((mnStateSet & nStateMask)!=0) != bValue) + { + if (bValue) + { + mnStateSet |= nStateMask; + FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(), Any(nState)); + } + else + { + mnStateSet &= ~nStateMask; + FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(nState), Any()); + } + } +} + + + + +void PresenterAccessible::AccessibleObject::AddChild ( + const ::rtl::Reference<AccessibleObject>& rpChild) +{ + maChildren.push_back(rpChild); + rpChild->SetAccessibleParent(this); + FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any()); +} + + + + +void PresenterAccessible::AccessibleObject::RemoveChild ( + const ::rtl::Reference<AccessibleObject>& rpChild) +{ + rpChild->SetAccessibleParent(Reference<XAccessible>()); + maChildren.erase(::std::find(maChildren.begin(), maChildren.end(), rpChild)); + FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any()); +} + + + + +void PresenterAccessible::AccessibleObject::SetIsFocused (const bool bIsFocused) +{ + if (mbIsFocused != bIsFocused) + { + mbIsFocused = bIsFocused; + UpdateStateSet(); + } +} + + + + +void PresenterAccessible::AccessibleObject::SetAccessibleName (const ::rtl::OUString& rsName) +{ + if (msName != rsName) + { + const OUString sOldName(msName); + msName = rsName; + FireAccessibleEvent(AccessibleEventId::NAME_CHANGED, Any(sOldName), Any(msName)); + } +} + + + + +void PresenterAccessible::AccessibleObject::FireAccessibleEvent ( + const sal_Int16 nEventId, + const uno::Any& rOldValue, + const uno::Any& rNewValue ) +{ + AccessibleEventObject aEventObject; + + aEventObject.Source = Reference<XWeak>(this); + aEventObject.EventId = nEventId; + aEventObject.NewValue = rNewValue; + aEventObject.OldValue = rOldValue; + + ::std::vector<Reference<XAccessibleEventListener> > aListenerCopy(maListeners); + for (::std::vector<Reference<XAccessibleEventListener> >::const_iterator + iListener(aListenerCopy.begin()), + iEnd(aListenerCopy.end()); + iListener!=iEnd; + ++iListener) + { + try + { + (*iListener)->notifyEvent(aEventObject); + } + catch(lang::DisposedException&) + { + // Listener has been disposed and should have been removed + // already. + removeEventListener(*iListener); + } + catch(Exception&) + { + // Ignore all other exceptions and assume that they are + // caused by a temporary problem. + } + } +} + + + +awt::Point PresenterAccessible::AccessibleObject::GetRelativeLocation (void) +{ + awt::Point aLocation; + if (mxContentWindow.is()) + { + const awt::Rectangle aContentBox (mxContentWindow->getPosSize()); + aLocation.X = aContentBox.X; + aLocation.Y = aContentBox.Y; + if (mxBorderWindow.is()) + { + const awt::Rectangle aBorderBox (mxBorderWindow->getPosSize()); + aLocation.X += aBorderBox.X; + aLocation.Y += aBorderBox.Y; + } + } + return aLocation; +} + + + + +awt::Size PresenterAccessible::AccessibleObject::GetSize (void) +{ + if (mxContentWindow.is()) + { + const awt::Rectangle aBox (mxContentWindow->getPosSize()); + return awt::Size(aBox.Width, aBox.Height); + } + else + return awt::Size(); +} + + + + +awt::Point PresenterAccessible::AccessibleObject::GetAbsoluteParentLocation (void) +{ + Reference<XAccessibleComponent> xParentComponent; + if (mxParentAccessible.is()) + xParentComponent = Reference<XAccessibleComponent>( + mxParentAccessible->getAccessibleContext(), UNO_QUERY); + if (xParentComponent.is()) + return xParentComponent->getLocationOnScreen(); + else + return awt::Point(); +} + + + + +sal_Bool PresenterAccessible::AccessibleObject::IsDisposed (void) const +{ + return (rBHelper.bDisposed || rBHelper.bInDispose); +} + + + + +void PresenterAccessible::AccessibleObject::ThrowIfDisposed (void) const + throw (lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + ThrowException("object has already been disposed", ET_Disposed); +} + + + + +void PresenterAccessible::AccessibleObject::ThrowException ( + const sal_Char* pMessage, + const ExceptionType eExceptionType) const +{ + const OUString sMessage (OUString(A2S("PresenterAccessible: ")) + OUString::createFromAscii(pMessage)); + const Reference<XInterface> xObject ( + const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + switch (eExceptionType) + { + default: + case ET_Runtime: + throw RuntimeException(sMessage, xObject); + case ET_Disposed: + throw lang::DisposedException(sMessage, xObject); + case ET_IndexOutOfBounds: + throw lang::IndexOutOfBoundsException(sMessage, xObject); + } +} + + + + + +//===== AccessibleStateSet ==================================================== + +AccessibleStateSet::AccessibleStateSet (const sal_Int32 nStateSet) + : AccessibleStateSetInterfaceBase(m_aMutex), + mnStateSet (nStateSet) +{ +} + + + + +AccessibleStateSet::~AccessibleStateSet (void) +{ +} + + + + +sal_uInt32 AccessibleStateSet::GetStateMask (const sal_Int16 nState) +{ + if (nState<0 || nState>=sal_Int16(sizeof(sal_uInt32)*8)) + { + throw RuntimeException(A2S("AccessibleStateSet::GetStateMask: invalid state"), NULL); + } + + return 1<<nState; +} + + + + +//----- XAccessibleStateSet --------------------------------------------------- + +sal_Bool SAL_CALL AccessibleStateSet::isEmpty (void) + throw (cssu::RuntimeException) +{ + return mnStateSet==0; +} + + + + +sal_Bool SAL_CALL AccessibleStateSet::contains (sal_Int16 nState) + throw (cssu::RuntimeException) +{ + return (mnStateSet & GetStateMask(nState)) != 0; +} + + + + +sal_Bool SAL_CALL AccessibleStateSet::containsAll (const cssu::Sequence<sal_Int16>& rStateSet) + throw (cssu::RuntimeException) +{ + for (sal_Int32 nIndex=0,nCount=rStateSet.getLength(); nIndex<nCount; ++nIndex) + { + if ((mnStateSet & GetStateMask(rStateSet[nIndex])) == 0) + return sal_False; + } + return sal_True; +} + + + + +cssu::Sequence<sal_Int16> SAL_CALL AccessibleStateSet::getStates (void) + throw (cssu::RuntimeException) +{ + ::std::vector<sal_Int16> aStates; + aStates.reserve(sizeof(mnStateSet)*8); + for (sal_uInt16 nIndex=0; nIndex<sizeof(mnStateSet)*8; ++nIndex) + if ((mnStateSet & GetStateMask(nIndex)) != 0) + aStates.push_back(nIndex); + return Sequence<sal_Int16>(&aStates.front(), aStates.size()); +} + + + + +//===== AccessibleRelationSet ================================================= + +AccessibleRelationSet::AccessibleRelationSet (void) + : AccessibleRelationSetInterfaceBase(m_aMutex), + maRelations() +{ +} + + + + +AccessibleRelationSet::~AccessibleRelationSet (void) +{ +} + + + + +void AccessibleRelationSet::AddRelation ( + const sal_Int16 nRelationType, + const Reference<XInterface>& rxObject) +{ + maRelations.resize(maRelations.size()+1); + maRelations.back().RelationType = nRelationType; + maRelations.back().TargetSet.realloc(1); + maRelations.back().TargetSet[0] = rxObject; +} + + + + +//----- XAccessibleRelationSet ------------------------------------------------ + +sal_Int32 SAL_CALL AccessibleRelationSet::getRelationCount (void) + throw (cssu::RuntimeException) +{ + return maRelations.size(); +} + + + + +AccessibleRelation SAL_CALL AccessibleRelationSet::getRelation (sal_Int32 nIndex) + throw (cssu::RuntimeException, css::lang::IndexOutOfBoundsException) +{ + if (nIndex<0 && sal_uInt32(nIndex)>=maRelations.size()) + return AccessibleRelation(); + else + return maRelations[nIndex]; +} + + + + +sal_Bool SAL_CALL AccessibleRelationSet::containsRelation (sal_Int16 nRelationType) + throw (cssu::RuntimeException) +{ + for (::std::vector<AccessibleRelation>::const_iterator iRelation(maRelations.begin()); + iRelation!=maRelations.end(); + ++iRelation) + { + if (iRelation->RelationType == nRelationType) + return sal_True; + } + return sal_False; +} + + + + +AccessibleRelation SAL_CALL AccessibleRelationSet::getRelationByType (sal_Int16 nRelationType) + throw (cssu::RuntimeException) +{ + for (::std::vector<AccessibleRelation>::const_iterator iRelation(maRelations.begin()); + iRelation!=maRelations.end(); + ++iRelation) + { + if (iRelation->RelationType == nRelationType) + return *iRelation; + } + return AccessibleRelation(); +} + + + + +//===== PresenterAccessible::AccessibleParagraph ============================== + +PresenterAccessible::AccessibleParagraph::AccessibleParagraph ( + const lang::Locale aLocale, + const sal_Int16 nRole, + const OUString& rsName, + const SharedPresenterTextParagraph& rpParagraph, + const sal_Int32 nParagraphIndex) + : PresenterAccessibleParagraphInterfaceBase(aLocale, nRole, rsName), + mpParagraph(rpParagraph), + mnParagraphIndex(nParagraphIndex) +{ +} + + + + +PresenterAccessible::AccessibleParagraph::~AccessibleParagraph (void) +{ +} + + + + +//----- XAccessibleContext ---------------------------------------------------- + +Reference<XAccessibleRelationSet> SAL_CALL + PresenterAccessible::AccessibleParagraph::getAccessibleRelationSet (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + rtl::Reference<AccessibleRelationSet> pSet (new AccessibleRelationSet); + + if (mxParentAccessible.is()) + { + Reference<XAccessibleContext> xParentContext (mxParentAccessible->getAccessibleContext()); + if (xParentContext.is()) + { + if (mnParagraphIndex>0) + pSet->AddRelation( + AccessibleRelationType::CONTENT_FLOWS_FROM, + xParentContext->getAccessibleChild(mnParagraphIndex-1)); + + if (mnParagraphIndex<xParentContext->getAccessibleChildCount()-1) + pSet->AddRelation( + AccessibleRelationType::CONTENT_FLOWS_TO, + xParentContext->getAccessibleChild(mnParagraphIndex+1)); + } + } + + return Reference<XAccessibleRelationSet>(pSet.get()); +} + + + + + + +//----- XAccessibleText ------------------------------------------------------- + +sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getCaretPosition (void) + throw (cssu::RuntimeException) +{ + ThrowIfDisposed(); + + sal_Int32 nPosition (-1); + if (mpParagraph) + nPosition = mpParagraph->GetCaretPosition(); + + return nPosition; +} + + + + +sal_Bool SAL_CALL PresenterAccessible::AccessibleParagraph::setCaretPosition (sal_Int32 nIndex) + throw (::com::sun::star::lang::IndexOutOfBoundsException, cssu::RuntimeException) +{ + ThrowIfDisposed(); + + if (mpParagraph) + { + mpParagraph->SetCaretPosition(nIndex); + return sal_True; + } + else + return sal_False; +} + + + + +sal_Unicode SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacter (sal_Int32 nIndex) + throw (::com::sun::star::lang::IndexOutOfBoundsException, cssu::RuntimeException) +{ + ThrowIfDisposed(); + + if (mpParagraph) + return mpParagraph->GetCharacter(nIndex); + else + { + ThrowException("no text support in current mode", ET_IndexOutOfBounds); + // The method above throws an exception and the following line is + // never reached. But there is at least one compiler that can not + // detect this and we need the return to make it happy. + return sal_Unicode(); + } +} + + + + +Sequence<css::beans::PropertyValue> SAL_CALL + PresenterAccessible::AccessibleParagraph::getCharacterAttributes ( + ::sal_Int32 nIndex, + const cssu::Sequence<rtl::OUString>& rRequestedAttributes) + throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException) +{ + ThrowIfDisposed(); + +#ifdef VERBOSE + OSL_TRACE("PresenterAccessible::AccessibleParagraph::getCharacterAttributes at %x,%d returns empty set\r", + this,nIndex); + for (sal_Int32 nAttributeIndex(0),nAttributeCount(rRequestedAttributes.getLength()); + nAttributeIndex<nAttributeCount; + ++nAttributeIndex) + { + OSL_TRACE(" requested attribute %d is %s\r", + nAttributeIndex, + OUStringToOString(rRequestedAttributes[nAttributeIndex], RTL_TEXTENCODING_UTF8).getStr()); + } +#endif + + // Character properties are not supported. + (void)nIndex; + (void)rRequestedAttributes; + return Sequence<css::beans::PropertyValue>(); +} + + + + +awt::Rectangle SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacterBounds ( + sal_Int32 nIndex) + throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException) +{ + ThrowIfDisposed(); + + awt::Rectangle aCharacterBox; + if (nIndex < 0) + { + ThrowException("invalid text index", ET_IndexOutOfBounds); + } + else if (mpParagraph) + { + aCharacterBox = mpParagraph->GetCharacterBounds(nIndex, false); + // Convert coordinates relative to the window origin into absolute + // screen coordinates. + const awt::Point aWindowLocationOnScreen (getLocationOnScreen()); + aCharacterBox.X += aWindowLocationOnScreen.X; + aCharacterBox.Y += aWindowLocationOnScreen.Y; + } + else + { + ThrowException("no text support in current mode", ET_IndexOutOfBounds); + } + + return aCharacterBox; +} + + + + +sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacterCount (void) + throw (cssu::RuntimeException) +{ + ThrowIfDisposed(); + + sal_Int32 nCount (0); + if (mpParagraph) + nCount = mpParagraph->GetCharacterCount(); + + return nCount; +} + + + + +sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getIndexAtPoint ( + const css::awt::Point& rPoint) + throw (cssu::RuntimeException) +{ + ThrowIfDisposed(); + + sal_Int32 nIndex (-1); + if (mpParagraph) + nIndex = mpParagraph->GetIndexAtPoint(rPoint); + + return nIndex; +} + + + + +::rtl::OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectedText (void) + throw (cssu::RuntimeException) +{ + ThrowIfDisposed(); + + return getTextRange(getSelectionStart(), getSelectionEnd()); +} + + + + +sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectionStart (void) + throw (cssu::RuntimeException) +{ + ThrowIfDisposed(); + + return getCaretPosition(); +} + + + + +sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectionEnd (void) + throw (cssu::RuntimeException) +{ + ThrowIfDisposed(); + + return getCaretPosition(); +} + + + + +sal_Bool SAL_CALL PresenterAccessible::AccessibleParagraph::setSelection ( + sal_Int32 nStartIndex, + sal_Int32 nEndIndex) + throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException) +{ + (void)nEndIndex; + ThrowIfDisposed(); + + return setCaretPosition(nStartIndex); +} + + + + +::rtl::OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getText (void) + throw (cssu::RuntimeException) +{ + ThrowIfDisposed(); + + ::rtl::OUString sText; + if (mpParagraph) + sText = mpParagraph->GetText(); + + return sText; +} + + + + +::rtl::OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getTextRange ( + sal_Int32 nLocalStartIndex, + sal_Int32 nLocalEndIndex) + throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException) +{ + ThrowIfDisposed(); + + ::rtl::OUString sText; + if (mpParagraph) + { + const TextSegment aSegment ( + mpParagraph->CreateTextSegment(nLocalStartIndex, nLocalEndIndex)); + sText = aSegment.SegmentText; + } + + return sText; +} + + + + +TextSegment SAL_CALL PresenterAccessible::AccessibleParagraph::getTextAtIndex ( + sal_Int32 nLocalCharacterIndex, + sal_Int16 nTextType) + throw (css::lang::IndexOutOfBoundsException, + css::lang::IllegalArgumentException, + cssu::RuntimeException) +{ + ThrowIfDisposed(); + + TextSegment aSegment; + if (mpParagraph) + aSegment = mpParagraph->GetTextSegment(0, nLocalCharacterIndex, nTextType); + + return aSegment; +} + + + + +TextSegment SAL_CALL PresenterAccessible::AccessibleParagraph::getTextBeforeIndex ( + sal_Int32 nLocalCharacterIndex, + sal_Int16 nTextType) + throw (css::lang::IndexOutOfBoundsException, + css::lang::IllegalArgumentException, + cssu::RuntimeException) +{ + ThrowIfDisposed(); + + TextSegment aSegment; + if (mpParagraph) + aSegment = mpParagraph->GetTextSegment(-1, nLocalCharacterIndex, nTextType); + + return aSegment; +} + + + + +TextSegment SAL_CALL PresenterAccessible::AccessibleParagraph::getTextBehindIndex ( + sal_Int32 nLocalCharacterIndex, + sal_Int16 nTextType) + throw (css::lang::IndexOutOfBoundsException, + css::lang::IllegalArgumentException, + cssu::RuntimeException) +{ + ThrowIfDisposed(); + + TextSegment aSegment; + if (mpParagraph) + aSegment = mpParagraph->GetTextSegment(+1, nLocalCharacterIndex, nTextType); + + return aSegment; +} + + + + +sal_Bool SAL_CALL PresenterAccessible::AccessibleParagraph::copyText ( + sal_Int32 nStartIndex, + sal_Int32 nEndIndex) + throw (css::lang::IndexOutOfBoundsException, cssu::RuntimeException) +{ + ThrowIfDisposed(); + + // Return false because copying to clipboard is not supported. + // It IS supported in the notes view. There is no need to duplicate + // this here. + (void)nStartIndex; + (void)nEndIndex; + return sal_False; +} + + + + +//----- protected ------------------------------------------------------------- + +awt::Point PresenterAccessible::AccessibleParagraph::GetRelativeLocation (void) +{ + awt::Point aLocation (AccessibleObject::GetRelativeLocation()); + if (mpParagraph) + { + const awt::Point aParagraphLocation (mpParagraph->GetRelativeLocation()); + aLocation.X += aParagraphLocation.X; + aLocation.Y += aParagraphLocation.Y; + } + + return aLocation; +} + + + + +awt::Size PresenterAccessible::AccessibleParagraph::GetSize (void) +{ + if (mpParagraph) + return mpParagraph->GetSize(); + else + return AccessibleObject::GetSize(); +} + + + + +awt::Point PresenterAccessible::AccessibleParagraph::GetAbsoluteParentLocation (void) +{ + if (mxParentAccessible.is()) + { + Reference<XAccessibleContext> xParentContext( + mxParentAccessible->getAccessibleContext(), UNO_QUERY); + if (xParentContext.is()) + { + Reference<XAccessibleComponent> xGrandParentComponent( + xParentContext->getAccessibleParent(), UNO_QUERY); + if (xGrandParentComponent.is()) + return xGrandParentComponent->getLocationOnScreen(); + } + } + + return awt::Point(); +} + + + + +bool PresenterAccessible::AccessibleParagraph::GetWindowState (const sal_Int16 nType) const +{ + switch (nType) + { + case AccessibleStateType::EDITABLE: + return mpParagraph.get()!=NULL; + + case AccessibleStateType::ACTIVE: + return true; + + default: + return AccessibleObject::GetWindowState(nType); + } +} + + + + + + +//===== AccessibleNotes ======================================================= + +AccessibleNotes::AccessibleNotes ( + const css::lang::Locale aLocale, + const sal_Int16 nRole, + const ::rtl::OUString& rsName) + : AccessibleObject(aLocale,nRole,rsName), + mpTextView() +{ +} + + + + +rtl::Reference<PresenterAccessible::AccessibleObject> AccessibleNotes::Create ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const lang::Locale aLocale, + const Reference<awt::XWindow>& rxContentWindow, + const Reference<awt::XWindow>& rxBorderWindow, + const ::boost::shared_ptr<PresenterTextView>& rpTextView) +{ + OUString sName (A2S("Presenter Notes Text")); + { + PresenterConfigurationAccess aConfiguration ( + rxContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.extension.PresenterScreen/")), + PresenterConfigurationAccess::READ_ONLY); + aConfiguration.GetConfigurationNode(A2S("Presenter/Accessibility/Notes/String")) + >>= sName; + } + + rtl::Reference<AccessibleNotes> pObject ( + new AccessibleNotes( + aLocale, + AccessibleRole::PANEL, + sName)); + pObject->LateInitialization(); + pObject->SetTextView(rpTextView); + pObject->UpdateStateSet(); + pObject->SetWindow(rxContentWindow, rxBorderWindow); + + return rtl::Reference<PresenterAccessible::AccessibleObject>(pObject.get()); +} + + + + +void AccessibleNotes::SetTextView ( + const ::boost::shared_ptr<PresenterTextView>& rpTextView) +{ + ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> > aChildren; + + // Release any listeners to the current text view. + if (mpTextView) + { + mpTextView->GetCaret()->SetCaretMotionBroadcaster( + ::boost::function<void(sal_Int32,sal_Int32,sal_Int32,sal_Int32)>()); + mpTextView->SetTextChangeBroadcaster( + ::boost::function<void(void)>()); + } + + mpTextView = rpTextView; + + if (mpTextView) + { + // Create a new set of children, one for each paragraph. + const sal_Int32 nParagraphCount (mpTextView->GetParagraphCount()); + for (sal_Int32 nIndex=0; nIndex<nParagraphCount; ++nIndex) + { + rtl::Reference<PresenterAccessible::AccessibleParagraph> pParagraph ( + new PresenterAccessible::AccessibleParagraph( + css::lang::Locale(), + AccessibleRole::PARAGRAPH, + A2S("Paragraph")+OUString::valueOf(nIndex), + rpTextView->GetParagraph(nIndex), + nIndex)); + pParagraph->LateInitialization(); + pParagraph->SetWindow( + Reference<awt::XWindow>(mxContentWindow, UNO_QUERY), + Reference<awt::XWindow>(mxBorderWindow, UNO_QUERY)); + pParagraph->SetAccessibleParent(this); + aChildren.push_back( + rtl::Reference<PresenterAccessible::AccessibleObject>(pParagraph.get())); + } + maChildren.swap(aChildren); + FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any()); + + // Dispose the old children. (This will remove them from the focus + // manager). + for (std::vector<rtl::Reference<AccessibleObject> >::const_iterator + iChild(aChildren.begin()), iEnd(aChildren.end()); + iChild!=iEnd; + ++iChild) + { + Reference<lang::XComponent> xComponent (static_cast<XWeak*>(iChild->get()), UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + } + + // This class acts as a controller of who broadcasts caret motion + // events and handles text changes. Register the corresponding + // listeners here. + mpTextView->GetCaret()->SetCaretMotionBroadcaster( + ::boost::bind(&AccessibleNotes::NotifyCaretChange, this, _1, _2, _3, _4)); + mpTextView->SetTextChangeBroadcaster( + ::boost::bind(&AccessibleNotes::HandleTextChange, this)); + } +} + + + + +void AccessibleNotes::SetWindow ( + const cssu::Reference<css::awt::XWindow>& rxContentWindow, + const cssu::Reference<css::awt::XWindow>& rxBorderWindow) +{ + AccessibleObject::SetWindow(rxContentWindow, rxBorderWindow); + + // Set the windows at the children as well, so that every paragraph can + // setup its geometry. + for (::std::vector<rtl::Reference<AccessibleObject> >::const_iterator + iChild(maChildren.begin()), + iEnd(maChildren.end()); + iChild!=iEnd; + ++iChild) + { + (*iChild)->SetWindow(rxContentWindow, rxBorderWindow); + } +} + + + + +void AccessibleNotes::NotifyCaretChange ( + const sal_Int32 nOldParagraphIndex, + const sal_Int32 nOldCharacterIndex, + const sal_Int32 nNewParagraphIndex, + const sal_Int32 nNewCharacterIndex) +{ + AccessibleFocusManager::Instance()->FocusObject( + nNewParagraphIndex >= 0 + ? maChildren[nNewParagraphIndex] + : this); + + if (nOldParagraphIndex != nNewParagraphIndex) + { + // Moved caret from one paragraph to another (or showed or + // hid the caret). Move focuse from one accessible + // paragraph to another. + if (nOldParagraphIndex >= 0) + { + maChildren[nOldParagraphIndex]->FireAccessibleEvent( + AccessibleEventId::CARET_CHANGED, + Any(nOldCharacterIndex), + Any(sal_Int32(-1))); + } + if (nNewParagraphIndex >= 0) + { + maChildren[nNewParagraphIndex]->FireAccessibleEvent( + AccessibleEventId::CARET_CHANGED, + Any(sal_Int32(-1)), + Any(nNewCharacterIndex)); + } + } + else if (nNewParagraphIndex >= 0) + { + // Caret moved inside one paragraph. + maChildren[nNewParagraphIndex]->FireAccessibleEvent( + AccessibleEventId::CARET_CHANGED, + Any(nOldCharacterIndex), + Any(nNewCharacterIndex)); + } +} + + + + +void AccessibleNotes::HandleTextChange (void) +{ + SetTextView(mpTextView); +} + + + + +//===== AccessibleFocusManager ================================================ + +::boost::shared_ptr<AccessibleFocusManager> AccessibleFocusManager::mpInstance; + +::boost::shared_ptr<AccessibleFocusManager> AccessibleFocusManager::Instance (void) +{ + if ( ! mpInstance) + { + mpInstance.reset(new AccessibleFocusManager()); + } + return mpInstance; +} + + + + +AccessibleFocusManager::AccessibleFocusManager (void) + : maFocusableObjects() +{ +} + + + + +void AccessibleFocusManager::AddFocusableObject ( + const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject) +{ + OSL_ASSERT(rpObject.is()); + OSL_ASSERT(::std::find(maFocusableObjects.begin(),maFocusableObjects.end(), rpObject)==maFocusableObjects.end()); + + maFocusableObjects.push_back(rpObject); +} + + + + +void AccessibleFocusManager::RemoveFocusableObject ( + const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject) +{ + ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> >::iterator iObject ( + ::std::find(maFocusableObjects.begin(),maFocusableObjects.end(), rpObject)); + + if (iObject != maFocusableObjects.end()) + maFocusableObjects.erase(iObject); + else + { + OSL_ASSERT(iObject!=maFocusableObjects.end()); + } +} + + + + +void AccessibleFocusManager::FocusObject ( + const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject) +{ + // Remove the focus of any of the other focusable objects. + for (::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> >::const_iterator + iObject (maFocusableObjects.begin()), + iEnd (maFocusableObjects.end()); + iObject != iEnd; + ++iObject) + { + if (*iObject!=rpObject) + (*iObject)->SetIsFocused(false); + } + + if (rpObject.is()) + rpObject->SetIsFocused(true); +} + +} } // end of namespace ::sd::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterAccessibility.hxx b/sdext/source/presenter/PresenterAccessibility.hxx new file mode 100644 index 000000000000..16e19abc1695 --- /dev/null +++ b/sdext/source/presenter/PresenterAccessibility.hxx @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_ACCESSIBILITY_HXX +#define SDEXT_PRESENTER_PRESENTER_ACCESSIBILITY_HXX + +#include "PresenterPaneContainer.hxx" + +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/TextSegment.hpp> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/awt/XFocusListener.hpp> +#include <com/sun/star/awt/XWindow2.hpp> +#include <com/sun/star/awt/WindowEvent.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/drawing/framework/XConfigurationController.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/drawing/framework/XPane2.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/compbase3.hxx> +#include <cppuhelper/basemutex.hxx> +#include <rtl/ref.hxx> +#include <boost/shared_ptr.hpp> + +namespace css = ::com::sun::star; +namespace cssu = ::com::sun::star::uno; +namespace cssa = ::com::sun::star::accessibility; + + +namespace sdext { namespace presenter { + +class PresenterController; +class PresenterTextView; + +namespace { + typedef ::cppu::WeakComponentImplHelper3 < + css::accessibility::XAccessible, + css::lang::XInitialization, + css::awt::XFocusListener + > PresenterAccessibleInterfaceBase; +} + +class PresenterAccessible + : public ::cppu::BaseMutex, + public PresenterAccessibleInterfaceBase +{ +public: + PresenterAccessible ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const css::uno::Reference<css::drawing::framework::XPane>& rxMainPane); + virtual ~PresenterAccessible (void); + + void SetAccessibleParent (const cssu::Reference<cssa::XAccessible>& rxAccessibleParent); + + void UpdateAccessibilityHierarchy (void); + + void NotifyCurrentSlideChange ( + const sal_Int32 nCurrentSlideIndex, + const sal_Int32 nSlideCount); + + /** Return whether accessibility support is active, i.e. whether + somebody has called getAccessibleContext() yet. + */ + bool IsAccessibilityActive (void) const; + + virtual void SAL_CALL disposing (void); + + + //----- XAccessible ------------------------------------------------------- + + virtual cssu::Reference<cssa::XAccessibleContext> SAL_CALL + getAccessibleContext (void) + throw (cssu::RuntimeException); + + + //----- XFocusListener ---------------------------------------------------- + + virtual void SAL_CALL focusGained (const css::awt::FocusEvent& rEvent) + throw (cssu::RuntimeException); + + virtual void SAL_CALL focusLost (const css::awt::FocusEvent& rEvent) + throw (cssu::RuntimeException); + + + //----- XEventListener ---------------------------------------------------- + + virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) + throw (cssu::RuntimeException); + + + //----- XInitialization --------------------------------------------------- + + virtual void SAL_CALL initialize (const cssu::Sequence<cssu::Any>& rArguments) + throw (cssu::RuntimeException); + + + class AccessibleObject; + class AccessibleParagraph; + +private: + const css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + ::rtl::Reference<PresenterController> mpPresenterController; + css::uno::Reference<css::drawing::framework::XResourceId> mxMainPaneId; + css::uno::Reference<css::drawing::framework::XPane2> mxMainPane; + css::uno::Reference<css::awt::XWindow> mxMainWindow; + css::uno::Reference<css::awt::XWindow> mxPreviewContentWindow; + css::uno::Reference<css::awt::XWindow> mxPreviewBorderWindow; + css::uno::Reference<css::awt::XWindow> mxNotesContentWindow; + css::uno::Reference<css::awt::XWindow> mxNotesBorderWindow; + ::rtl::Reference<AccessibleObject> mpAccessibleConsole; + ::rtl::Reference<AccessibleObject> mpAccessiblePreview; + ::rtl::Reference<AccessibleObject> mpAccessibleNotes; + css::uno::Reference<css::accessibility::XAccessible> mxAccessibleParent; + + void UpdateAccessibilityHierarchy ( + const css::uno::Reference<css::awt::XWindow>& rxPreviewContentWindow, + const css::uno::Reference<css::awt::XWindow>& rxPreviewBorderWindow, + const ::rtl::OUString& rsTitle, + const css::uno::Reference<css::awt::XWindow>& rxNotesContentWindow, + const css::uno::Reference<css::awt::XWindow>& rxNotesBorderWindow, + const ::boost::shared_ptr<PresenterTextView>& rpNotesTextView); + PresenterPaneContainer::SharedPaneDescriptor GetPreviewPane (void) const; +}; + + + + +} } // end of namespace ::sd::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterAnimation.cxx b/sdext/source/presenter/PresenterAnimation.cxx new file mode 100644 index 000000000000..0be27e813b38 --- /dev/null +++ b/sdext/source/presenter/PresenterAnimation.cxx @@ -0,0 +1,143 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterAnimation.hxx" + +#include <osl/time.h> + +namespace sdext { namespace presenter { + +sal_uInt64 GetCurrentTime (void) +{ + TimeValue aTimeValue; + if (osl_getSystemTime(&aTimeValue)) + return sal_uInt64(aTimeValue.Seconds * 1000.0 + aTimeValue.Nanosec / 1000000.0); + else + return 0; +} + + + + +PresenterAnimation::PresenterAnimation ( + const sal_uInt64 nStartDelay, + const sal_uInt64 nTotalDuration, + const sal_uInt64 nStepDuration) + : mnStartTime(GetCurrentTime()+nStartDelay), + mnTotalDuration(nTotalDuration), + mnStepDuration(nStepDuration), + mpStartCallbacks(), + mpEndCallbacks() +{ +} + + + + +PresenterAnimation::~PresenterAnimation (void) +{ +} + + + + +sal_uInt64 PresenterAnimation::GetStartTime (void) +{ + return mnStartTime; +} + + + + +sal_uInt64 PresenterAnimation::GetEndTime (void) +{ + return mnStartTime + mnTotalDuration; +} + + + + +sal_uInt64 PresenterAnimation::GetStepDuration (void) +{ + return mnStepDuration; +} + + + + +void PresenterAnimation::AddStartCallback (const Callback& rCallback) +{ + if (mpStartCallbacks.get() == NULL) + mpStartCallbacks.reset(new ::std::vector<Callback>()); + mpStartCallbacks->push_back(rCallback); +} + + + + +void PresenterAnimation::AddEndCallback (const Callback& rCallback) +{ + if (mpEndCallbacks.get() == NULL) + mpEndCallbacks.reset(new ::std::vector<Callback>()); + mpEndCallbacks->push_back(rCallback); +} + + + +void PresenterAnimation::RunStartCallbacks (void) +{ + if (mpStartCallbacks.get() != NULL) + { + ::std::vector<Callback>::const_iterator iCallback; + for (iCallback=mpStartCallbacks->begin(); iCallback!=mpStartCallbacks->end(); ++iCallback) + (*iCallback)(); + } +} + + + + +void PresenterAnimation::RunEndCallbacks (void) +{ + if (mpEndCallbacks.get() != NULL) + { + ::std::vector<Callback>::const_iterator iCallback; + for (iCallback=mpEndCallbacks->begin(); iCallback!=mpEndCallbacks->end(); ++iCallback) + (*iCallback)(); + } +} + + + + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterAnimation.hxx b/sdext/source/presenter/PresenterAnimation.hxx new file mode 100644 index 000000000000..76d102a20758 --- /dev/null +++ b/sdext/source/presenter/PresenterAnimation.hxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_ANIMATION_HXX +#define SDEXT_PRESENTER_ANIMATION_HXX + +#include <sal/types.h> +#include <boost/function.hpp> +#include <boost/noncopyable.hpp> +#include <boost/scoped_ptr.hpp> +#include <boost/shared_ptr.hpp> +#include <vector> + +namespace sdext { namespace presenter { + +/** Base class for animations handled by a PresenterAnimator object. + A PresenterAnimation objects basically states when it wants to be + started, how long it runs, and in what steps it wants to be called back + while running. + When a PresenterAnimation object is active/running its Run() method is + called back with increasing values between 0 and 1. +*/ +class PresenterAnimation + : private ::boost::noncopyable +{ +public: + /** Create a new PresenterAnimation object. + @param nStartDelay + The delay in ms (milliseconds) from this call until the new + object is to be activated. + @param nTotalDuration + The duration in ms the Run() method is to be called with + increasing values between 0 and 1. + @param nStepDuration + The duration between calls to Run(). This leads to approximately + nTotalDuration/nStepDuration calls to Run(). The exact duration + of each step may vary depending on system load an other influences. + */ + PresenterAnimation ( + const sal_uInt64 nStartDelay, + const sal_uInt64 nTotalDuration, + const sal_uInt64 nStepDuration); + virtual ~PresenterAnimation (void); + + /** Return the absolute start time in a system dependent format. + At about this time the Run() method will be called with a value of 0. + */ + sal_uInt64 GetStartTime (void); + + /** Return the absolute end time in a system dependent format. + At about this time the Run() method will be called with a value of 1. + */ + sal_uInt64 GetEndTime (void); + + /** Return the duration of each step in ms. + */ + sal_uInt64 GetStepDuration (void); + + typedef ::boost::function<void(void)> Callback; + + /** Add a callback that is executed before Run() is called for the first + time. + */ + void AddStartCallback (const Callback& rCallback); + + /** Add a callback that is executed after Run() is called for the last + time. + */ + void AddEndCallback (const Callback& rCallback); + + /** Called with nProgress taking on values between 0 and 1. + @param nProgress + A value between 0 and 1. + @param nCurrentTime + Current time in a system dependent format. + */ + virtual void Run (const double nProgress, const sal_uInt64 nCurrentTime) = 0; + + /** Called just before Run() is called for the first time to trigger the + callbacks registered via the <method>AddStartCallback()</method>. + */ + void RunStartCallbacks (void); + + /** Called just after Run() is called for the last time to trigger the + callbacks registered via the <method>AddEndCallback()</method>. + */ + void RunEndCallbacks (void); + +private: + const sal_uInt64 mnStartTime; + const sal_uInt64 mnTotalDuration; + const sal_uInt64 mnStepDuration; + ::boost::scoped_ptr<std::vector<Callback> > mpStartCallbacks; + ::boost::scoped_ptr<std::vector<Callback> > mpEndCallbacks; +}; + +sal_uInt64 GetCurrentTime (void); +inline sal_uInt32 GetSeconds (const sal_uInt64 nTime) { return sal_uInt32(nTime / 1000); } +inline sal_uInt32 GetNanoSeconds (const sal_uInt64 nTime) { return sal_uInt32((nTime % 1000) * 1000000); } + +typedef ::boost::shared_ptr<PresenterAnimation> SharedPresenterAnimation; + + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterAnimator.cxx b/sdext/source/presenter/PresenterAnimator.cxx new file mode 100644 index 000000000000..d16528f658e3 --- /dev/null +++ b/sdext/source/presenter/PresenterAnimator.cxx @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterAnimator.hxx" + +#include "PresenterTimer.hxx" +#include <osl/diagnose.h> +#include <osl/time.h> +#include <salhelper/timer.hxx> +#include <boost/bind.hpp> +#include <boost/function.hpp> + +namespace sdext { namespace presenter { + + + +//===== PresenterAnimator ===================================================== + +PresenterAnimator::PresenterAnimator (void) + : maFutureAnimations(), + maActiveAnimations(), + mnCurrentTaskId(0), + mnNextTime(0) +{ +} + + + + +PresenterAnimator::~PresenterAnimator (void) +{ + PresenterTimer::CancelTask(mnCurrentTaskId); +} + + + + + +void PresenterAnimator::AddAnimation (const SharedPresenterAnimation& rpAnimation) +{ + ::osl::MutexGuard aGuard (m_aMutex); + + maFutureAnimations.insert(AnimationList::value_type(rpAnimation->GetStartTime(), rpAnimation)); + ScheduleNextRun(); +} + + + + +void PresenterAnimator::Process (void) +{ + ::osl::MutexGuard aGuard (m_aMutex); + + mnNextTime = 0; + + const sal_uInt64 nCurrentTime (GetCurrentTime()); + + ActivateAnimations(nCurrentTime); + + while ( ! maActiveAnimations.empty()) + { + sal_uInt64 nRequestedTime (maActiveAnimations.begin()->first); + SharedPresenterAnimation pAnimation (maActiveAnimations.begin()->second); + + if (nRequestedTime > nCurrentTime) + break; + + maActiveAnimations.erase(maActiveAnimations.begin()); + + const double nTotalDuration (double(pAnimation->GetEndTime() - pAnimation->GetStartTime())); + double nProgress (nTotalDuration > 0 ? (nCurrentTime - pAnimation->GetStartTime()) / nTotalDuration : 1); + if (nProgress <= 0) + nProgress = 0; + else if (nProgress >= 1) + nProgress = 1; + + OSL_TRACE("running animation step at %f (requested was %f) %f\n", + nCurrentTime/1e6, nRequestedTime/1e6, nProgress); + pAnimation->Run(nProgress, nCurrentTime); + + if (nCurrentTime < pAnimation->GetEndTime()) + maActiveAnimations.insert( + AnimationList::value_type( + nCurrentTime + pAnimation->GetStepDuration(), + pAnimation)); + else + pAnimation->RunEndCallbacks(); + } + + ScheduleNextRun(); +} + + + + +void PresenterAnimator::ActivateAnimations (const sal_uInt64 nCurrentTime) +{ + while ( ! maFutureAnimations.empty() + && maFutureAnimations.begin()->first <= nCurrentTime) + { + SharedPresenterAnimation pAnimation (maFutureAnimations.begin()->second); + maActiveAnimations.insert(*maFutureAnimations.begin()); + maFutureAnimations.erase(maFutureAnimations.begin()); + pAnimation->RunStartCallbacks(); + } +} + + + + +void PresenterAnimator::ScheduleNextRun (void) +{ + sal_uInt64 nStartTime (0); + + if ( ! maActiveAnimations.empty()) + { + nStartTime = maActiveAnimations.begin()->first; + if ( ! maFutureAnimations.empty()) + if (maFutureAnimations.begin()->first < nStartTime) + nStartTime = maFutureAnimations.begin()->first; + } + else if ( ! maFutureAnimations.empty()) + nStartTime = maFutureAnimations.begin()->first; + + if (nStartTime > 0) + ScheduleNextRun(nStartTime); +} + + + + +void PresenterAnimator::ScheduleNextRun (const sal_uInt64 nStartTime) +{ + if (mnNextTime==0 || nStartTime<mnNextTime) + { + mnNextTime = nStartTime; + ::salhelper::TTimeValue aTimeValue (GetSeconds(mnNextTime), GetNanoSeconds(mnNextTime)); + PresenterTimer::ScheduleSingleTaskAbsolute ( + ::boost::bind(&PresenterAnimator::Process, this), + aTimeValue); + } +} + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterAnimator.hxx b/sdext/source/presenter/PresenterAnimator.hxx new file mode 100644 index 000000000000..073592b69947 --- /dev/null +++ b/sdext/source/presenter/PresenterAnimator.hxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_ANIMATOR_HXX +#define SDEXT_PRESENTER_ANIMATOR_HXX + +#include "PresenterAnimation.hxx" +#include <cppuhelper/basemutex.hxx> +#include <map> +#include <boost/noncopyable.hpp> +#include <boost/scoped_ptr.hpp> + +namespace sdext { namespace presenter { + +/** Simple animation management. Call AddAnimation to run animations + concurrently or one of the other. See PresenterAnimation for details of + how to specify animations. +*/ +class PresenterAnimator + : private ::boost::noncopyable, + private ::cppu::BaseMutex +{ +public: + PresenterAnimator (void); + virtual ~PresenterAnimator (void); + + /** Add an animation. The time at which to start and end this animation + is provided by the animation itself. + */ + void AddAnimation (const SharedPresenterAnimation& rpAnimation); + +private: + typedef ::std::multimap<sal_uInt64,SharedPresenterAnimation> AnimationList; + AnimationList maFutureAnimations; + AnimationList maActiveAnimations; + sal_Int32 mnCurrentTaskId; + sal_uInt64 mnNextTime; + + void Process (void); + void ActivateAnimations (const sal_uInt64 nCurrentTime); + void ScheduleNextRun (void); + void ScheduleNextRun (const sal_uInt64 nStartTime); + +}; + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterBitmapContainer.cxx b/sdext/source/presenter/PresenterBitmapContainer.cxx new file mode 100644 index 000000000000..1422ac3509dc --- /dev/null +++ b/sdext/source/presenter/PresenterBitmapContainer.cxx @@ -0,0 +1,501 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterBitmapContainer.hxx" +#include "PresenterComponent.hxx" +#include "PresenterConfigurationAccess.hxx" + +#include <com/sun/star/deployment/XPackageInformationProvider.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/XIntegerBitmap.hpp> +#include <boost/bind.hpp> +#include <map> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::std; +using ::rtl::OUString; + +#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) + + +namespace sdext { namespace presenter { + +namespace { +static OUString gsNameProperty (A2S("Name")); +static OUString gsNormalFileNameProperty (A2S("NormalFileName")); +static OUString gsMouseOverFileNameProperty (A2S("MouseOverFileName")); +static OUString gsButtonDownFileNameProperty (A2S("ButtonDownFileName")); +static OUString gsDisabledFileNameProperty (A2S("DisabledFileName")); +static OUString gsMaskFileNameProperty (A2S("MaskFileName")); +static OUString gsXOffsetProperty (A2S("XOffset")); +static OUString gsYOffsetProperty (A2S("YOffset")); +static OUString gsXHotSpotProperty (A2S("XHotSpot")); +static OUString gsYHotSpotProperty (A2S("YHotSpot")); +static OUString gsReplacementColorProperty (A2S("ReplacementColor")); +static OUString gsHorizontalTexturingModeProperty (A2S("HorizontalTexturingMode")); +static OUString gsVerticalTexturingModeProperty (A2S("VerticalTexturingMode")); +} + +//===== PresenterBitmapContainer ============================================== + +PresenterBitmapContainer::PresenterBitmapContainer ( + const ::rtl::OUString& rsConfigurationBase, + const ::boost::shared_ptr<PresenterBitmapContainer>& rpParentContainer, + const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const OUString& rsBasePath, + const css::uno::Reference<css::drawing::XPresenterHelper>& rxPresenterHelper) + : mpParentContainer(rpParentContainer), + maIconContainer(), + msBasePath(rsBasePath), + mxCanvas(rxCanvas), + mxPresenterHelper(rxPresenterHelper) +{ + Initialize(rxComponentContext); + + // Get access to the configuration. + PresenterConfigurationAccess aConfiguration ( + rxComponentContext, + A2S("org.openoffice.Office.extension.PresenterScreen"), + PresenterConfigurationAccess::READ_ONLY); + Reference<container::XNameAccess> xBitmapList ( + aConfiguration.GetConfigurationNode(rsConfigurationBase), + UNO_QUERY_THROW); + + LoadBitmaps(xBitmapList); +} + + + + + +PresenterBitmapContainer::PresenterBitmapContainer ( + const css::uno::Reference<css::container::XNameAccess>& rxRootNode, + const ::boost::shared_ptr<PresenterBitmapContainer>& rpParentContainer, + const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const OUString& rsBasePath, + const css::uno::Reference<css::drawing::XPresenterHelper>& rxPresenterHelper) + : mpParentContainer(rpParentContainer), + maIconContainer(), + msBasePath(rsBasePath), + mxCanvas(rxCanvas), + mxPresenterHelper(rxPresenterHelper) +{ + Initialize(rxComponentContext); + + LoadBitmaps(rxRootNode); +} + + + + +void PresenterBitmapContainer::Initialize ( + const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext) +{ + if ( ! mxPresenterHelper.is()) + { + // Create an object that is able to load the bitmaps in a format that is + // supported by the canvas. + Reference<lang::XMultiComponentFactory> xFactory ( + rxComponentContext->getServiceManager(), UNO_QUERY); + if ( ! xFactory.is()) + return; + mxPresenterHelper = Reference<drawing::XPresenterHelper>( + xFactory->createInstanceWithContext( + A2S("com.sun.star.drawing.PresenterHelper"), + rxComponentContext), + UNO_QUERY_THROW); + } +} + + + + +PresenterBitmapContainer::~PresenterBitmapContainer (void) +{ + maIconContainer.clear(); +} + + + + +SharedBitmapDescriptor PresenterBitmapContainer::GetBitmap ( + const OUString& rsName) const +{ + BitmapContainer::const_iterator iSet (maIconContainer.find(rsName)); + if (iSet != maIconContainer.end()) + return iSet->second; + else if (mpParentContainer.get() != NULL) + return mpParentContainer->GetBitmap(rsName); + else + return SharedBitmapDescriptor(); +} + + + + +void PresenterBitmapContainer::LoadBitmaps ( + const css::uno::Reference<css::container::XNameAccess>& rxBitmapList) +{ + if ( ! mxCanvas.is()) + return; + + if ( ! rxBitmapList.is()) + return; + + try + { + // Load all button bitmaps. + if (rxBitmapList.is()) + { + PresenterConfigurationAccess::ForAll( + rxBitmapList, + ::boost::bind(&PresenterBitmapContainer::ProcessBitmap, this, _1, _2)); + } + } + catch (Exception&) + { + OSL_ASSERT(false); + } +} + + + + +SharedBitmapDescriptor PresenterBitmapContainer::LoadBitmap ( + const css::uno::Reference<css::container::XHierarchicalNameAccess>& rxNode, + const ::rtl::OUString& rsPath, + const css::uno::Reference<css::drawing::XPresenterHelper>& rxPresenterHelper, + const OUString& rsBasePath, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const SharedBitmapDescriptor& rpDefault) +{ + SharedBitmapDescriptor pBitmap; + + if (rxNode.is()) + { + try + { + Reference<beans::XPropertySet> xBitmapProperties ( + PresenterConfigurationAccess::GetConfigurationNode(rxNode, rsPath), + UNO_QUERY); + if (xBitmapProperties.is()) + pBitmap = LoadBitmap( + xBitmapProperties, + rxPresenterHelper, + rsBasePath, + rxCanvas, + rpDefault); + } + catch (Exception&) + { + OSL_ASSERT(false); + } + } + + return pBitmap; +} + + + + +void PresenterBitmapContainer::ProcessBitmap ( + const OUString& rsKey, + const Reference<beans::XPropertySet>& rxProperties) +{ + OUString sName; + if ( ! (PresenterConfigurationAccess::GetProperty(rxProperties, gsNameProperty) >>= sName)) + sName = rsKey; + + maIconContainer[sName] = LoadBitmap( + rxProperties, + mxPresenterHelper, + msBasePath, + mxCanvas, + SharedBitmapDescriptor()); +} + + + + +SharedBitmapDescriptor PresenterBitmapContainer::LoadBitmap ( + const Reference<beans::XPropertySet>& rxProperties, + const css::uno::Reference<css::drawing::XPresenterHelper>& rxPresenterHelper, + const OUString& rsBasePath, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const SharedBitmapDescriptor& rpDefault) +{ + OSL_ASSERT(rxCanvas.is()); + OSL_ASSERT(rxPresenterHelper.is()); + + SharedBitmapDescriptor pBitmap (new BitmapDescriptor(rpDefault)); + + if ( ! rxProperties.is()) + return pBitmap; + + OUString sFileName; + + // Load bitmaps. + if (PresenterConfigurationAccess::GetProperty(rxProperties, gsNormalFileNameProperty) >>= sFileName) + try + { + pBitmap->SetBitmap( + BitmapDescriptor::Normal, + rxPresenterHelper->loadBitmap(rsBasePath + sFileName, rxCanvas)); + } + catch (Exception&) + {} + if (PresenterConfigurationAccess::GetProperty(rxProperties, gsMouseOverFileNameProperty) >>= sFileName) + try + { + pBitmap->SetBitmap( + BitmapDescriptor::MouseOver, + rxPresenterHelper->loadBitmap(rsBasePath + sFileName, rxCanvas)); + } + catch (Exception&) + {} + if (PresenterConfigurationAccess::GetProperty(rxProperties, gsButtonDownFileNameProperty) >>= sFileName) + try + { + pBitmap->SetBitmap( + BitmapDescriptor::ButtonDown, + rxPresenterHelper->loadBitmap(rsBasePath + sFileName, rxCanvas)); + } + catch (Exception&) + {} + if (PresenterConfigurationAccess::GetProperty(rxProperties, gsDisabledFileNameProperty) >>= sFileName) + try + { + pBitmap->SetBitmap( + BitmapDescriptor::Disabled, + rxPresenterHelper->loadBitmap(rsBasePath + sFileName, rxCanvas)); + } + catch (Exception&) + {} + if (PresenterConfigurationAccess::GetProperty(rxProperties, gsMaskFileNameProperty) >>= sFileName) + try + { + pBitmap->SetBitmap( + BitmapDescriptor::Mask, + rxPresenterHelper->loadBitmap(rsBasePath + sFileName, rxCanvas)); + } + catch (Exception&) + {} + + + PresenterConfigurationAccess::GetProperty(rxProperties, gsXOffsetProperty) >>= pBitmap->mnXOffset; + PresenterConfigurationAccess::GetProperty(rxProperties, gsYOffsetProperty) >>= pBitmap->mnYOffset; + + PresenterConfigurationAccess::GetProperty(rxProperties, gsXHotSpotProperty) >>= pBitmap->mnXHotSpot; + PresenterConfigurationAccess::GetProperty(rxProperties, gsYHotSpotProperty) >>= pBitmap->mnYHotSpot; + + PresenterConfigurationAccess::GetProperty(rxProperties, gsReplacementColorProperty) >>= pBitmap->maReplacementColor; + + OUString sTexturingMode; + if (PresenterConfigurationAccess::GetProperty(rxProperties, gsHorizontalTexturingModeProperty) >>= sTexturingMode) + pBitmap->meHorizontalTexturingMode = StringToTexturingMode(sTexturingMode); + if (PresenterConfigurationAccess::GetProperty(rxProperties, gsVerticalTexturingModeProperty) >>= sTexturingMode) + pBitmap->meVerticalTexturingMode = StringToTexturingMode(sTexturingMode); + + return pBitmap; +} + + + + +PresenterBitmapContainer::BitmapDescriptor::TexturingMode + PresenterBitmapContainer::StringToTexturingMode (const OUString& rsTexturingMode) +{ + if (rsTexturingMode == A2S("Once")) + return PresenterBitmapContainer::BitmapDescriptor::Once; + else if (rsTexturingMode == A2S("Repeat")) + return PresenterBitmapContainer::BitmapDescriptor::Repeat; + else if (rsTexturingMode == A2S("Stretch")) + return PresenterBitmapContainer::BitmapDescriptor::Stretch; + else + return PresenterBitmapContainer::BitmapDescriptor::Once; +} + + + + +//===== PresenterBitmapContainer::BitmapSet =================================== + +PresenterBitmapContainer::BitmapDescriptor::BitmapDescriptor (void) + : mnWidth(0), + mnHeight(0), + mnXOffset(0), + mnYOffset(0), + mnXHotSpot(0), + mnYHotSpot(0), + maReplacementColor(0x00000000), + meHorizontalTexturingMode(Once), + meVerticalTexturingMode(Once), + mxNormalBitmap(), + mxMouseOverBitmap(), + mxButtonDownBitmap(), + mxDisabledBitmap(), + mxMaskBitmap() +{ +} + + + + +PresenterBitmapContainer::BitmapDescriptor::BitmapDescriptor ( + const ::boost::shared_ptr<PresenterBitmapContainer::BitmapDescriptor>& rpDefault) + : mnWidth(0), + mnHeight(0), + mnXOffset(0), + mnYOffset(0), + mnXHotSpot(0), + mnYHotSpot(0), + maReplacementColor(0x00000000), + meHorizontalTexturingMode(Once), + meVerticalTexturingMode(Once), + mxNormalBitmap(), + mxMouseOverBitmap(), + mxButtonDownBitmap(), + mxDisabledBitmap(), + mxMaskBitmap() +{ + if (rpDefault.get() != NULL) + { + mnWidth = rpDefault->mnWidth; + mnHeight = rpDefault->mnHeight; + mnXOffset = rpDefault->mnXOffset; + mnYOffset = rpDefault->mnYOffset; + mnXHotSpot = rpDefault->mnXHotSpot; + mnYHotSpot = rpDefault->mnYHotSpot; + maReplacementColor = rpDefault->maReplacementColor; + meHorizontalTexturingMode = rpDefault->meHorizontalTexturingMode; + meVerticalTexturingMode = rpDefault->meVerticalTexturingMode; + mxNormalBitmap = rpDefault->mxNormalBitmap; + mxMouseOverBitmap = rpDefault->mxMouseOverBitmap; + mxButtonDownBitmap = rpDefault->mxButtonDownBitmap; + mxDisabledBitmap = rpDefault->mxDisabledBitmap; + mxMaskBitmap = rpDefault->mxMaskBitmap; + } +} + + +css::uno::Reference<css::rendering::XBitmap> + PresenterBitmapContainer::BitmapDescriptor::GetNormalBitmap (void) const +{ + return mxNormalBitmap; +} + + + + +css::uno::Reference<css::rendering::XBitmap> + PresenterBitmapContainer::BitmapDescriptor::GetBitmap ( + const Mode eMode, + const bool bMissingDefaultsToNormal) const +{ + switch (eMode) + { + case Normal: + default: + return mxNormalBitmap; + + case MouseOver: + if (mxMouseOverBitmap.is()) + return mxMouseOverBitmap; + else if (bMissingDefaultsToNormal) + return mxNormalBitmap; + + case ButtonDown: + if (mxButtonDownBitmap.is()) + return mxButtonDownBitmap; + else if (bMissingDefaultsToNormal) + return mxNormalBitmap; + + case Disabled: + if (mxDisabledBitmap.is()) + return mxDisabledBitmap; + else if (bMissingDefaultsToNormal) + return mxNormalBitmap; + + case Mask: + return mxMaskBitmap; + } + return NULL; +} + + + + +void PresenterBitmapContainer::BitmapDescriptor::SetBitmap ( + const Mode eMode, + const css::uno::Reference<css::rendering::XBitmap>& rxBitmap) +{ + switch (eMode) + { + case Normal: + default: + mxNormalBitmap = rxBitmap; + if (mxNormalBitmap.is()) + { + const geometry::IntegerSize2D aSize (mxNormalBitmap->getSize()); + mnWidth = aSize.Width; + mnHeight = aSize.Height; + } + break; + + case MouseOver: + mxMouseOverBitmap = rxBitmap; + break; + + case ButtonDown: + mxButtonDownBitmap = rxBitmap; + break; + + case Disabled: + mxDisabledBitmap = rxBitmap; + break; + + case Mask: + mxMaskBitmap = rxBitmap; + break; + } +} + + + + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterBitmapContainer.hxx b/sdext/source/presenter/PresenterBitmapContainer.hxx new file mode 100644 index 000000000000..500899992605 --- /dev/null +++ b/sdext/source/presenter/PresenterBitmapContainer.hxx @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_BITMAP_CONTAINER_HXX +#define SDEXT_PRESENTER_BITMAP_CONTAINER_HXX + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/rendering/XBitmap.hpp> +#include <com/sun/star/rendering/XCanvas.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/util/Color.hpp> +#include <boost/noncopyable.hpp> +#include <boost/scoped_ptr.hpp> +#include <map> +#include <vector> +#include <boost/shared_ptr.hpp> + +namespace css = ::com::sun::star; + + +namespace sdext { namespace presenter { + +/** Manage a set of bitmap groups as they are used for buttons: three + bitmaps, one for the normal state, one for a mouse over effect and one + to show that the button has been pressed. + A bitmap group is defined by some entries in the configuration. +*/ +class PresenterBitmapContainer + : private ::boost::noncopyable +{ +public: + /** There is one bitmap for the normal state, one for a mouse over effect and one + to show that a button has been pressed. + */ + class BitmapDescriptor + { + public: + BitmapDescriptor (void); + BitmapDescriptor (const ::boost::shared_ptr<BitmapDescriptor>& rpDefault); + + enum Mode {Normal, MouseOver, ButtonDown, Disabled, Mask}; + css::uno::Reference<css::rendering::XBitmap> GetNormalBitmap (void) const; + css::uno::Reference<css::rendering::XBitmap> GetBitmap ( + const Mode eMode, + const bool bMissingDefaultsToNormal = true) const; + void SetBitmap ( + const Mode eMode, + const css::uno::Reference<css::rendering::XBitmap>& rxBitmap); + + sal_Int32 mnWidth; + sal_Int32 mnHeight; + sal_Int32 mnXOffset; + sal_Int32 mnYOffset; + sal_Int32 mnXHotSpot; + sal_Int32 mnYHotSpot; + css::util::Color maReplacementColor; + enum TexturingMode { Once, Repeat, Stretch }; + TexturingMode meHorizontalTexturingMode; + TexturingMode meVerticalTexturingMode; + + private: + css::uno::Reference<css::rendering::XBitmap> mxNormalBitmap; + css::uno::Reference<css::rendering::XBitmap> mxMouseOverBitmap; + css::uno::Reference<css::rendering::XBitmap> mxButtonDownBitmap; + css::uno::Reference<css::rendering::XBitmap> mxDisabledBitmap; + css::uno::Reference<css::rendering::XBitmap> mxMaskBitmap; + }; + + /** Create a new bitmap container from a section of the configuration. + @param rxComponentContext + The component context is used to create new API objects. + @param rxCanvas + Bitmaps are created specifically for this canvas. + @param rsConfigurationBase + The name of a configuration node whose sub-tree defines the + bitmap sets. + */ + PresenterBitmapContainer ( + const ::rtl::OUString& rsConfigurationBase, + const ::boost::shared_ptr<PresenterBitmapContainer>& rpParentContainer, + const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const ::rtl::OUString& rsBasePath, + const css::uno::Reference<css::drawing::XPresenterHelper>& rxPresenterHelper = NULL); + PresenterBitmapContainer ( + const css::uno::Reference<css::container::XNameAccess>& rsRootNode, + const ::boost::shared_ptr<PresenterBitmapContainer>& rpParentContainer, + const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const ::rtl::OUString& rsBasePath, + const css::uno::Reference<css::drawing::XPresenterHelper>& rxPresenterHelper = NULL); + ~PresenterBitmapContainer (void); + + void Initialize ( + const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext); + + /** Return the bitmap set that is associated with the given name. + */ + ::boost::shared_ptr<BitmapDescriptor> GetBitmap (const ::rtl::OUString& rsName) const; + + static ::boost::shared_ptr<BitmapDescriptor> LoadBitmap ( + const css::uno::Reference<css::container::XHierarchicalNameAccess>& rxNode, + const ::rtl::OUString& rsPathToBitmapNode, + const css::uno::Reference<css::drawing::XPresenterHelper>& rxPresenterHelper, + const ::rtl::OUString& rsBitmapBasePath, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const ::boost::shared_ptr<BitmapDescriptor>& rpDefaultBitmap); + +private: + ::boost::shared_ptr<PresenterBitmapContainer> mpParentContainer; + typedef ::std::map<rtl::OUString, ::boost::shared_ptr<BitmapDescriptor> > BitmapContainer; + BitmapContainer maIconContainer; + ::rtl::OUString msBasePath; + css::uno::Reference<css::rendering::XCanvas> mxCanvas; + css::uno::Reference<css::drawing::XPresenterHelper> mxPresenterHelper; + + void LoadBitmaps ( + const css::uno::Reference<css::container::XNameAccess>& rsRootNode); + void ProcessBitmap ( + const ::rtl::OUString& rsKey, + const css::uno::Reference<css::beans::XPropertySet>& rProperties); + static ::boost::shared_ptr<BitmapDescriptor> LoadBitmap ( + const css::uno::Reference<css::beans::XPropertySet>& rxProperties, + const css::uno::Reference<css::drawing::XPresenterHelper>& rxPresenterHelper, + const ::rtl::OUString& rsBasePath, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const ::boost::shared_ptr<PresenterBitmapContainer::BitmapDescriptor>& rpDefault); + static BitmapDescriptor::TexturingMode + StringToTexturingMode (const ::rtl::OUString& rsTexturingMode); +}; + + +typedef PresenterBitmapContainer::BitmapDescriptor PresenterBitmapDescriptor; +typedef ::boost::shared_ptr<PresenterBitmapContainer::BitmapDescriptor> SharedBitmapDescriptor; + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterButton.cxx b/sdext/source/presenter/PresenterButton.cxx new file mode 100644 index 000000000000..e13bbcdc1386 --- /dev/null +++ b/sdext/source/presenter/PresenterButton.cxx @@ -0,0 +1,615 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * 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 <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/TextDirection.hpp> +#include <boost/bind.hpp> + +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> PresenterButton::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) +{ + Reference<beans::XPropertySet> 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<PresenterButton> 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<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) + : 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<lang::XMultiComponentFactory> xFactory (rxComponentContext->getServiceManager()); + if ( ! xFactory.is()) + throw RuntimeException(); + + mxPresenterHelper = Reference<drawing::XPresenterHelper>( + xFactory->createInstanceWithContext( + OUString(RTL_CONSTASCII_USTRINGPARAM("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<awt::XWindowPeer> 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<lang::XComponent> 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<lang::XComponent> 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<css::rendering::XCanvas>& rxParentCanvas, + const css::uno::Reference<css::awt::XWindow>& rxParentWindow) +{ + if (mxCanvas.is()) + { + Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY); + mxCanvas = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + + if (mxPresenterHelper.is() && rxParentCanvas.is() && rxParentWindow.is()) + { + mxCanvas = mxPresenterHelper->createSharedCanvas ( + Reference<rendering::XSpriteCanvas>(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<rendering::XBitmap> 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<double>(4), + rendering::CompositeOperation::SOURCE); + + mxCanvas->drawBitmap(xBitmap, aViewState, aRenderState); + + Reference<rendering::XSpriteCanvas> 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<rendering::XCanvas>& 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<rendering::XTextLayout> 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<double>(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<rendering::XBitmap> 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<rendering::XCanvas> xCanvas (mxNormalBitmap, UNO_QUERY); + if (xCanvas.is()) + RenderButton( + xCanvas, + maButtonSize, + mpFont, + PresenterBitmapDescriptor::Normal, + pLeftBitmap, + pCenterBitmap, + pRightBitmap); + + mxMouseOverBitmap = mxCanvas->getDevice()->createCompatibleAlphaBitmap(maButtonSize); + xCanvas = Reference<rendering::XCanvas>(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<beans::XPropertySet> PresenterButton::GetConfigurationProperties ( + const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext, + const OUString& rsConfgurationName) +{ + PresenterConfigurationAccess aConfiguration ( + rxComponentContext, + PresenterConfigurationAccess::msPresenterScreenRootName, + PresenterConfigurationAccess::READ_ONLY); + return Reference<beans::XPropertySet>( + PresenterConfigurationAccess::Find ( + Reference<container::XNameAccess>( + 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<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + } +} + + +} } // end of namespace sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterButton.hxx b/sdext/source/presenter/PresenterButton.hxx new file mode 100644 index 000000000000..b952a9bfa77c --- /dev/null +++ b/sdext/source/presenter/PresenterButton.hxx @@ -0,0 +1,188 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_BUTTON_HXX +#define SDEXT_PRESENTER_PRESENTER_BUTTON_HXX + +#include "PresenterBitmapContainer.hxx" +#include "PresenterTheme.hxx" +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/XWindowListener.hpp> +#include <com/sun/star/awt/XPaintListener.hpp> +#include <com/sun/star/awt/XMouseListener.hpp> +#include <com/sun/star/awt/XMouseMotionListener.hpp> +#include <com/sun/star/rendering/XCanvas.hpp> +#include <com/sun/star/rendering/XBitmap.hpp> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase4.hxx> +#include <boost/noncopyable.hpp> +#include <rtl/ref.hxx> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +class PresenterController; + +namespace { + typedef ::cppu::WeakComponentImplHelper4 < + css::awt::XWindowListener, + css::awt::XPaintListener, + css::awt::XMouseListener, + css::awt::XMouseMotionListener + > PresenterButtonInterfaceBase; +} + +/** Button for the presenter screen. It displays a text surrounded by a + frame. +*/ +class PresenterButton + : private ::boost::noncopyable, + private ::cppu::BaseMutex, + public PresenterButtonInterfaceBase +{ +public: + static ::rtl::Reference<PresenterButton> 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 ::rtl::OUString& rsConfigurationName); + ~PresenterButton (void); + + virtual void SAL_CALL disposing (void); + + void SetCenter (const css::geometry::RealPoint2D& rLocation); + void SetCanvas ( + const css::uno::Reference<css::rendering::XCanvas>& rxParentCanvas, + const css::uno::Reference<css::awt::XWindow>& rxParentWindow); + css::geometry::IntegerSize2D GetSize (void); + + // XWindowListener + + virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // XPaintListener + + virtual void SAL_CALL windowPaint (const css::awt::PaintEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XMouseListener + + virtual void SAL_CALL mousePressed (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL mouseReleased (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL mouseEntered (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL mouseExited (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + + // XMouseMotionListener + + virtual void SAL_CALL mouseMoved (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseDragged (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + + // lang::XEventListener + virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + +private: + ::rtl::Reference<PresenterController> mpPresenterController; + ::boost::shared_ptr<PresenterTheme> mpTheme; + css::uno::Reference<css::awt::XWindow> mxWindow; + css::uno::Reference<css::rendering::XCanvas> mxCanvas; + css::uno::Reference<css::drawing::XPresenterHelper> mxPresenterHelper; + const ::rtl::OUString msText; + const PresenterTheme::SharedFontDescriptor mpFont; + const PresenterTheme::SharedFontDescriptor mpMouseOverFont; + const ::rtl::OUString msAction; + css::geometry::RealPoint2D maCenter; + css::geometry::IntegerSize2D maButtonSize; + PresenterBitmapDescriptor::Mode meState; + css::uno::Reference<css::rendering::XBitmap> mxNormalBitmap; + css::uno::Reference<css::rendering::XBitmap> mxMouseOverBitmap; + + 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& rFont, + const PresenterTheme::SharedFontDescriptor& rMouseOverFont, + const ::rtl::OUString& rxText, + const ::rtl::OUString& rxAction); + void RenderButton ( + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::geometry::IntegerSize2D& rSize, + const PresenterTheme::SharedFontDescriptor& rFont, + const PresenterBitmapDescriptor::Mode eMode, + const SharedBitmapDescriptor& rpLeft, + const SharedBitmapDescriptor& rpCenter, + const SharedBitmapDescriptor& rpRight); + css::geometry::IntegerSize2D CalculateButtonSize (void); + void Invalidate (void); + css::uno::Reference<css::rendering::XBitmap> GetBitmap ( + const SharedBitmapDescriptor& mpIcon, + const PresenterBitmapDescriptor::Mode eMode); + void SetupButtonBitmaps (void); + static css::uno::Reference<css::beans::XPropertySet> GetConfigurationProperties ( + const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext, + const ::rtl::OUString& rsConfgurationName); + + void ThrowIfDisposed (void) const + throw (::com::sun::star::lang::DisposedException); +}; + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterCanvasHelper.cxx b/sdext/source/presenter/PresenterCanvasHelper.cxx new file mode 100644 index 000000000000..f783b381a6e4 --- /dev/null +++ b/sdext/source/presenter/PresenterCanvasHelper.cxx @@ -0,0 +1,331 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterCanvasHelper.hxx" + +#include "PresenterController.hxx" +#include "PresenterGeometryHelper.hxx" +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/TextDirection.hpp> +#include <com/sun/star/rendering/TexturingMode.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace sdext { namespace presenter { + +PresenterCanvasHelper::PresenterCanvasHelper (void) + : maDefaultViewState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL), + maDefaultRenderState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE) +{ +} + + + + +PresenterCanvasHelper::~PresenterCanvasHelper (void) +{ +} + + + + +void PresenterCanvasHelper::Paint ( + const SharedBitmapDescriptor& rpBitmap, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRepaintBox, + const css::awt::Rectangle& rOuterBoundingBox, + const css::awt::Rectangle& rContentBoundingBox) const +{ + PaintRectangle(rpBitmap,rxCanvas,rRepaintBox,rOuterBoundingBox,rContentBoundingBox, + maDefaultViewState, maDefaultRenderState); +} + + + + +void PresenterCanvasHelper::PaintRectangle ( + const SharedBitmapDescriptor& rpBitmap, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRepaintBox, + const css::awt::Rectangle& rOuterBoundingBox, + const css::awt::Rectangle& rContentBoundingBox, + const css::rendering::ViewState& rDefaultViewState, + const css::rendering::RenderState& rDefaultRenderState) +{ + if (rpBitmap.get() == NULL) + return; + + if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is()) + return; + + // Create a clip polypolygon that has the content box as hole. + ::std::vector<awt::Rectangle> aRectangles; + aRectangles.reserve(2); + aRectangles.push_back( + PresenterGeometryHelper::Intersection(rRepaintBox, rOuterBoundingBox)); + if (rContentBoundingBox.Width > 0 && rContentBoundingBox.Height > 0) + aRectangles.push_back( + PresenterGeometryHelper::Intersection(rRepaintBox, rContentBoundingBox)); + Reference<rendering::XPolyPolygon2D> xPolyPolygon ( + PresenterGeometryHelper::CreatePolygon( + aRectangles, + rxCanvas->getDevice())); + if ( ! xPolyPolygon.is()) + return; + xPolyPolygon->setFillRule(rendering::FillRule_EVEN_ODD); + + if (rpBitmap->GetNormalBitmap().is()) + { + if (rpBitmap->meHorizontalTexturingMode == PresenterBitmapDescriptor::Repeat + || rpBitmap->meVerticalTexturingMode == PresenterBitmapDescriptor::Repeat) + { + PaintTiledBitmap( + Reference<rendering::XBitmap>(rpBitmap->GetNormalBitmap(), UNO_QUERY), + rxCanvas, + rRepaintBox, + xPolyPolygon, + rContentBoundingBox, + rDefaultViewState, + rDefaultRenderState); + } + else + { + PaintBitmap( + Reference<rendering::XBitmap>(rpBitmap->GetNormalBitmap(), UNO_QUERY), + awt::Point(rOuterBoundingBox.X, rOuterBoundingBox.Y), + rxCanvas, + rRepaintBox, + xPolyPolygon, + rDefaultViewState, + rDefaultRenderState); + } + } + else + { + PaintColor( + rpBitmap->maReplacementColor, + rxCanvas, + rRepaintBox, + xPolyPolygon, + rDefaultViewState, + rDefaultRenderState); + } +} + + + + +void PresenterCanvasHelper::PaintTiledBitmap ( + const css::uno::Reference<css::rendering::XBitmap>& rxTexture, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRepaintBox, + const css::uno::Reference<css::rendering::XPolyPolygon2D>& rxPolygon, + const css::awt::Rectangle& rHole, + const css::rendering::ViewState& rDefaultViewState, + const css::rendering::RenderState& rDefaultRenderState) +{ + if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is()) + return; + + if ( ! rxTexture.is()) + return; + + if ( ! rxPolygon.is()) + return; + + rendering::ViewState aViewState (rDefaultViewState); + aViewState.Clip = rxPolygon; + + // Create a local render state at which the location of the bitmap is + // set. + rendering::RenderState aRenderState (rDefaultRenderState); + + + // Tile the bitmap over the repaint box. + const geometry::IntegerSize2D aBitmapSize (rxTexture->getSize()); + const sal_Int32 nLeft = (rRepaintBox.X / aBitmapSize.Width) * aBitmapSize.Width; + const sal_Int32 nTop = (rRepaintBox.Y / aBitmapSize.Height) * aBitmapSize.Height; + const sal_Int32 nRight = ((rRepaintBox.X + rRepaintBox.Width - 1 + aBitmapSize.Width - 1) + / aBitmapSize.Width) * aBitmapSize.Width; + const sal_Int32 nBottom = ((rRepaintBox.Y + rRepaintBox.Height - 1 + aBitmapSize.Height - 1) + / aBitmapSize.Height) * aBitmapSize.Height; + + for (sal_Int32 nY=nTop; nY<=nBottom; nY+=aBitmapSize.Height) + for (sal_Int32 nX=nLeft; nX<=nRight; nX+=aBitmapSize.Width) + { + if (PresenterGeometryHelper::IsInside( + awt::Rectangle(nX,nY,aBitmapSize.Width,aBitmapSize.Height), + rHole)) + { + continue; + } + aRenderState.AffineTransform.m02 = nX; + aRenderState.AffineTransform.m12 = nY; + rxCanvas->drawBitmap( + rxTexture, + aViewState, + aRenderState); + } +} + + + + +void PresenterCanvasHelper::PaintBitmap ( + const css::uno::Reference<css::rendering::XBitmap>& rxBitmap, + const awt::Point& rLocation, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRepaintBox, + const css::uno::Reference<css::rendering::XPolyPolygon2D>& rxPolygon, + const css::rendering::ViewState& rDefaultViewState, + const css::rendering::RenderState& rDefaultRenderState) +{ + if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is()) + return; + + if ( ! rxBitmap.is()) + return; + + if ( ! rxPolygon.is()) + return; + + // Set the repaint box as clip rectangle at the view state. + rendering::ViewState aViewState (rDefaultViewState); + aViewState.Clip = PresenterGeometryHelper::CreatePolygon(rRepaintBox, rxCanvas->getDevice()); + + + // Setup the rendering state so that the bitmap is painted top left in + // the polygon bounding box. + rendering::RenderState aRenderState (rDefaultRenderState); + aRenderState.AffineTransform = geometry::AffineMatrix2D(1,0, rLocation.X, 0,1,rLocation.Y); + aRenderState.Clip = rxPolygon; + + rxCanvas->drawBitmap( + rxBitmap, + aViewState, + aRenderState); +} + + + + +void PresenterCanvasHelper::PaintColor ( + const css::util::Color nColor, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRepaintBox, + const css::uno::Reference<css::rendering::XPolyPolygon2D>& rxPolygon, + const css::rendering::ViewState& rDefaultViewState, + const css::rendering::RenderState& rDefaultRenderState) +{ + if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is()) + return; + + if ( ! rxPolygon.is()) + return; + + // Set the repaint box as clip rectangle at the view state. + rendering::ViewState aViewState (rDefaultViewState); + aViewState.Clip = PresenterGeometryHelper::CreatePolygon(rRepaintBox, rxCanvas->getDevice()); + + + // Setup the rendering state to use the given color. + rendering::RenderState aRenderState (rDefaultRenderState); + SetDeviceColor(aRenderState, nColor); + + rxCanvas->fillPolyPolygon( + rxPolygon, + aViewState, + aRenderState); +} + + + + +void PresenterCanvasHelper::SetDeviceColor( + rendering::RenderState& rRenderState, + const util::Color aColor) +{ + // Other component counts then 4 (RGBA) are not accepted (anymore). + + OSL_ASSERT(rRenderState.DeviceColor.getLength() == 4); + if (rRenderState.DeviceColor.getLength() == 4) + { + rRenderState.DeviceColor[0] = ((aColor >> 16) & 0x0ff) / 255.0; + rRenderState.DeviceColor[1] = ((aColor >> 8) & 0x0ff) / 255.0; + rRenderState.DeviceColor[2] = ((aColor >> 0) & 0x0ff) / 255.0; + rRenderState.DeviceColor[3] = 1.0 - ((aColor >> 24) & 0x0ff) / 255.0; + } +} + + + + +css::geometry::RealRectangle2D PresenterCanvasHelper::GetTextBoundingBox ( + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, + const ::rtl::OUString& rsText, + const sal_Int8 nTextDirection) +{ + if (rxFont.is() && rsText.getLength() > 0) + { + rendering::StringContext aContext (rsText, 0, rsText.getLength()); + Reference<rendering::XTextLayout> xLayout ( + rxFont->createTextLayout(aContext, nTextDirection, 0)); + return xLayout->queryTextBounds(); + } + else + { + return geometry::RealRectangle2D(0,0,0,0); + } +} + + + + +css::geometry::RealSize2D PresenterCanvasHelper::GetTextSize ( + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, + const ::rtl::OUString& rsText, + const sal_Int8 nTextDirection) +{ + const geometry::RealRectangle2D aTextBBox (GetTextBoundingBox(rxFont, rsText, nTextDirection)); + return css::geometry::RealSize2D(aTextBBox.X2 - aTextBBox.X1, aTextBBox.Y2 - aTextBBox.Y1); +} + + +} } // end of namespace sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterCanvasHelper.hxx b/sdext/source/presenter/PresenterCanvasHelper.hxx new file mode 100644 index 000000000000..58dde30788e6 --- /dev/null +++ b/sdext/source/presenter/PresenterCanvasHelper.hxx @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_CANVAS_HELPER_HXX +#define SDEXT_PRESENTER_PRESENTER_CANVAS_HELPER_HXX + +#include "PresenterTheme.hxx" +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/rendering/TextDirection.hpp> +#include <com/sun/star/rendering/XCanvas.hpp> +#include <com/sun/star/rendering/XCanvasFont.hpp> +#include <com/sun/star/rendering/XPolyPolygon2D.hpp> +#include <rtl/ref.hxx> +#include <boost/noncopyable.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +class PresenterController; + +/** Collection of functions to ease the life of a canvas user. +*/ +class PresenterCanvasHelper + : ::boost::noncopyable +{ +public: + PresenterCanvasHelper (void); + ~PresenterCanvasHelper (void); + + void Paint ( + const SharedBitmapDescriptor& rpBitmap, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRepaintBox, + const css::awt::Rectangle& rBackgroundBoundingBox, + const css::awt::Rectangle& rContentBoundingBox) const; + + static void PaintRectangle ( + const SharedBitmapDescriptor& rpBitmap, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRepaintBox, + const css::awt::Rectangle& rBackgroundBoundingBox, + const css::awt::Rectangle& rContentBoundingBox, + const css::rendering::ViewState& rDefaultViewState, + const css::rendering::RenderState& rDefaultRenderState); + + static void SetDeviceColor( + css::rendering::RenderState& rRenderState, + const css::util::Color aColor); + + static css::geometry::RealRectangle2D GetTextBoundingBox ( + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, + const ::rtl::OUString& rsText, + const sal_Int8 = css::rendering::TextDirection::WEAK_LEFT_TO_RIGHT); + + static css::geometry::RealSize2D GetTextSize ( + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, + const ::rtl::OUString& rsText, + const sal_Int8 = css::rendering::TextDirection::WEAK_LEFT_TO_RIGHT); + +private: + const css::rendering::ViewState maDefaultViewState; + const css::rendering::RenderState maDefaultRenderState; + + static void PaintTiledBitmap ( + const css::uno::Reference<css::rendering::XBitmap>& rxTexture, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRepaintBox, + const css::uno::Reference<css::rendering::XPolyPolygon2D>& rxPolygon, + const css::awt::Rectangle& rHole, + const css::rendering::ViewState& rDefaultViewState, + const css::rendering::RenderState& rDefaultRenderState); + + static void PaintBitmap ( + const css::uno::Reference<css::rendering::XBitmap>& rxBitmap, + const css::awt::Point& rLocation, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRepaintBox, + const css::uno::Reference<css::rendering::XPolyPolygon2D>& rxPolygon, + const css::rendering::ViewState& rDefaultViewState, + const css::rendering::RenderState& rDefaultRenderState); + + static void PaintColor ( + const css::util::Color nColor, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRepaintBox, + const css::uno::Reference<css::rendering::XPolyPolygon2D>& rxPolygon, + const css::rendering::ViewState& rDefaultViewState, + const css::rendering::RenderState& rDefaultRenderState); +}; + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterClock.cxx b/sdext/source/presenter/PresenterClock.cxx new file mode 100644 index 000000000000..1d14b6473e20 --- /dev/null +++ b/sdext/source/presenter/PresenterClock.cxx @@ -0,0 +1,1445 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterClock.hxx" +#include "PresenterComponent.hxx" +#include "PresenterConfigurationAccess.hxx" +#include "PresenterGeometryHelper.hxx" +#include <com/sun/star/awt/InvalidateStyle.hpp> +#include <com/sun/star/awt/MouseButton.hpp> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/deployment/XPackageInformationProvider.hpp> +#include <com/sun/star/drawing/framework/XControllerManager.hpp> +#include <com/sun/star/drawing/framework/XConfigurationController.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/PathCapType.hpp> +#include <com/sun/star/rendering/TextDirection.hpp> +#include <com/sun/star/rendering/XCanvasFont.hpp> +#include <com/sun/star/rendering/XSpriteCanvas.hpp> +#include <com/sun/star/util/Color.hpp> +#include <osl/mutex.hxx> +#include <osl/time.h> +#include <rtl/ref.hxx> +#include <salhelper/timer.hxx> +#include <boost/bind.hpp> +#include <cmath> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +namespace sdext { namespace presenter { + + +/** Wrapper around a library timer. +*/ +class PresenterClock::Timer : public salhelper::Timer +{ +public: + explicit Timer (const ::rtl::Reference<PresenterClock>& rpClock); + virtual ~Timer (void); + + void Stop (void); + +protected: + virtual void SAL_CALL onShot (void); + +private: + ::rtl::Reference<PresenterClock> mpClock; +}; + + + + +namespace { + bool GetDateTime (oslDateTime& rDateTime); + + class BitmapDescriptor + { + public: + Reference<rendering::XBitmap> mxBitmap; + awt::Point maOffset; + Reference<rendering::XBitmap> mxScaledBitmap; + geometry::RealPoint2D maScaledOffset; + }; +} + + + + +class PresenterClock::Painter +{ +public: + virtual void Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState, + const rendering::RenderState& rRenderState, + const util::Color& rBackgroundColor, + const sal_Int32 nHour, + const sal_Int32 nMinute, + const sal_Int32 nSecond, + const bool bShowSeconds) = 0; + virtual void Resize (const awt::Size& rSize) = 0; +}; + + + + +namespace { + class AnalogDefaultPainter : public PresenterClock::Painter + { + public: + AnalogDefaultPainter (void); + virtual ~AnalogDefaultPainter (void) {} + virtual void Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState, + const rendering::RenderState& rRenderState, + const util::Color& rBackgroundColor, + const sal_Int32 nHour, + const sal_Int32 nMinute, + const sal_Int32 nSecond, + const bool bShowSeconds); + virtual void Resize (const awt::Size& rSize); + private: + geometry::RealPoint2D maCenter; + double mnOuterRadius; + awt::Size maSize; + Reference<rendering::XBitmap> mxBitmap; + + /** Relative length (with respect to radius) from center to the tip of + the hand. + */ + static const double mnRelativeHourHandLength; + /** Relative length (with respect to radius) from center to the + oposing end of the tip of the hand. + */ + static const double mnRelativeHourHandLength2; + static const double mnRelativeHourHandWidth; + static const double mnRelativeMinuteHandLength; + static const double mnRelativeMinuteHandLength2; + static const double mnRelativeMinuteHandWidth; + static const double mnRelativeSecondHandLength; + static const double mnRelativeSecondHandLength2; + static const double mnRelativeSecondHandWidth; + + void PaintAngledLine ( + const double nAngle, + const double nInnerRadius, + const double nOuterRadius, + const double nStrokeWidth, + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState, + const rendering::RenderState& rRenderState); + }; + + + class AnalogBitmapPainter : public PresenterClock::Painter + { + public: + AnalogBitmapPainter( + const Reference<XComponentContext>& rxContext, + const OUString& rsThemeName); + virtual ~AnalogBitmapPainter (void) {} + virtual void Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState, + const rendering::RenderState& rRenderState, + const util::Color& rBackgroundColor, + const sal_Int32 nHour, + const sal_Int32 nMinute, + const sal_Int32 nSecond, + const bool bShowSeconds); + virtual void Resize (const awt::Size& rSize); + private: + css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + const OUString msThemeName; + bool mbThemeLoaded; + bool mbThemeLoadingFailed; + geometry::RealPoint2D maCenter; + double mnOuterRadius; + BitmapDescriptor maFace; + BitmapDescriptor maMinuteHand; + BitmapDescriptor maHourHand; + + void PrepareBitmaps (const Reference<rendering::XCanvas>& rxCanvas); + Reference<container::XNameAccess> GetTheme ( + PresenterConfigurationAccess& rConfiguration); + bool ThemeNameComparator ( + const ::rtl::OUString& rsKey, + const Reference<container::XNameAccess>& rxCandidate, + const ::rtl::OUString& rsCurrentThemeName); + void LoadBitmaps ( + PresenterConfigurationAccess& rConfiguration, + const Reference<container::XNameAccess>& rxNameAccess, + const Reference<rendering::XCanvas>& rxCanvas); + void LoadBitmap ( + const OUString& rsKey, + const ::std::vector<Any>& rValues, + const OUString& rsBitmapPath, + const Reference<container::XNameAccess>& rxBitmapLoader); + void ScaleBitmaps (void); + }; + + + class DigitalDefaultPainter : public PresenterClock::Painter + { + public: + DigitalDefaultPainter ( + const ::rtl::Reference<PresenterController>& rpPresenterController, + const Reference<XResourceId>& rxViewId); + virtual ~DigitalDefaultPainter (void); + + virtual void Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState, + const rendering::RenderState& rRenderState, + const util::Color& rBackgroundColor, + const sal_Int32 nHour, + const sal_Int32 nMinute, + const sal_Int32 nSecond, + const bool bShowSeconds); + virtual void Resize (const awt::Size& rSize); + + private: + ::rtl::Reference<PresenterController> mpPresenterController; + bool mbIs24HourFormat; + bool mbIsAdaptFontSize; + Reference<rendering::XCanvasFont> mxFont; + awt::Size maWindowSize; + OUString msViewURL; + + void CreateFont ( + const Reference<rendering::XCanvas>& rxCanvas, + const bool bIsShowSeconds); + }; + + +} // end of anonymous namespace + + + + +//===== PresenterClock ================================================================= + +::rtl::Reference<PresenterClock> PresenterClock::Create ( + const Reference<XComponentContext>& rxContext, + const Reference<XResourceId>& rxViewId, + const Reference<frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController) +{ + ::rtl::Reference<PresenterClock> pClock (new PresenterClock( + rxContext, + rxViewId, + rxController, + rpPresenterController)); + pClock->LateInit(); + return pClock; +} + + + + +PresenterClock::PresenterClock ( + const Reference<XComponentContext>& rxContext, + const Reference<XResourceId>& rxViewId, + const Reference<frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterClockInterfaceBase(m_aMutex), + mxComponentContext(rxContext), + mxViewId(rxViewId), + mxWindow(), + mxCanvas(), + mxPane(), + mpPresenterController(rpPresenterController), + mbIsResizePending(true), + maViewState(), + maRenderState(), + mpTimer(), + mpClockPainter(), + mpClockPainter2(), + mnMode(1), + mnHour(-1), + mnMinute(-1), + mnSecond(-1), + mbIsShowSeconds(true) +{ + SetMode(mnMode); + + maViewState.AffineTransform = geometry::AffineMatrix2D(1,0,0, 0,1,0); + maRenderState.AffineTransform = geometry::AffineMatrix2D(1,0,0, 0,1,0); + maRenderState.DeviceColor = Sequence<double>(4); + PresenterCanvasHelper::SetDeviceColor(maRenderState, util::Color(0x00000000)); + + try + { + + Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW); + Reference<XConfigurationController> xCC (xCM->getConfigurationController(), UNO_QUERY_THROW); + mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW); + + mxWindow = mxPane->getWindow(); + if (mxWindow.is()) + { + mxWindow->addPaintListener(this); + mxWindow->addWindowListener(this); + mxWindow->addMouseListener(this); + Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY); + if (xPeer.is()) + xPeer->setBackground(util::Color(0xff000000)); + mxWindow->setVisible(sal_True); + } + + Resize(); + } + catch (RuntimeException&) + { + disposing(); + throw; + } +} + + + + +PresenterClock::~PresenterClock (void) +{ +} + + + + +void PresenterClock::LateInit (void) +{ + mpTimer = new Timer(this); +} + + + + +void SAL_CALL PresenterClock::disposing (void) +{ + if (mpTimer != NULL) + { + mpTimer->Stop(); + } + if (mxWindow.is()) + { + mxWindow->removePaintListener(this); + mxWindow->removeWindowListener(this); + mxWindow->removeMouseListener(this); + mxWindow = NULL; + } + mxCanvas = NULL; + mxViewId = NULL; +} + + + + +void PresenterClock::UpdateTime (void) +{ + // Get current time and check whether it is different from last time. + oslDateTime aDateTime; + if ( ! GetDateTime(aDateTime)) + return; + if (aDateTime.Hours != mnHour + || aDateTime.Minutes != mnMinute + || aDateTime.Seconds != mnSecond) + { + mnHour = aDateTime.Hours % 24; + mnMinute = aDateTime.Minutes % 60; + mnSecond = aDateTime.Seconds % 60; + + Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY); + if (xPeer.is()) + xPeer->invalidate(awt::InvalidateStyle::NOERASE | + awt::InvalidateStyle::UPDATE); + } +} + + + + +//----- lang::XEventListener ------------------------------------------------- + +void SAL_CALL PresenterClock::disposing (const lang::EventObject& rEventObject) + throw (RuntimeException) +{ + if (rEventObject.Source == mxWindow) + { + mxWindow = NULL; + if (mpTimer != NULL) + mpTimer->Stop(); + } +} + + + + +//----- XPaintListener -------------------------------------------------------- + +void SAL_CALL PresenterClock::windowPaint (const awt::PaintEvent& rEvent) + throw (RuntimeException) +{ + ThrowIfDisposed(); + Paint(rEvent.UpdateRect); +} + + + + +//----- XWindowListener ------------------------------------------------------- + +void SAL_CALL PresenterClock::windowResized (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + mbIsResizePending = true; +} + + + + +void SAL_CALL PresenterClock::windowMoved (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + mbIsResizePending = true; +} + + + + +void SAL_CALL PresenterClock::windowShown (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + mbIsResizePending = true; +} + + + + +void SAL_CALL PresenterClock::windowHidden (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; +} + + + + +//----- XMouseListener -------------------------------------------------------- + +void SAL_CALL PresenterClock::mousePressed (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + if (rEvent.Buttons == awt::MouseButton::LEFT) + { + SetMode(mnMode+1); + } +} + + + + +void SAL_CALL PresenterClock::mouseReleased (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterClock::mouseEntered (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterClock::mouseExited (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +//----- XResourceId ----------------------------------------------------------- + +Reference<XResourceId> SAL_CALL PresenterClock::getResourceId (void) + throw (RuntimeException) +{ + return mxViewId; +} + + + + +sal_Bool SAL_CALL PresenterClock::isAnchorOnly (void) + throw (RuntimeException) +{ + return false; +} + + + + +//----------------------------------------------------------------------------- + +void PresenterClock::Resize (void) +{ + if (mxPane.is()) + mxCanvas = Reference<rendering::XCanvas>(mxPane->getCanvas(), UNO_QUERY); + if (mxWindow.is() && mxCanvas.is()) + { + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + const awt::Size aWindowSize(aWindowBox.Width,aWindowBox.Height); + if (mpClockPainter.get() != NULL) + mpClockPainter->Resize(aWindowSize); + if (mpClockPainter2.get() != NULL) + mpClockPainter2->Resize(aWindowSize); + mbIsResizePending = false; + } +} + + + + +void PresenterClock::Paint (const awt::Rectangle& rUpdateBox) +{ + if ( ! mxCanvas.is() && mxPane.is()) + mxCanvas = Reference<rendering::XCanvas>(mxPane->getCanvas(), UNO_QUERY); + if ( ! mxWindow.is() + || ! mxCanvas.is() + || ! mxCanvas->getDevice().is()) + { + return; + } + + try + { + if (mbIsResizePending) + Resize(); + + Reference<rendering::XPolyPolygon2D> xUpdatePolygon ( + PresenterGeometryHelper::CreatePolygon(rUpdateBox, mxCanvas->getDevice())); + + Clear(xUpdatePolygon); + + if (mpClockPainter.get() != NULL) + mpClockPainter->Paint(mxCanvas, + maViewState, + maRenderState, + mpPresenterController->GetViewBackgroundColor(mxViewId->getResourceURL()), + mnHour, + mnMinute, + mnSecond, + mbIsShowSeconds); + + if (mpClockPainter2.get() != NULL) + mpClockPainter2->Paint( + mxCanvas, + maViewState, + maRenderState, + mpPresenterController->GetViewBackgroundColor(mxViewId->getResourceURL()), + mnHour, + mnMinute, + mnSecond, + mbIsShowSeconds); + } + catch (RuntimeException& e) + { + (void)e; + } + + // Make the back buffer visible. + Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); + if (xSpriteCanvas.is()) + xSpriteCanvas->updateScreen(sal_False); +} + + + + +void PresenterClock::Clear (const Reference<rendering::XPolyPolygon2D>& rxUpdatePolygon) +{ + rendering::RenderState aRenderState = maRenderState; + const sal_Int32 nColor ( + mpPresenterController->GetViewBackgroundColor(mxViewId->getResourceURL())); + aRenderState.DeviceColor[0] = ((nColor&0x00ff0000) >> 16) / 255.0; + aRenderState.DeviceColor[1] = ((nColor&0x0000ff00) >> 8) / 255.0; + aRenderState.DeviceColor[2] = ((nColor&0x000000ff) >> 0) / 255.0; + + if (rxUpdatePolygon.is()) + mxCanvas->fillPolyPolygon( + rxUpdatePolygon, + maViewState, + aRenderState); +} + + + + +void PresenterClock::SetMode (const sal_Int32 nMode) +{ + mnMode = nMode % 3; + + switch (mnMode) + { + case 0: + mpClockPainter.reset( + new AnalogBitmapPainter( + mxComponentContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("ClockTheme")))); + mpClockPainter2.reset(); + break; + + case 1: + mpClockPainter.reset(); + mpClockPainter2.reset(new AnalogDefaultPainter()); + break; + + case 2: + mpClockPainter.reset(); + mpClockPainter2.reset(new DigitalDefaultPainter(mpPresenterController, mxViewId)); + break; + + case 3: + mpClockPainter.reset( + new AnalogBitmapPainter( + mxComponentContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("ClockTheme")))); + mpClockPainter2.reset(new AnalogDefaultPainter()); + break; + } + Resize(); +} + + + + +void PresenterClock::ThrowIfDisposed (void) + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterClock object has already been disposed")), + static_cast<uno::XWeak*>(this)); + } +} + + + + +//===== Timer ================================================================= + +PresenterClock::Timer::Timer (const ::rtl::Reference<PresenterClock>& rpClock) + : salhelper::Timer(salhelper::TTimeValue(10), salhelper::TTimeValue(100/*ms*/)), + mpClock(rpClock) +{ + acquire(); + start(); +} + + + + +PresenterClock::Timer::~Timer (void) +{ + if (mpClock.is()) + Stop(); +} + + + + +void PresenterClock::Timer::Stop (void) +{ + mpClock = NULL; + stop(); + release(); +} + + + + +void SAL_CALL PresenterClock::Timer::onShot (void) +{ + if (mpClock.get() != NULL) + mpClock->UpdateTime(); +} + + + +namespace { + +//============================================================================= + +bool GetDateTime (oslDateTime& rDateTime) +{ + TimeValue aSystemTime; + TimeValue aLocalTime; + if (osl_getSystemTime(&aSystemTime)) + if (osl_getLocalTimeFromSystemTime(&aSystemTime, &aLocalTime)) + if (osl_getDateTimeFromTimeValue(&aLocalTime, &rDateTime)) + return true; + return false; +} + + + + +//===== AnalogDefaultPainter ================================================== + +const double AnalogDefaultPainter::mnRelativeHourHandLength = 0.65; +const double AnalogDefaultPainter::mnRelativeHourHandLength2 (-0.1); +const double AnalogDefaultPainter::mnRelativeHourHandWidth (0.055); +const double AnalogDefaultPainter::mnRelativeMinuteHandLength (-0.2); +const double AnalogDefaultPainter::mnRelativeMinuteHandLength2 (0.85); +const double AnalogDefaultPainter::mnRelativeMinuteHandWidth (0.025); +const double AnalogDefaultPainter::mnRelativeSecondHandLength (-0.25); +const double AnalogDefaultPainter::mnRelativeSecondHandLength2 (0.95); +const double AnalogDefaultPainter::mnRelativeSecondHandWidth (0.015); + +AnalogDefaultPainter::AnalogDefaultPainter (void) + : maCenter(0,0), + mnOuterRadius(0), + maSize(0,0), + mxBitmap() +{ +} + + + + +void AnalogDefaultPainter::Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState, + const rendering::RenderState& rRenderState, + const util::Color& rBackgroundColor, + const sal_Int32 nHour, + const sal_Int32 nMinute, + const sal_Int32 nSecond, + const bool bShowSeconds) +{ + double nInnerRadius (0); + double nStrokeWidth (0.1); + const double nClockSize (2*mnOuterRadius); + + // Some antialiasing is created by painting into a bitmap twice the + // screen size and then scaling it down. + const sal_Int32 nSuperSampleFactor (2); + if ( ! mxBitmap.is()) + { + mxBitmap = (rxCanvas->getDevice()->createCompatibleBitmap( + geometry::IntegerSize2D( + maSize.Width*nSuperSampleFactor, + maSize.Height*nSuperSampleFactor))); + } + Reference<rendering::XCanvas> xBitmapCanvas (mxBitmap, UNO_QUERY); + rendering::RenderState aRenderState(rRenderState); + aRenderState.AffineTransform.m00 = nSuperSampleFactor; + aRenderState.AffineTransform.m11 = nSuperSampleFactor; + + // Clear the background. + aRenderState.DeviceColor[0] = ((rBackgroundColor&0x00ff0000) >> 16) / 255.0; + aRenderState.DeviceColor[1] = ((rBackgroundColor&0x0000ff00) >> 8) / 255.0; + aRenderState.DeviceColor[2] = ((rBackgroundColor&0x000000ff) >> 0) / 255.0; + Reference<rendering::XPolyPolygon2D> xPolygon ( + PresenterGeometryHelper::CreatePolygon( + awt::Rectangle(0,0,maSize.Width,maSize.Height), + xBitmapCanvas->getDevice())); + if (xPolygon.is()) + xBitmapCanvas->fillPolyPolygon(xPolygon, rViewState, aRenderState); + + // Clock face and clock hands are painted in black. + aRenderState.DeviceColor[0] = 0; + aRenderState.DeviceColor[1] = 0; + aRenderState.DeviceColor[2] = 0; + + // Paint the clock face. + for (sal_Int32 nHourMark=0; nHourMark<12; ++nHourMark) + { + if (nHourMark%3 == 0) + { + nInnerRadius = 0.7 * mnOuterRadius; + nStrokeWidth = 0.05 * nClockSize; + } + else + { + nInnerRadius = 0.8 * mnOuterRadius; + nStrokeWidth = 0.03 * nClockSize; + } + + const double nAngle (nHourMark * 2 * M_PI / 12); + PaintAngledLine(nAngle, nInnerRadius, mnOuterRadius, nStrokeWidth, + xBitmapCanvas, rViewState, aRenderState); + } + + // Paint the hour hand. + const double nHoursAngle (((nHour%12)+nMinute/60.0) * 2 * M_PI / 12); + PaintAngledLine(nHoursAngle, + mnRelativeHourHandLength2*mnOuterRadius, + mnRelativeHourHandLength*mnOuterRadius, + mnRelativeHourHandWidth*nClockSize, + xBitmapCanvas, rViewState, aRenderState); + + // Paint the minute hand. + const double nMinutesAngle ((nMinute+nSecond/60.0) * 2 * M_PI / 60); + PaintAngledLine(nMinutesAngle, + mnRelativeMinuteHandLength2*mnOuterRadius, + mnRelativeMinuteHandLength*mnOuterRadius, + mnRelativeMinuteHandWidth*nClockSize, + xBitmapCanvas, rViewState, aRenderState); + + // Optionally paint the second hand. + if (bShowSeconds) + { + const double nSecondsAngle (nSecond * 2 * M_PI / 60); + PaintAngledLine(nSecondsAngle, + mnRelativeSecondHandLength2*mnOuterRadius, + mnRelativeSecondHandLength*mnOuterRadius, + mnRelativeSecondHandWidth*nClockSize, + xBitmapCanvas, rViewState, aRenderState); + } + + aRenderState.AffineTransform.m00 = 1.0 / nSuperSampleFactor; + aRenderState.AffineTransform.m11 = 1.0 / nSuperSampleFactor; + rxCanvas->drawBitmap(mxBitmap,rViewState,aRenderState); +} + + + + +void AnalogDefaultPainter::PaintAngledLine ( + const double nAngle, + const double nInnerRadius, + const double nOuterRadius, + const double nStrokeWidth, + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState, + const rendering::RenderState& rRenderState) +{ + if ( ! rxCanvas.is()) + return; + + rendering::StrokeAttributes aStrokeAttributes; + aStrokeAttributes.StrokeWidth = nStrokeWidth; + aStrokeAttributes.StartCapType = rendering::PathCapType::SQUARE; + aStrokeAttributes.EndCapType = rendering::PathCapType::SQUARE; + aStrokeAttributes.StartCapType = rendering::PathCapType::BUTT; + aStrokeAttributes.EndCapType = rendering::PathCapType::BUTT; + const double nCos (cos(nAngle - M_PI/2)); + const double nSin (sin(nAngle - M_PI/2)); + + Sequence<Sequence<geometry::RealPoint2D> > aPoints(1); + aPoints[0] = Sequence<geometry::RealPoint2D>(2); + aPoints[0][0] = geometry::RealPoint2D( + maCenter.X + nInnerRadius*nCos + 0.5, + maCenter.Y + nInnerRadius*nSin + 0.5); + aPoints[0][1] = geometry::RealPoint2D( + maCenter.X + nOuterRadius*nCos + 0.5, + maCenter.Y + nOuterRadius*nSin + 0.5); + + Reference<rendering::XPolyPolygon2D> xLine ( + rxCanvas->getDevice()->createCompatibleLinePolyPolygon(aPoints), + UNO_QUERY); + if ( ! xLine.is()) + return; + rxCanvas->strokePolyPolygon( + xLine, + rViewState, + rRenderState, + aStrokeAttributes); +} + + + + +void AnalogDefaultPainter::Resize (const awt::Size& rWindowSize) +{ + maSize = rWindowSize; + maCenter = geometry::RealPoint2D(rWindowSize.Width/2.0, rWindowSize.Height/2.0); + mnOuterRadius = ::std::min(rWindowSize.Width, rWindowSize.Height) / 2.0 - 2; + mxBitmap = NULL; +} + + + + +//===== AnalogBitmapPainter =================================================== + +AnalogBitmapPainter::AnalogBitmapPainter ( + const Reference<XComponentContext>& rxContext, + const OUString& rsThemeName) + : mxComponentContext(rxContext), + msThemeName(rsThemeName), + mbThemeLoaded(false), + mbThemeLoadingFailed(false), + maCenter(), + mnOuterRadius(), + maFace(), + maMinuteHand(), + maHourHand() +{ +} + + + + +void AnalogBitmapPainter::Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState, + const rendering::RenderState& rRenderState, + const util::Color& rBackgroundColor, + const sal_Int32 nHour, + const sal_Int32 nMinute, + const sal_Int32 nSecond, + const bool bShowSeconds) +{ + (void)rBackgroundColor; + (void)nSecond; + (void)bShowSeconds; + + if ( ! rxCanvas.is()) + return; + + rendering::RenderState aRenderState = rRenderState; + + try + { + PrepareBitmaps(rxCanvas); + + if (maFace.mxScaledBitmap.is()) + { + aRenderState.AffineTransform = geometry::AffineMatrix2D( + 1,0, maCenter.X - maFace.maScaledOffset.X, + 0,1, maCenter.Y - maFace.maScaledOffset.Y); + rxCanvas->drawBitmap(maFace.mxScaledBitmap, rViewState, aRenderState); + } + + if (maMinuteHand.mxScaledBitmap.is()) + { + const double nMinuteAngle ((nMinute+nSecond/60.0) * 2.0 * M_PI / 60.0); + const double nCos (cos(nMinuteAngle - M_PI/2)); + const double nSin (sin(nMinuteAngle - M_PI/2)); + aRenderState.AffineTransform = geometry::AffineMatrix2D( + nCos, + -nSin, + -maMinuteHand.maScaledOffset.X*nCos + + maMinuteHand.maScaledOffset.Y*nSin+maCenter.X, + nSin, + nCos, + -maMinuteHand.maScaledOffset.X*nSin + - maMinuteHand.maScaledOffset.Y*nCos+maCenter.Y); + rxCanvas->drawBitmap(maMinuteHand.mxScaledBitmap, rViewState, aRenderState); + } + + if (maHourHand.mxScaledBitmap.is()) + { + const double nHoursAngle ((nHour%12+nMinute/60.0) * 2.0 * M_PI / 12.0); + const double nCos (cos(nHoursAngle - M_PI/2)); + const double nSin (sin(nHoursAngle - M_PI/2)); + aRenderState.AffineTransform = geometry::AffineMatrix2D( + nCos, + -nSin, + -maHourHand.maScaledOffset.X*nCos+maHourHand.maScaledOffset.Y*nSin+maCenter.X, + nSin, + nCos, + -maHourHand.maScaledOffset.X*nSin-maHourHand.maScaledOffset.Y*nCos+maCenter.Y); + rxCanvas->drawBitmap(maHourHand.mxScaledBitmap, rViewState, aRenderState); + } + } + catch(beans::UnknownPropertyException&) + { + } + catch(RuntimeException&) + { + } +} + + + + +void AnalogBitmapPainter::Resize (const awt::Size& rWindowSize) +{ + maCenter = geometry::RealPoint2D(rWindowSize.Width/2.0, rWindowSize.Height/2.0); + mnOuterRadius = ::std::min(rWindowSize.Width, rWindowSize.Height) / 2.0 - 2; + maFace.mxScaledBitmap = NULL; + maHourHand.mxScaledBitmap = NULL; + maMinuteHand.mxScaledBitmap = NULL; +} + + + + +void AnalogBitmapPainter::PrepareBitmaps (const Reference<rendering::XCanvas>& rxCanvas) +{ + if (mbThemeLoadingFailed) + { + // Theme loading has failed previously. Do not try a second time. + return; + } + if ( ! rxCanvas.is()) + { + // No canvas => bitmaps can neither be loaded, transformed into the + // right format, nor can they be painted. + return; + } + + if ( ! mbThemeLoaded) + { + mbThemeLoaded = true; + + // Get access to the clock bitmaps in the configuration. + PresenterConfigurationAccess aConfiguration ( + mxComponentContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.extension.PresenterScreen")), + PresenterConfigurationAccess::READ_ONLY); + + Reference<container::XNameAccess> xTheme (GetTheme(aConfiguration)); + if (xTheme.is()) + LoadBitmaps(aConfiguration, xTheme, rxCanvas); + else + mbThemeLoadingFailed = true; + } + + ScaleBitmaps(); +} + + + + +Reference<container::XNameAccess> AnalogBitmapPainter::GetTheme ( + PresenterConfigurationAccess& rConfiguration) +{ + Reference<container::XNameAccess> xTheme; + + // Get root of clock themes. + Reference<container::XHierarchicalNameAccess> xClock ( + rConfiguration.GetConfigurationNode( + OUString(RTL_CONSTASCII_USTRINGPARAM("PresenterScreenSettings/AnalogBitmapClock"))), + UNO_QUERY); + + // Determine the name of the theme to use. + OUString sCurrentThemeName (RTL_CONSTASCII_USTRINGPARAM("DefaultTheme")); + rConfiguration.GetConfigurationNode( + xClock, + OUString(RTL_CONSTASCII_USTRINGPARAM("CurrentTheme"))) >>= sCurrentThemeName; + + // Load the clock theme. + Reference<container::XNameAccess> xThemes ( + rConfiguration.GetConfigurationNode( + xClock, + OUString(RTL_CONSTASCII_USTRINGPARAM("Themes"))), + UNO_QUERY); + if (xThemes.is()) + { + xTheme = Reference<container::XNameAccess>( + PresenterConfigurationAccess::Find( + xThemes, + ::boost::bind(&AnalogBitmapPainter::ThemeNameComparator, + this, _1, _2, sCurrentThemeName)), + UNO_QUERY); + } + + return xTheme; +} + + + + +bool AnalogBitmapPainter::ThemeNameComparator ( + const OUString& rsKey, + const Reference<container::XNameAccess>& rxCandidate, + const OUString& rsCurrentThemeName) +{ + (void)rsKey; + if (rxCandidate.is()) + { + OUString sThemeName; + if (rxCandidate->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("ThemeName"))) >>= sThemeName) + { + return sThemeName == rsCurrentThemeName; + } + } + return false; +} + + + + + +void AnalogBitmapPainter::LoadBitmaps ( + PresenterConfigurationAccess& rConfiguration, + const Reference<container::XNameAccess>& rxClockTheme, + const Reference<rendering::XCanvas>& rxCanvas) +{ + (void)rConfiguration; + + // Get base path to bitmaps. + Reference<deployment::XPackageInformationProvider> xInformationProvider ( + mxComponentContext->getValueByName(OUString(RTL_CONSTASCII_USTRINGPARAM( + "/singletons/com.sun.star.deployment.PackageInformationProvider"))), + UNO_QUERY); + OUString sLocation; + if (xInformationProvider.is()) + sLocation = xInformationProvider->getPackageLocation(gsExtensionIdentifier); + sLocation += OUString(RTL_CONSTASCII_USTRINGPARAM("/")); + + // Create the bitmap loader. + Reference<lang::XMultiComponentFactory> xFactory ( + mxComponentContext->getServiceManager(), UNO_QUERY); + if ( ! xFactory.is()) + return; + Sequence<Any> aArguments(1); + aArguments[0] <<= rxCanvas; + Reference<container::XNameAccess> xBitmapLoader( + xFactory->createInstanceWithArgumentsAndContext( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.PresenterWorkaroundService")), + aArguments, + mxComponentContext), + UNO_QUERY); + if ( ! xBitmapLoader.is()) + return; + + + // Iterate over all entries in the bitmap list and load the bitmaps. + Reference<container::XNameAccess> xBitmaps ( + rxClockTheme->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("Bitmaps"))), + UNO_QUERY); + ::std::vector<rtl::OUString> aBitmapProperties (3); + aBitmapProperties[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("FileName")); + aBitmapProperties[1] = OUString(RTL_CONSTASCII_USTRINGPARAM("XOffset")); + aBitmapProperties[2] = OUString(RTL_CONSTASCII_USTRINGPARAM("YOffset")); + PresenterConfigurationAccess::ForAll( + xBitmaps, + aBitmapProperties, + ::boost::bind(&AnalogBitmapPainter::LoadBitmap, + this, + _1, + _2, + sLocation, + xBitmapLoader)); +} + + + + +void AnalogBitmapPainter::LoadBitmap ( + const OUString& rsKey, + const ::std::vector<Any>& rValues, + const OUString& rsBitmapPath, + const Reference<container::XNameAccess>& rxBitmapLoader) +{ + if (rValues.size() == 3) + { + BitmapDescriptor* pDescriptor = NULL; + if (rsKey == OUString(RTL_CONSTASCII_USTRINGPARAM("Face"))) + pDescriptor = &maFace; + else if (rsKey == OUString(RTL_CONSTASCII_USTRINGPARAM("HourHand"))) + pDescriptor = &maHourHand; + else if (rsKey == OUString(RTL_CONSTASCII_USTRINGPARAM("MinuteHand"))) + pDescriptor = &maMinuteHand; + + if (pDescriptor == NULL) + return; + + OUString sFileName; + if ( ! (rValues[0] >>= sFileName)) + return; + + rValues[1] >>= pDescriptor->maOffset.X; + rValues[2] >>= pDescriptor->maOffset.Y; + + pDescriptor->mxBitmap = Reference<rendering::XBitmap>( + rxBitmapLoader->getByName(rsBitmapPath+sFileName), UNO_QUERY); + + if ( ! pDescriptor->mxBitmap.is()) + mbThemeLoadingFailed = true; + } +} + + + + +void AnalogBitmapPainter::ScaleBitmaps (void) +{ + if (mbThemeLoadingFailed) + return; + if ( ! maFace.mxBitmap.is()) + return; + + const geometry::IntegerSize2D aFaceSize (maFace.mxBitmap->getSize()); + const sal_Int32 nSize = std::max(aFaceSize.Width, aFaceSize.Height); + const double nScale = mnOuterRadius*2 / nSize; + + BitmapDescriptor* aDescriptors[3] = { &maFace, &maHourHand, &maMinuteHand }; + for (int nIndex=0; nIndex<3; ++nIndex) + { + BitmapDescriptor& rDescriptor (*aDescriptors[nIndex]); + if ( ! rDescriptor.mxScaledBitmap.is() && rDescriptor.mxBitmap.is()) + { + const geometry::IntegerSize2D aBitmapSize (rDescriptor.mxBitmap->getSize()); + rDescriptor.mxScaledBitmap = rDescriptor.mxBitmap->getScaledBitmap( + geometry::RealSize2D(aBitmapSize.Width*nScale, aBitmapSize.Height*nScale), + sal_False); + rDescriptor.maScaledOffset = geometry::RealPoint2D( + rDescriptor.maOffset.X * nScale, + rDescriptor.maOffset.Y * nScale); + } + } +} + + + + +//===== DigitalDefaultPainter ================================================= + +DigitalDefaultPainter::DigitalDefaultPainter ( + const ::rtl::Reference<PresenterController>& rpPresenterController, + const Reference<XResourceId>& rxViewId) + : mpPresenterController(rpPresenterController), + mbIs24HourFormat(false), + mbIsAdaptFontSize(true), + mxFont(), + maWindowSize(0,0), + msViewURL(rxViewId.is() ? rxViewId->getResourceURL() : OUString()) +{ +} + + + + +DigitalDefaultPainter::~DigitalDefaultPainter (void) +{ +} + + + + +void DigitalDefaultPainter::Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState, + const rendering::RenderState& rRenderState, + const util::Color& rBackgroundColor, + const sal_Int32 nHour, + const sal_Int32 nMinute, + const sal_Int32 nSecond, + const bool bIsShowSeconds) +{ + (void)rBackgroundColor; + (void)rRenderState; + + if ( ! mxFont.is()) + CreateFont(rxCanvas,bIsShowSeconds); + if ( ! mxFont.is()) + return; + + OUString sText; + + if (mbIs24HourFormat) + sText = OUString::valueOf(nHour); + else + { + sText = OUString::valueOf(nHour>12 ? nHour-12 : nHour); + } + sText += OUString(RTL_CONSTASCII_USTRINGPARAM(":")); + const OUString sMinutes (OUString::valueOf(nMinute)); + switch (sMinutes.getLength()) + { + case 1 : + sText += OUString(RTL_CONSTASCII_USTRINGPARAM("0")) + sMinutes; + break; + case 2: + sText += sMinutes; + break; + + default: + return; + } + if (bIsShowSeconds) + { + sText += OUString(RTL_CONSTASCII_USTRINGPARAM(":")); + const OUString sSeconds (OUString::valueOf(nSecond)); + switch (sSeconds.getLength()) + { + case 1 : + sText += OUString(RTL_CONSTASCII_USTRINGPARAM("0")) + sSeconds; + break; + case 2: + sText += sSeconds; + break; + + default: + return; + } + } + + rendering::StringContext aContext ( + sText, + 0, + sText.getLength()); + Reference<rendering::XTextLayout> xLayout (mxFont->createTextLayout( + aContext, + rendering::TextDirection::WEAK_LEFT_TO_RIGHT, + 0)); + if ( ! xLayout.is()) + return; + geometry::RealRectangle2D aBox (xLayout->queryTextBounds()); + + + rendering::RenderState aRenderState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + + util::Color aFontColor (mpPresenterController->GetViewFontColor(msViewURL)); + PresenterCanvasHelper::SetDeviceColor(aRenderState, aFontColor); + aRenderState.AffineTransform.m02 + = (maWindowSize.Width - (aBox.X2-aBox.X1+1)) / 2 - aBox.X1; + aRenderState.AffineTransform.m12 + = (maWindowSize.Height - (aBox.Y2-aBox.Y1+1)) / 2 - aBox.Y1; + rxCanvas->drawText( + aContext, + mxFont, + rViewState, + aRenderState, + rendering::TextDirection::WEAK_LEFT_TO_RIGHT); +} + + + + +void DigitalDefaultPainter::Resize (const awt::Size& rSize) +{ + if (maWindowSize.Width != rSize.Width || maWindowSize.Height != rSize.Height) + { + maWindowSize = rSize; + if (mbIsAdaptFontSize) + mxFont = NULL; + } +} + + + + +void DigitalDefaultPainter::CreateFont ( + const Reference<rendering::XCanvas>& rxCanvas, + const bool bIsShowSeconds) +{ + if (rxCanvas.is() + && rxCanvas->getDevice().is() + && maWindowSize.Width>0 + && maWindowSize.Height>0) + { + // Create a time template for determinging the right font size. + // Assume that 0 is the widest digit or that all digits have the + // same width. + OUString sTimeTemplate; + // For the case that not all digits have the same width, create + // different templates for 12 and 24 hour mode. + if (mbIs24HourFormat) + sTimeTemplate = OUString(RTL_CONSTASCII_USTRINGPARAM("20")); + else + sTimeTemplate = OUString(RTL_CONSTASCII_USTRINGPARAM("10")); + if (bIsShowSeconds) + sTimeTemplate += OUString(RTL_CONSTASCII_USTRINGPARAM(":00:00")); + else + sTimeTemplate += OUString(RTL_CONSTASCII_USTRINGPARAM(":00")); + + rendering::StringContext aContext ( + sTimeTemplate, + 0, + sTimeTemplate.getLength()); + + // When the font size is adapted to the window size (as large as + // possible without overlapping) then that is done in a four step + // process: + // 1. Create a font in a default size, e.g. 10pt. + // 2. Determine a scale factor from enlarging the text bounding box + // to maximal size inside the window. + // 3. Create a new font by scaling the default size with the factor + // calculated in step 2. + // 4. Text may be rendered differently in different sizes. + // Therefore repeat step 2 and 3 once. More iterations may lead to + // even better results but probably not to visible differences. + rendering::FontRequest aFontRequest (mpPresenterController->GetViewFontRequest(msViewURL)); + // TODO: use font from view style from configuration + aFontRequest.CellSize = 10; + + for (sal_Int32 nLoop=0; nLoop<3; ++nLoop) + { + mxFont = rxCanvas->createFont( + aFontRequest, + Sequence<beans::PropertyValue>(), + geometry::Matrix2D(1,0,0,1)); + if (mxFont.is()) + { + Reference<rendering::XTextLayout> xLayout (mxFont->createTextLayout( + aContext, + rendering::TextDirection::WEAK_LEFT_TO_RIGHT, + 0)); + + if ( ! xLayout.is()) + break; + + geometry::RealRectangle2D aBox (xLayout->queryTextBounds()); + if (aBox.X2<=aBox.X1 || aBox.Y2<=aBox.Y1) + break; + const double nHorizontalFactor = maWindowSize.Width / (aBox.X2-aBox.X1+1); + const double nVerticalFactor = maWindowSize.Height / (aBox.Y2-aBox.Y1+1); + aFontRequest.CellSize *= ::std::min(nHorizontalFactor,nVerticalFactor); + } + } + } +} + + +} // end of anonymous namespace + + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterClock.hxx b/sdext/source/presenter/PresenterClock.hxx new file mode 100644 index 000000000000..352663309b75 --- /dev/null +++ b/sdext/source/presenter/PresenterClock.hxx @@ -0,0 +1,202 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_CLOCK_HXX +#define SDEXT_PRESENTER_CLOCK_HXX + +#include "PresenterController.hxx" + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase4.hxx> +#include <com/sun/star/awt/XMouseListener.hpp> +#include <com/sun/star/awt/XPaintListener.hpp> +#include <com/sun/star/awt/XWindowListener.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/drawing/framework/XResourceId.hpp> +#include <com/sun/star/drawing/framework/XView.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/rendering/XCanvas.hpp> +#include <com/sun/star/rendering/XPolyPolygon2D.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <osl/thread.hxx> +#include <rtl/ref.hxx> +#include <boost/scoped_ptr.hpp> + +namespace css = ::com::sun::star; + +namespace { + typedef cppu::WeakComponentImplHelper4< + css::awt::XPaintListener, + css::awt::XWindowListener, + css::awt::XMouseListener, + css::drawing::framework::XView + > PresenterClockInterfaceBase; +} + +namespace sdext { namespace presenter { + + +/** A clock that displays the current time. This class is work in + progress. Future extensions may include + other times like time since presentation started or remaining time. + Painting of the clock is done by the inner Painer class which includes + at the moment a simple analog and a simple digital clock. +*/ +class PresenterClock + : private ::cppu::BaseMutex, + public PresenterClockInterfaceBase +{ +public: + static ::rtl::Reference<PresenterClock> Create ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId, + const css::uno::Reference<css::frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController); + + virtual void SAL_CALL disposing (void); + + /** Callback for an external timer or thread that initiates updates when + the time changes (seconds or minutes). + */ + void UpdateTime (void); + + /** An internally used base class for different painters. + */ + class Painter; + + + // lang::XEventListener + + virtual void SAL_CALL + disposing (const css::lang::EventObject& rEventObject) + throw (css::uno::RuntimeException); + + + // XPaintListener + + virtual void SAL_CALL windowPaint (const css::awt::PaintEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XWindowListener + + virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // XMouseListener + + virtual void SAL_CALL mousePressed (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseReleased (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseEntered (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseExited (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XResourceId + + virtual css::uno::Reference<css::drawing::framework::XResourceId> SAL_CALL getResourceId (void) + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isAnchorOnly (void) + throw (com::sun::star::uno::RuntimeException); + +private: + css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + css::uno::Reference<css::drawing::framework::XResourceId> mxViewId; + css::uno::Reference<css::awt::XWindow> mxWindow; + css::uno::Reference<css::rendering::XCanvas> mxCanvas; + css::uno::Reference<css::drawing::framework::XPane> mxPane; + ::rtl::Reference<PresenterController> mpPresenterController; + bool mbIsResizePending; + css::rendering::ViewState maViewState; + css::rendering::RenderState maRenderState; + /** A Timer is used for sampling the current time and schedule repaints + when the minute or second (when these are displayed) values have changed. + */ + class Timer; + Timer* mpTimer; + ::boost::scoped_ptr<Painter> mpClockPainter; + /** + This is used for debugging to show one clock atop another to compare + the output of the painters. + */ + ::boost::scoped_ptr<Painter> mpClockPainter2; + int mnMode; + sal_Int32 mnHour; + sal_Int32 mnMinute; + sal_Int32 mnSecond; + + bool mbIsShowSeconds; + + /** Use the static Create() method for creating a new PresenterClock + object. + */ + PresenterClock ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId, + const css::uno::Reference<css::frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~PresenterClock (void); + + void LateInit (void); + void Resize (void); + void Paint (const css::awt::Rectangle& rUpdateRectangle); + css::uno::Reference<css::rendering::XPolyPolygon2D> CreatePolygon ( + const css::awt::Rectangle& rBox); + void Clear (const css::uno::Reference<css::rendering::XPolyPolygon2D>& rxUpdatePolygon); + void SetMode (sal_Int32 nMode); + + /** This method throws a DisposedException when the object has already been + disposed. + */ + void ThrowIfDisposed (void) + throw (css::lang::DisposedException); +}; + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterComponent.cxx b/sdext/source/presenter/PresenterComponent.cxx new file mode 100644 index 000000000000..d59a5b5dd0b4 --- /dev/null +++ b/sdext/source/presenter/PresenterComponent.cxx @@ -0,0 +1,141 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterComponent.hxx" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implementationentry.hxx" +#include <com/sun/star/deployment/DeploymentException.hpp> +#include <com/sun/star/deployment/XPackageInformationProvider.hpp> + +#include "PresenterExtensionIdentifier.hxx" +#include "PresenterProtocolHandler.hxx" +#include "PresenterScreen.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace cppu; +using namespace osl; +using ::rtl::OUString; + + + +namespace sdext { namespace presenter { + +static OUString gsBasePath; + +::rtl::OUString PresenterComponent::GetBasePath ( + const Reference<XComponentContext>& rxComponentContext) +{ + return GetBasePath(rxComponentContext, gsExtensionIdentifier); +} + + + + +::rtl::OUString PresenterComponent::GetBasePath ( + const Reference<XComponentContext>& rxComponentContext, + const OUString& rsExtensionIdentifier) +{ + if (gsBasePath.getLength() == 0) + { + // Determine the base path of the bitmaps. + Reference<deployment::XPackageInformationProvider> xInformationProvider ( + rxComponentContext->getValueByName( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "/singletons/com.sun.star.deployment.PackageInformationProvider"))), + UNO_QUERY); + if (xInformationProvider.is()) + { + try + { + gsBasePath = xInformationProvider->getPackageLocation(rsExtensionIdentifier) + + OUString(RTL_CONSTASCII_USTRINGPARAM("/")); + } + catch(deployment::DeploymentException&) + { + } + } + } + + return gsBasePath; +} + + + +rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; + +static struct ImplementationEntry gServiceEntries[] = +{ + { + PresenterProtocolHandler::Create, + PresenterProtocolHandler::getImplementationName_static, + PresenterProtocolHandler::getSupportedServiceNames_static, + createSingleComponentFactory, &g_moduleCount.modCnt, 0 + }, + { + PresenterScreenJob::Create, + PresenterScreenJob::getImplementationName_static, + PresenterScreenJob::getSupportedServiceNames_static, + createSingleComponentFactory, 0, 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + + + + +extern "C" +{ + sal_Bool SAL_CALL component_canUnload( TimeValue *pTime ) + { + return g_moduleCount.canUnload( &g_moduleCount , pTime ); + } + + sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey ) + { + return component_writeInfoHelper(pServiceManager, pRegistryKey, gServiceEntries); + } + + + + + SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) + { + return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , gServiceEntries); + } + +} + +} } // end of namespace sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterComponent.hxx b/sdext/source/presenter/PresenterComponent.hxx new file mode 100644 index 000000000000..4334d53f081d --- /dev/null +++ b/sdext/source/presenter/PresenterComponent.hxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_COMPONENT_HXX +#define SDEXT_PRESENTER_COMPONENT_HXX + +#include <com/sun/star/uno/XComponentContext.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +/** This string is replaced automatically by the makefile during the + building of this extension. +*/ +class PresenterComponent +{ +public: + const static ::rtl::OUString gsExtensionIdentifier; + + static ::rtl::OUString GetBasePath ( + const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext); + static ::rtl::OUString GetBasePath ( + const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext, + const ::rtl::OUString& rsExtensionIdentifier); +}; + + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterConfigurationAccess.cxx b/sdext/source/presenter/PresenterConfigurationAccess.cxx new file mode 100644 index 000000000000..acba65b233a9 --- /dev/null +++ b/sdext/source/presenter/PresenterConfigurationAccess.cxx @@ -0,0 +1,412 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterConfigurationAccess.hxx" + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> + +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 ::rtl::OUString PresenterConfigurationAccess::msPresenterScreenRootName = + A2S("/org.openoffice.Office.extension.PresenterScreen/"); + +PresenterConfigurationAccess::PresenterConfigurationAccess ( + const Reference<XComponentContext>& rxContext, + const OUString& rsRootName, + WriteMode eMode) + : mxRoot(), + maNode() +{ + try + { + Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager()); + if (xFactory.is()) + { + Sequence<Any> aCreationArguments(3); + aCreationArguments[0] = makeAny(beans::PropertyValue( + A2S("nodepath"), + 0, + makeAny(rsRootName), + beans::PropertyState_DIRECT_VALUE)); + aCreationArguments[1] = makeAny(beans::PropertyValue( + A2S("depth"), + 0, + makeAny((sal_Int32)-1), + beans::PropertyState_DIRECT_VALUE)); + aCreationArguments[2] = makeAny(beans::PropertyValue( + A2S("lazywrite"), + 0, + makeAny(true), + beans::PropertyState_DIRECT_VALUE)); + + OUString sAccessService; + if (eMode == READ_ONLY) + sAccessService = A2S("com.sun.star.configuration.ConfigurationAccess"); + else + sAccessService = A2S("com.sun.star.configuration.ConfigurationUpdateAccess"); + + Reference<lang::XMultiServiceFactory> xProvider ( + xFactory->createInstanceWithContext( + A2S("com.sun.star.configuration.ConfigurationProvider"), + rxContext), + UNO_QUERY_THROW); + mxRoot = xProvider->createInstanceWithArguments( + sAccessService, aCreationArguments); + maNode <<= mxRoot; + } + } + catch (Exception& rException) + { + OSL_TRACE ("caught exception while opening configuration: %s", + ::rtl::OUStringToOString(rException.Message, + RTL_TEXTENCODING_UTF8).getStr()); + } +} + + + + +PresenterConfigurationAccess::~PresenterConfigurationAccess (void) +{ +} + + + + +bool PresenterConfigurationAccess::IsValid (void) const +{ + return mxRoot.is(); +} + + + + +Any PresenterConfigurationAccess::GetConfigurationNode (const OUString& sPathToNode) +{ + return GetConfigurationNode( + Reference<container::XHierarchicalNameAccess>(mxRoot, UNO_QUERY), + sPathToNode); +} + + + + +Reference<beans::XPropertySet> PresenterConfigurationAccess::GetNodeProperties ( + const OUString& sPathToNode) +{ + return GetNodeProperties( + Reference<container::XHierarchicalNameAccess>(mxRoot, UNO_QUERY), + sPathToNode); +} + + + + +bool PresenterConfigurationAccess::GoToChild (const ::rtl::OUString& rsPathToNode) +{ + if ( ! IsValid()) + return false; + + Reference<container::XHierarchicalNameAccess> xNode (maNode, UNO_QUERY); + if (xNode.is()) + { + maNode = GetConfigurationNode( + Reference<container::XHierarchicalNameAccess>(maNode, UNO_QUERY), + rsPathToNode); + if (Reference<XInterface>(maNode, UNO_QUERY).is()) + return true; + } + + mxRoot = NULL; + return false; +} + + + + +bool PresenterConfigurationAccess::GoToChild (const Predicate& rPredicate) +{ + if ( ! IsValid()) + return false; + + maNode = Find(Reference<container::XNameAccess>(maNode,UNO_QUERY), rPredicate); + if (Reference<XInterface>(maNode, UNO_QUERY).is()) + return true; + + mxRoot = NULL; + return false; +} + + + + +bool PresenterConfigurationAccess::SetProperty ( + const ::rtl::OUString& rsPropertyName, + const Any& rValue) +{ + Reference<beans::XPropertySet> xProperties (maNode, UNO_QUERY); + if (xProperties.is()) + { + xProperties->setPropertyValue(rsPropertyName, rValue); + return true; + } + else + return false; +} + + + + +Any PresenterConfigurationAccess::GetConfigurationNode ( + const css::uno::Reference<css::container::XHierarchicalNameAccess>& rxNode, + const OUString& sPathToNode) +{ + if (sPathToNode.getLength() == 0) + return Any(rxNode); + + try + { + if (rxNode.is()) + { + return rxNode->getByHierarchicalName(sPathToNode); + } + } + catch (Exception& rException) + { + OSL_TRACE ("caught exception while getting configuration node %s: %s", + ::rtl::OUStringToOString(sPathToNode, RTL_TEXTENCODING_UTF8).getStr(), + ::rtl::OUStringToOString(rException.Message, RTL_TEXTENCODING_UTF8).getStr()); + } + + return Any(); +} + + + + +Reference<beans::XPropertySet> PresenterConfigurationAccess::GetNodeProperties ( + const css::uno::Reference<css::container::XHierarchicalNameAccess>& rxNode, + const ::rtl::OUString& rsPathToNode) +{ + return Reference<beans::XPropertySet>(GetConfigurationNode(rxNode, rsPathToNode), UNO_QUERY); +} + + + + +void PresenterConfigurationAccess::CommitChanges (void) +{ + Reference<util::XChangesBatch> xConfiguration (mxRoot, UNO_QUERY); + if (xConfiguration.is()) + xConfiguration->commitChanges(); +} + + + + +Any PresenterConfigurationAccess::GetValue (const rtl::OUString& sKey) +{ + Reference<container::XNameAccess> xAccess (GetConfigurationNode(sKey), UNO_QUERY); + if (xAccess.is()) + { + return xAccess->getByName(sKey); + } + else + { + return Any(); + } +} + + + + +void PresenterConfigurationAccess::ForAll ( + const Reference<container::XNameAccess>& rxContainer, + const ::std::vector<OUString>& rArguments, + const ItemProcessor& rProcessor) +{ + if (rxContainer.is()) + { + ::std::vector<Any> aValues(rArguments.size()); + Sequence<OUString> aKeys (rxContainer->getElementNames()); + for (sal_Int32 nItemIndex=0; nItemIndex<aKeys.getLength(); ++nItemIndex) + { + bool bHasAllValues (true); + const OUString& rsKey (aKeys[nItemIndex]); + Reference<container::XNameAccess> xSetItem (rxContainer->getByName(rsKey), UNO_QUERY); + Reference<beans::XPropertySet> xSet (xSetItem, UNO_QUERY); + OSL_ASSERT(xSet.is()); + if (xSetItem.is()) + { + // Get from the current item of the container the children + // that match the names in the rArguments list. + for (sal_uInt32 nValueIndex=0; nValueIndex<aValues.size(); ++nValueIndex) + { + if ( ! xSetItem->hasByName(rArguments[nValueIndex])) + bHasAllValues = false; + else + aValues[nValueIndex] = xSetItem->getByName(rArguments[nValueIndex]); + } + } + else + bHasAllValues = false; + if (bHasAllValues) + rProcessor(rsKey,aValues); + } + } +} + + + + +void PresenterConfigurationAccess::ForAll ( + const Reference<container::XNameAccess>& rxContainer, + const PropertySetProcessor& rProcessor) +{ + if (rxContainer.is()) + { + Sequence<OUString> aKeys (rxContainer->getElementNames()); + for (sal_Int32 nItemIndex=0; nItemIndex<aKeys.getLength(); ++nItemIndex) + { + const OUString& rsKey (aKeys[nItemIndex]); + Reference<beans::XPropertySet> xSet (rxContainer->getByName(rsKey), UNO_QUERY); + if (xSet.is()) + rProcessor(rsKey, xSet); + } + } +} + + + + +void PresenterConfigurationAccess::FillList( + const Reference<container::XNameAccess>& rxContainer, + const ::rtl::OUString& rsArgument, + ::std::vector<OUString>& rList) +{ + try + { + if (rxContainer.is()) + { + Sequence<OUString> aKeys (rxContainer->getElementNames()); + rList.resize(aKeys.getLength()); + for (sal_Int32 nItemIndex=0; nItemIndex<aKeys.getLength(); ++nItemIndex) + { + Reference<container::XNameAccess> xSetItem ( + rxContainer->getByName(aKeys[nItemIndex]), UNO_QUERY); + if (xSetItem.is()) + { + xSetItem->getByName(rsArgument) >>= rList[nItemIndex]; + } + } + } + } + catch (RuntimeException&) + {} +} + + + + +Any PresenterConfigurationAccess::Find ( + const Reference<container::XNameAccess>& rxContainer, + const Predicate& rPredicate) +{ + if (rxContainer.is()) + { + Sequence<OUString> aKeys (rxContainer->getElementNames()); + for (sal_Int32 nItemIndex=0; nItemIndex<aKeys.getLength(); ++nItemIndex) + { + Reference<beans::XPropertySet> xProperties ( + rxContainer->getByName(aKeys[nItemIndex]), + UNO_QUERY); + if (xProperties.is()) + if (rPredicate(aKeys[nItemIndex], xProperties)) + return Any(xProperties); + } + } + return Any(); +} + + + + +bool PresenterConfigurationAccess::IsStringPropertyEqual ( + const ::rtl::OUString& rsValue, + const ::rtl::OUString& rsPropertyName, + const css::uno::Reference<css::beans::XPropertySet>& rxNode) +{ + OUString sValue; + if (GetProperty(rxNode, rsPropertyName) >>= sValue) + return sValue == rsValue; + else + return false; +} + + + + +Any PresenterConfigurationAccess::GetProperty ( + const Reference<beans::XPropertySet>& rxProperties, + const OUString& rsKey) +{ + OSL_ASSERT(rxProperties.is()); + if ( ! rxProperties.is()) + return Any(); + try + { + Reference<beans::XPropertySetInfo> xInfo (rxProperties->getPropertySetInfo()); + if (xInfo.is()) + if ( ! xInfo->hasPropertyByName(rsKey)) + return Any(); + return rxProperties->getPropertyValue(rsKey); + } + catch (beans::UnknownPropertyException&) + { + } + return Any(); +} + + + + +} } // end of namespace sdext::tools + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterConfigurationAccess.hxx b/sdext/source/presenter/PresenterConfigurationAccess.hxx new file mode 100644 index 000000000000..81f1130e696b --- /dev/null +++ b/sdext/source/presenter/PresenterConfigurationAccess.hxx @@ -0,0 +1,208 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_CONFIGURATION_ACCESS_HXX +#define SDEXT_PRESENTER_CONFIGURATION_ACCESS_HXX + +#include <rtl/ustring.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <vector> +#include <boost/function.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +/** This class gives access to the configuration. Create an object of this + class for one node of the configuration. This will be the root node. + From this one you can use this class in two ways. + + <p>In a stateless mode (with exception of the root node) you can use static + methods for obtaining child nodes, get values from properties at leaf + nodes and iterate over children of inner nodes.</p> + + <p>In a stateful mode use non-static methods like GoToChild() to + navigate to children.</p> + + <p>Note to call CommitChanges() after making changes to + PresenterConfigurationAccess object that was opened in READ_WRITE mode.</p> +*/ +class PresenterConfigurationAccess +{ +public: + enum WriteMode { READ_WRITE, READ_ONLY }; + typedef ::boost::function<bool( + const ::rtl::OUString&, + const css::uno::Reference<css::beans::XPropertySet>&)> Predicate; + static const ::rtl::OUString msPresenterScreenRootName; + + /** Create a new object to access the configuration entries below the + given root. + @param rsRootName + Name of the root. You can use msPresenterScreenRootName to + access the configuration of the presenter screen. + @param eMode + This flag specifies whether to give read-write or read-only + access. + */ + PresenterConfigurationAccess( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const ::rtl::OUString& rsRootName, + WriteMode eMode); + + ~PresenterConfigurationAccess (void); + + /** Return a configuration node below the root of the called object. + @param rsPathToNode + The relative path from the root (as given the constructor) to the node. + */ + css::uno::Any GetConfigurationNode ( + const ::rtl::OUString& rsPathToNode); + css::uno::Reference<css::beans::XPropertySet> GetNodeProperties ( + const ::rtl::OUString& rsPathToNode); + + /** Return <TRUE/> when opening the configuration (via creating a new + PresenterConfigurationAccess object) or previous calls to + GoToChild() left the called PresenterConfigurationAccess object in a + valid state. + */ + bool IsValid (void) const; + + /** Move the focused node to the (possibly indirect) child specified by the given path. + */ + bool GoToChild (const ::rtl::OUString& rsPathToNode); + + /** Move the focused node to the first direct child that fulfills the the given predicate. + */ + bool GoToChild (const Predicate& rPredicate); + + /** Modify the property child of the currently focused node. Keep in + mind to call CommitChanges() to write the change back to the + configuration. + */ + bool SetProperty (const ::rtl::OUString& rsPropertyName, const css::uno::Any& rValue); + + /** Return a configuration node below the given node. + @param rxNode + The node that acts as root to the given relative path. + @param rsPathToNode + The relative path from the given node to the requested node. + When this string is empty then rxNode is returned. + @return + The type of the returned node varies with the requested node. + It is empty when the node was not found. + */ + static css::uno::Any GetConfigurationNode ( + const css::uno::Reference<css::container::XHierarchicalNameAccess>& rxNode, + const ::rtl::OUString& rsPathToNode); + + static css::uno::Reference<css::beans::XPropertySet> GetNodeProperties ( + const css::uno::Reference<css::container::XHierarchicalNameAccess>& rxNode, + const ::rtl::OUString& rsPathToNode); + + /** Write any changes that have been made back to the configuration. + This call is ignored when the called ConfigurationAccess object was + not create with read-write mode. + */ + void CommitChanges (void); + + css::uno::Any GetValue (const rtl::OUString& sKey); + + typedef ::boost::function<void( + const ::rtl::OUString&, + const ::std::vector<css::uno::Any>&) > ItemProcessor; + typedef ::boost::function<void( + const ::rtl::OUString&, + const ::css::uno::Reference<css::beans::XPropertySet>&) > PropertySetProcessor; + + /** Execute a functor for all elements of the given container. + @param rxContainer + The container is a XNameAccess to a list of the configuration. + This can be a node returned by GetConfigurationNode(). + @param rArguments + The functor is called with arguments that are children of each + element of the container. The set of children is specified this + list. + @param rFunctor + The functor to be executed for some or all of the elements in + the given container. + */ + static void ForAll ( + const css::uno::Reference<css::container::XNameAccess>& rxContainer, + const ::std::vector<rtl::OUString>& rArguments, + const ItemProcessor& rProcessor); + static void ForAll ( + const css::uno::Reference<css::container::XNameAccess>& rxContainer, + const PropertySetProcessor& rProcessor); + + /** Fill a list with the string contents of all sub-elements in the given container. + @param rxContainer + The container is a XNameAccess to a list of the configuration. + This can be a node returned by GetConfigurationNode(). + @param rsArgument + This specifies which string children of the elements in the + container are to be inserted into the list. The specified child + has to be of type string. + @param rList + The list to be filled. + */ + static void FillList( + const css::uno::Reference<css::container::XNameAccess>& rxContainer, + const ::rtl::OUString& rsArgument, + ::std::vector<rtl::OUString>& rList); + + static css::uno::Any Find ( + const css::uno::Reference<css::container::XNameAccess>& rxContainer, + const Predicate& rPredicate); + + static bool IsStringPropertyEqual ( + const ::rtl::OUString& rsValue, + const ::rtl::OUString& rsPropertyName, + const css::uno::Reference<css::beans::XPropertySet>& rxNode); + + /** This method wraps a call to getPropertyValue() and returns an empty + Any instead of throwing an exception when the property does not + exist. + */ + static css::uno::Any GetProperty ( + const css::uno::Reference<css::beans::XPropertySet>& rxProperties, + const ::rtl::OUString& rsKey); + +private: + css::uno::Reference<css::uno::XInterface> mxRoot; + css::uno::Any maNode; +}; + +} } // end of namespace sdext::tools + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterController.cxx b/sdext/source/presenter/PresenterController.cxx new file mode 100644 index 000000000000..d37f0d966db8 --- /dev/null +++ b/sdext/source/presenter/PresenterController.cxx @@ -0,0 +1,1380 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterController.hxx" + +#include "PresenterAccessibility.hxx" +#include "PresenterAnimator.hxx" +#include "PresenterCanvasHelper.hxx" +#include "PresenterCurrentSlideObserver.hxx" +#include "PresenterFrameworkObserver.hxx" +#include "PresenterHelper.hxx" +#include "PresenterNotesView.hxx" +#include "PresenterPaintManager.hxx" +#include "PresenterPaneAnimator.hxx" +#include "PresenterPaneBase.hxx" +#include "PresenterPaneContainer.hxx" +#include "PresenterPaneBorderPainter.hxx" +#include "PresenterTheme.hxx" +#include "PresenterViewFactory.hxx" +#include "PresenterWindowManager.hxx" + +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/awt/Key.hpp> +#include <com/sun/star/awt/KeyModifier.hpp> +#include <com/sun/star/awt/MouseButton.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/drawing/XDrawView.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/framework/ResourceActivationMode.hpp> +#include <com/sun/star/drawing/framework/ResourceId.hpp> +#include <com/sun/star/drawing/framework/XControllerManager.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/presentation/XPresentation.hpp> +#include <com/sun/star/presentation/XPresentationSupplier.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/TextDirection.hpp> + +#include <rtl/ustrbuf.hxx> +#include <boost/bind.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +namespace { + const sal_Int32 ResourceActivationEventType = 0; + const sal_Int32 ResourceDeactivationEventType = 1; + const sal_Int32 ConfigurationUpdateEndEventType = 2; +} + + +#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) + + +namespace sdext { namespace presenter { + +PresenterController::InstanceContainer PresenterController::maInstances; + +::rtl::Reference<PresenterController> PresenterController::Instance ( + const css::uno::Reference<css::frame::XFrame>& rxFrame) +{ + InstanceContainer::const_iterator iInstance (maInstances.find(rxFrame)); + if (iInstance != maInstances.end()) + return iInstance->second; + else + return ::rtl::Reference<PresenterController>(); +} + + + + +PresenterController::PresenterController ( + const Reference<XComponentContext>& rxContext, + const Reference<frame::XController>& rxController, + const Reference<presentation::XSlideShowController>& rxSlideShowController, + const rtl::Reference<PresenterPaneContainer>& rpPaneContainer, + const Reference<XResourceId>& rxMainPaneId) + : PresenterControllerInterfaceBase(m_aMutex), + mxComponentContext(rxContext), + mxController(rxController), + mxConfigurationController(), + mxSlideShowController(rxSlideShowController), + mxMainPaneId(rxMainPaneId), + mpPaneContainer(rpPaneContainer), + mnCurrentSlideIndex(-1), + mxCurrentSlide(), + mxNextSlide(), + mpWindowManager(new PresenterWindowManager(rxContext,mpPaneContainer,this)), + mpCurrentPaneAnimation(), + mnWindowBackgroundColor(0x00ffffff), + mpTheme(), + mxMainWindow(), + mpPaneBorderPainter(), + mpAnimator(new PresenterAnimator()), + mpCanvasHelper(new PresenterCanvasHelper()), + mxPresenterHelper(), + mpPaintManager(), + mnPendingSlideNumber(-1), + mxUrlTransformer(), + mpAccessibleObject(), + mbIsAccessibilityActive(false) +{ + OSL_ASSERT(mxController.is()); + + if ( ! mxSlideShowController.is()) + throw new lang::IllegalArgumentException( + A2S("missing slide show controller"), + static_cast<XWeak*>(this), + 2); + + new PresenterCurrentSlideObserver(this,rxSlideShowController); + + // Listen for configuration changes. + Reference<XControllerManager> xCM (mxController, UNO_QUERY_THROW); + mxConfigurationController = xCM->getConfigurationController(); + if (mxConfigurationController.is()) + { + mxConfigurationController->addConfigurationChangeListener( + this, + A2S("ResourceActivation"), + Any(ResourceActivationEventType)); + mxConfigurationController->addConfigurationChangeListener( + this, + A2S("ResourceDeactivation"), + Any(ResourceDeactivationEventType)); + mxConfigurationController->addConfigurationChangeListener( + this, + A2S("ConfigurationUpdateEnd"), + Any(ConfigurationUpdateEndEventType)); + } + + // Listen for the frame being activated. + Reference<frame::XFrame> xFrame (mxController->getFrame()); + if (xFrame.is()) + xFrame->addFrameActionListener(this); + + // Create the border painter. + mpPaneBorderPainter = new PresenterPaneBorderPainter(rxContext); + mpWindowManager->SetPaneBorderPainter(mpPaneBorderPainter); + + // Create an object that is able to load the bitmaps in a format that is + // supported by the canvas. + Reference<lang::XMultiComponentFactory> xFactory ( + rxContext->getServiceManager(), UNO_QUERY); + if ( ! xFactory.is()) + return; + mxPresenterHelper = Reference<drawing::XPresenterHelper>( + xFactory->createInstanceWithContext( + A2S("com.sun.star.drawing.PresenterHelper"), + rxContext), + UNO_QUERY_THROW); + + if (mxSlideShowController.is()) + { + mxSlideShowController->activate(); + Reference<beans::XPropertySet> xProperties (mxSlideShowController, UNO_QUERY); + if (xProperties.is()) + { + Reference<awt::XWindow> xWindow ( + xProperties->getPropertyValue(A2S("ParentWindow")), UNO_QUERY); + if (xWindow.is()) + xWindow->addKeyListener(this); + } + } + + UpdateCurrentSlide(0); + + maInstances[mxController->getFrame()] = this; + + // Create a URLTransformer. + if (xFactory.is()) + { + mxUrlTransformer = Reference<util::XURLTransformer>( + xFactory->createInstanceWithContext( + A2S("com.sun.star.util.URLTransformer"), + mxComponentContext), + UNO_QUERY); + } +} + + + + +PresenterController::~PresenterController (void) +{ +} + + + + +void PresenterController::disposing (void) +{ + maInstances.erase(mxController->getFrame()); + + if (mxMainWindow.is()) + { + mxMainWindow->removeKeyListener(this); + mxMainWindow->removeFocusListener(this); + mxMainWindow->removeMouseListener(this); + mxMainWindow->removeMouseMotionListener(this); + mxMainWindow = NULL; + } + if (mxConfigurationController.is()) + mxConfigurationController->removeConfigurationChangeListener(this); + + Reference<XComponent> xWindowManagerComponent ( + static_cast<XWeak*>(mpWindowManager.get()), UNO_QUERY); + mpWindowManager = NULL; + if (xWindowManagerComponent.is()) + xWindowManagerComponent->dispose(); + + if (mxController.is()) + { + Reference<frame::XFrame> xFrame (mxController->getFrame()); + if (xFrame.is()) + xFrame->removeFrameActionListener(this); + mxController = NULL; + } + + mxComponentContext = NULL; + mxConfigurationController = NULL; + mxSlideShowController = NULL; + mxMainPaneId = NULL; + mpPaneContainer = NULL; + mnCurrentSlideIndex = -1; + mxCurrentSlide = NULL; + mxNextSlide = NULL; + mpCurrentPaneAnimation.reset(); + mpTheme.reset(); + { + Reference<lang::XComponent> xComponent ( + static_cast<XWeak*>(mpPaneBorderPainter.get()), UNO_QUERY); + mpPaneBorderPainter = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + mpAnimator.reset(); + mpCanvasHelper.reset(); + { + Reference<lang::XComponent> xComponent (mxPresenterHelper, UNO_QUERY); + mxPresenterHelper = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + mpPaintManager.reset(); + mnPendingSlideNumber = -1; + { + Reference<lang::XComponent> xComponent (mxUrlTransformer, UNO_QUERY); + mxUrlTransformer = NULL; + if (xComponent.is()) + xComponent->dispose(); + } +} + + + + +void PresenterController::UpdateCurrentSlide (const sal_Int32 nOffset) +{ + GetSlides(nOffset); + UpdatePaneTitles(); + UpdateViews(); + + // Update the accessibility object. + if (IsAccessibilityActive()) + { + sal_Int32 nSlideCount (0); + Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY); + if (xIndexAccess.is()) + nSlideCount = xIndexAccess->getCount(); + mpAccessibleObject->NotifyCurrentSlideChange(mnCurrentSlideIndex, nSlideCount); + } +} + + + + +void PresenterController::GetSlides (const sal_Int32 nOffset) +{ + if ( ! mxSlideShowController.is()) + return; + + // Get the current slide from the slide show controller. + mxCurrentSlide = NULL; + Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY); + sal_Int32 nSlideIndex = -1; + try + { + nSlideIndex = mxSlideShowController->getCurrentSlideIndex() + nOffset; + if (mxSlideShowController->isPaused()) + nSlideIndex = -1; + + if (xIndexAccess.is() && nSlideIndex>=0) + { + if (nSlideIndex < xIndexAccess->getCount()) + { + mnCurrentSlideIndex = nSlideIndex; + mxCurrentSlide = Reference<drawing::XDrawPage>( + xIndexAccess->getByIndex(nSlideIndex), UNO_QUERY); + } + } + } + catch (RuntimeException&) + { + } + + // Get the next slide. + mxNextSlide = NULL; + try + { + const sal_Int32 nNextSlideIndex (mxSlideShowController->getNextSlideIndex()+nOffset); + if (nNextSlideIndex >= 0) + { + if (xIndexAccess.is()) + { + if (nNextSlideIndex < xIndexAccess->getCount()) + mxNextSlide = Reference<drawing::XDrawPage>( + xIndexAccess->getByIndex(nNextSlideIndex), UNO_QUERY); + } + } + } + catch (RuntimeException&) + { + } +} + + + + +void PresenterController::UpdatePaneTitles (void) +{ + if ( ! mxSlideShowController.is()) + return; + + // Get placeholders and their values. + const OUString sCurrentSlideNumberPlaceholder (A2S("CURRENT_SLIDE_NUMBER")); + const OUString sCurrentSlideNamePlaceholder (A2S("CURRENT_SLIDE_NAME")); + const OUString sSlideCountPlaceholder (A2S("SLIDE_COUNT")); + + // Get string for slide count. + OUString sSlideCount (A2S("---")); + Reference<container::XIndexAccess> xIndexAccess(mxSlideShowController, UNO_QUERY); + if (xIndexAccess.is()) + sSlideCount = OUString::valueOf(xIndexAccess->getCount()); + + // Get string for current slide index. + OUString sCurrentSlideNumber (OUString::valueOf(mnCurrentSlideIndex + 1)); + + // Get name of the current slide. + OUString sCurrentSlideName; + Reference<container::XNamed> xNamedSlide (mxCurrentSlide, UNO_QUERY); + if (xNamedSlide.is()) + sCurrentSlideName = xNamedSlide->getName(); + Reference<beans::XPropertySet> xSlideProperties (mxCurrentSlide, UNO_QUERY); + if (xSlideProperties.is()) + { + try + { + OUString sName; + if (xSlideProperties->getPropertyValue(A2S("LinkDisplayName")) >>= sName) + { + // Find out whether the name of the current slide has been + // automatically created or has been set by the user. + if (sName != sCurrentSlideName) + sCurrentSlideName = sName; + } + } + catch (beans::UnknownPropertyException&) + { + } + } + + // Replace the placeholders with their current values. + PresenterPaneContainer::PaneList::const_iterator iPane; + for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane) + { + OSL_ASSERT((*iPane).get() != NULL); + + OUString sTemplate (IsAccessibilityActive() + ? (*iPane)->msAccessibleTitleTemplate + : (*iPane)->msTitleTemplate); + if (sTemplate.getLength() <= 0) + continue; + + OUStringBuffer sResult; + sResult.ensureCapacity(sTemplate.getLength()); + + sal_Int32 nIndex (0); + while (true) + { + sal_Int32 nStartIndex = sTemplate.indexOf('%', nIndex); + if (nStartIndex < 0) + { + // Add the remaining part of the string. + sResult.append(sTemplate.copy(nIndex, sTemplate.getLength()-nIndex)); + break; + } + else + { + // Add the part preceding the next %. + sResult.append(sTemplate.copy(nIndex, nStartIndex-nIndex)); + + // Get the placeholder + ++nIndex; + ++nStartIndex; + const sal_Int32 nEndIndex (sTemplate.indexOf('%', nStartIndex+1)); + const OUString sPlaceholder (sTemplate.copy(nStartIndex, nEndIndex-nStartIndex)); + nIndex = nEndIndex+1; + + // Replace the placeholder with its current value. + if (sPlaceholder == sCurrentSlideNumberPlaceholder) + sResult.append(sCurrentSlideNumber); + else if (sPlaceholder == sCurrentSlideNamePlaceholder) + sResult.append(sCurrentSlideName); + else if (sPlaceholder == sSlideCountPlaceholder) + sResult.append(sSlideCount); + } + } + + (*iPane)->msTitle = sResult.makeStringAndClear(); + if ((*iPane)->mxPane.is()) + (*iPane)->mxPane->SetTitle((*iPane)->msTitle); + } +} + + + + +void PresenterController::UpdateViews (void) +{ + // Tell all views about the slides they should display. + PresenterPaneContainer::PaneList::const_iterator iPane; + for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane) + { + Reference<drawing::XDrawView> xDrawView ((*iPane)->mxView, UNO_QUERY); + if (xDrawView.is()) + xDrawView->setCurrentPage(mxCurrentSlide); + } +} + + + + +SharedBitmapDescriptor + PresenterController::GetViewBackground (const ::rtl::OUString& rsViewURL) const +{ + if (mpTheme.get() != NULL) + { + const OUString sStyleName (mpTheme->GetStyleName(rsViewURL)); + return mpTheme->GetBitmap(sStyleName, A2S("Background")); + } + return SharedBitmapDescriptor(); +} + + + + +PresenterTheme::SharedFontDescriptor + PresenterController::GetViewFont (const ::rtl::OUString& rsViewURL) const +{ + if (mpTheme.get() != NULL) + { + const OUString sStyleName (mpTheme->GetStyleName(rsViewURL)); + return mpTheme->GetFont(sStyleName); + } + return PresenterTheme::SharedFontDescriptor(); +} + + + + +::boost::shared_ptr<PresenterTheme> PresenterController::GetTheme (void) const +{ + return mpTheme; +} + + + + +::rtl::Reference<PresenterWindowManager> PresenterController::GetWindowManager (void) const +{ + return mpWindowManager; +} + + + + +Reference<presentation::XSlideShowController> + PresenterController::GetSlideShowController(void) const +{ + return mxSlideShowController; +} + + + + +rtl::Reference<PresenterPaneContainer> PresenterController::GetPaneContainer (void) const +{ + return mpPaneContainer; +} + + + + +::rtl::Reference<PresenterPaneBorderPainter> PresenterController::GetPaneBorderPainter (void) const +{ + return mpPaneBorderPainter; +} + + + + +::boost::shared_ptr<PresenterAnimator> PresenterController::GetAnimator (void) const +{ + return mpAnimator; +} + + + + +::boost::shared_ptr<PresenterCanvasHelper> PresenterController::GetCanvasHelper (void) const +{ + return mpCanvasHelper; +} + + + + +Reference<drawing::XPresenterHelper> PresenterController::GetPresenterHelper (void) const +{ + return mxPresenterHelper; +} + + + + +::boost::shared_ptr<PresenterPaintManager> PresenterController::GetPaintManager (void) const +{ + return mpPaintManager; +} + + + + +void PresenterController::HideSlideSorter (void) +{ + if (mpCurrentPaneAnimation.get() != NULL) + { + mpCurrentPaneAnimation->HidePane(); + mpCurrentPaneAnimation.reset(); + } +} + + + + +void PresenterController::ShowView (const OUString& rsViewURL) +{ + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPaneContainer->FindViewURL(rsViewURL)); + if (pDescriptor.get() != NULL) + { + pDescriptor->mbIsActive = true; + mxConfigurationController->requestResourceActivation( + pDescriptor->mxPaneId, + ResourceActivationMode_ADD); + mxConfigurationController->requestResourceActivation( + ResourceId::createWithAnchor( + mxComponentContext, + rsViewURL, + pDescriptor->mxPaneId), + ResourceActivationMode_REPLACE); + } +} + + + + +void PresenterController::HideView (const OUString& rsViewURL) +{ + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPaneContainer->FindViewURL(rsViewURL)); + if (pDescriptor.get() != NULL) + { + mxConfigurationController->requestResourceDeactivation( + ResourceId::createWithAnchor( + mxComponentContext, + rsViewURL, + pDescriptor->mxPaneId)); + } +} + + + + +bool PresenterController::IsViewVisible (const OUString& rsViewURL) const +{ + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPaneContainer->FindViewURL(rsViewURL)); + if (pDescriptor.get() != NULL) + { + return mxConfigurationController->getResource( + ResourceId::createWithAnchor( + mxComponentContext, + rsViewURL, + pDescriptor->mxPaneId)).is(); + } + return false; +} + + + + +void PresenterController::DispatchUnoCommand (const OUString& rsCommand) const +{ + if ( ! mxUrlTransformer.is()) + return; + + util::URL aURL; + aURL.Complete = rsCommand; + mxUrlTransformer->parseStrict(aURL); + + Reference<frame::XDispatch> xDispatch (GetDispatch(aURL)); + if ( ! xDispatch.is()) + return; + + xDispatch->dispatch(aURL, Sequence<beans::PropertyValue>()); +} + + + + +Reference<css::frame::XDispatch> PresenterController::GetDispatch (const util::URL& rURL) const +{ + if ( ! mxController.is()) + return NULL; + + Reference<frame::XDispatchProvider> xDispatchProvider (mxController->getFrame(), UNO_QUERY); + if ( ! xDispatchProvider.is()) + return NULL; + + return xDispatchProvider->queryDispatch( + rURL, + OUString(), + frame::FrameSearchFlag::SELF); +} + + + + +util::URL PresenterController::CreateURLFromString (const ::rtl::OUString& rsURL) const +{ + util::URL aURL; + + if (mxUrlTransformer.is()) + { + aURL.Complete = rsURL; + mxUrlTransformer->parseStrict(aURL); + } + + return aURL; +} + + + + +Reference<drawing::framework::XConfigurationController> + PresenterController::GetConfigurationController (void) const +{ + return mxConfigurationController; +} + + + + +Reference<drawing::XDrawPage> PresenterController::GetCurrentSlide (void) const +{ + return mxCurrentSlide; +} + + + + +::rtl::Reference<PresenterAccessible> PresenterController::GetAccessible (void) const +{ + return mpAccessibleObject; +} + + + + +void PresenterController::SetAccessibilityActiveState (const bool bIsActive) +{ + if ( mbIsAccessibilityActive != bIsActive) + { + mbIsAccessibilityActive = bIsActive; + UpdatePaneTitles(); + } +} + + + + +bool PresenterController::IsAccessibilityActive (void) const +{ + return mbIsAccessibilityActive; +} + + + + +void PresenterController::HandleMouseClick (const awt::MouseEvent& rEvent) +{ + if (mxSlideShowController.is()) + { + switch (rEvent.Buttons) + { + case awt::MouseButton::LEFT: + if (rEvent.Modifiers == awt::KeyModifier::MOD2) + mxSlideShowController->gotoNextSlide(); + else + mxSlideShowController->gotoNextEffect(); + break; + + case awt::MouseButton::RIGHT: + mxSlideShowController->gotoPreviousSlide(); + break; + + default: + // Other or multiple buttons. + break; + } + } +} + + + + +void PresenterController::RequestViews ( + const bool bIsSlideSorterActive, + const bool bIsNotesViewActive, + const bool bIsHelpViewActive) +{ + PresenterPaneContainer::PaneList::const_iterator iPane; + PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end()); + for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane) + { + bool bActivate (true); + const OUString sViewURL ((*iPane)->msViewURL); + if (sViewURL == PresenterViewFactory::msNotesViewURL) + { + bActivate = bIsNotesViewActive && !bIsSlideSorterActive && !bIsHelpViewActive; + } + else if (sViewURL == PresenterViewFactory::msSlideSorterURL) + { + bActivate = bIsSlideSorterActive; + } + else if (sViewURL == PresenterViewFactory::msCurrentSlidePreviewViewURL + || sViewURL == PresenterViewFactory::msNextSlidePreviewViewURL) + { + bActivate = !bIsSlideSorterActive && ! bIsHelpViewActive; + } + else if (sViewURL == PresenterViewFactory::msToolBarViewURL) + { + bActivate = true; + } + else if (sViewURL == PresenterViewFactory::msHelpViewURL) + { + bActivate = bIsHelpViewActive; + } + + if (bActivate) + ShowView(sViewURL); + else + HideView(sViewURL); + } +} + + + + +//----- XConfigurationChangeListener ------------------------------------------ + +void SAL_CALL PresenterController::notifyConfigurationChange ( + const ConfigurationChangeEvent& rEvent) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + sal_Int32 nType (0); + if ( ! (rEvent.UserData >>= nType)) + return; + + switch (nType) + { + case ResourceActivationEventType: + if (rEvent.ResourceId->compareTo(mxMainPaneId) == 0) + { + InitializeMainPane(Reference<XPane>(rEvent.ResourceObject,UNO_QUERY)); + } + else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_DIRECT)) + { + // A pane bound to the main pane has been created and is + // stored in the pane container. + Reference<XPane> xPane (rEvent.ResourceObject,UNO_QUERY); + if (xPane.is()) + { + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPaneContainer->FindPaneId(xPane->getResourceId())); + + // When there is a call out anchor location set then tell the + // window about it. + if (pDescriptor->mbHasCalloutAnchor) + pDescriptor->mxPane->SetCalloutAnchor( + pDescriptor->maCalloutAnchorLocation); + } + } + else if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT)) + { + // A view bound to one of the panes has been created and is + // stored in the pane container along with its pane. + Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY); + if (xView.is()) + { + SharedBitmapDescriptor pViewBackground( + GetViewBackground(xView->getResourceId()->getResourceURL())); + mpPaneContainer->StoreView(xView, pViewBackground); + UpdateViews(); + mpWindowManager->NotifyViewCreation(xView); + } + } + break; + + case ResourceDeactivationEventType: + if (rEvent.ResourceId->isBoundTo(mxMainPaneId,AnchorBindingMode_INDIRECT)) + { + // If this is a view then remove it from the pane container. + Reference<XView> xView (rEvent.ResourceObject,UNO_QUERY); + if (xView.is()) + { + PresenterPaneContainer::SharedPaneDescriptor pDescriptor( + mpPaneContainer->RemoveView(xView)); + + // A possibly opaque view has been removed. Update() + // updates the clip polygon. + mpWindowManager->Update(); + // Request the repainting of the area previously + // occupied by the view. + if (pDescriptor.get() != NULL) + GetPaintManager()->Invalidate(pDescriptor->mxBorderWindow); + } + } + break; + + case ConfigurationUpdateEndEventType: + if (IsAccessibilityActive()) + { + mpAccessibleObject->UpdateAccessibilityHierarchy(); + UpdateCurrentSlide(0); + } + break; + } +} + + + + +//----- XEventListener -------------------------------------------------------- + +void SAL_CALL PresenterController::disposing ( + const lang::EventObject& rEvent) + throw (RuntimeException) +{ + if (rEvent.Source == mxController) + mxController = NULL; + else if (rEvent.Source == mxConfigurationController) + mxConfigurationController = NULL; + else if (rEvent.Source == mxSlideShowController) + mxSlideShowController = NULL; + else if (rEvent.Source == mxMainWindow) + mxMainWindow = NULL; +} + + + + +//----- XFrameActionListener -------------------------------------------------- + +void SAL_CALL PresenterController::frameAction ( + const frame::FrameActionEvent& rEvent) + throw (RuntimeException) +{ + if (rEvent.Action == frame::FrameAction_FRAME_ACTIVATED) + { + if (mxSlideShowController.is()) + mxSlideShowController->activate(); + } +} + + + + +//----- XKeyListener ---------------------------------------------------------- + +void SAL_CALL PresenterController::keyPressed (const awt::KeyEvent& rEvent) + throw (RuntimeException) +{ + // Tell all views about the unhandled key event. + PresenterPaneContainer::PaneList::const_iterator iPane; + for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane) + { + if ( ! (*iPane)->mbIsActive) + continue; + + Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY); + if (xKeyListener.is()) + xKeyListener->keyPressed(rEvent); + } +} + + + + +void SAL_CALL PresenterController::keyReleased (const awt::KeyEvent& rEvent) + throw (RuntimeException) +{ + if (rEvent.Source != mxMainWindow) + return; + + switch (rEvent.KeyCode) + { + case awt::Key::ESCAPE: + case awt::Key::SUBTRACT: + { + if( mxController.is() ) + { + Reference< XPresentationSupplier > xPS( mxController->getModel(), UNO_QUERY ); + if( xPS.is() ) + { + Reference< XPresentation > xP( xPS->getPresentation() ); + if( xP.is() ) + xP->end(); + } + } + } + break; + + case awt::Key::PAGEDOWN: + if (mxSlideShowController.is()) + { + if (rEvent.Modifiers == awt::KeyModifier::MOD2) + mxSlideShowController->gotoNextSlide(); + else + mxSlideShowController->gotoNextEffect(); + } + break; + + case awt::Key::RIGHT: + case awt::Key::SPACE: + case awt::Key::DOWN: + case awt::Key::N: + if (mxSlideShowController.is()) + { + mxSlideShowController->gotoNextEffect(); + } + break; + + case awt::Key::PAGEUP: + if (mxSlideShowController.is()) + { + if (rEvent.Modifiers == awt::KeyModifier::MOD2) + mxSlideShowController->gotoPreviousSlide(); + else + mxSlideShowController->gotoPreviousEffect(); + } + break; + + case awt::Key::LEFT: + case awt::Key::UP: + case awt::Key::P: + case awt::Key::BACKSPACE: + if (mxSlideShowController.is()) + { + mxSlideShowController->gotoPreviousEffect(); + } + break; + + case awt::Key::HOME: + if (mxSlideShowController.is()) + { + mxSlideShowController->gotoFirstSlide(); + } + break; + + case awt::Key::END: + if (mxSlideShowController.is()) + { + mxSlideShowController->gotoLastSlide(); + } + break; + + case awt::Key::W: + case awt::Key::COMMA: + if (mxSlideShowController.is()) + { + if (mxSlideShowController->isPaused()) + mxSlideShowController->resume(); + else + mxSlideShowController->blankScreen(0x00ffffff); + } + break; + + case awt::Key::B: + case awt::Key::POINT: + if (mxSlideShowController.is()) + { + if (mxSlideShowController->isPaused()) + mxSlideShowController->resume(); + else + mxSlideShowController->blankScreen(0x00000000); + } + break; + + case awt::Key::NUM0: + case awt::Key::NUM1: + case awt::Key::NUM2: + case awt::Key::NUM3: + case awt::Key::NUM4: + case awt::Key::NUM5: + case awt::Key::NUM6: + case awt::Key::NUM7: + case awt::Key::NUM8: + case awt::Key::NUM9: + HandleNumericKeyPress(rEvent.KeyCode-awt::Key::NUM0, rEvent.Modifiers); + break; + + case awt::Key::RETURN: + if (mnPendingSlideNumber > 0) + { + if (mxSlideShowController.is()) + mxSlideShowController->gotoSlideIndex(mnPendingSlideNumber - 1); + mnPendingSlideNumber = -1; + } + else + { + if (mxSlideShowController.is()) + mxSlideShowController->gotoNextEffect(); + } + + break; + + case awt::Key::F1: + // Toggle the help view. + if (mpWindowManager.get() != NULL) + { + if (mpWindowManager->GetViewMode() != PresenterWindowManager::VM_Help) + mpWindowManager->SetViewMode(PresenterWindowManager::VM_Help); + else + mpWindowManager->SetHelpViewState(false); + } + + break; + + default: + // Tell all views about the unhandled key event. + PresenterPaneContainer::PaneList::const_iterator iPane; + for (iPane=mpPaneContainer->maPanes.begin(); iPane!=mpPaneContainer->maPanes.end(); ++iPane) + { + if ( ! (*iPane)->mbIsActive) + continue; + + Reference<awt::XKeyListener> xKeyListener ((*iPane)->mxView, UNO_QUERY); + if (xKeyListener.is()) + xKeyListener->keyReleased(rEvent); + } + break; + } +} + + + + +void PresenterController::HandleNumericKeyPress ( + const sal_Int32 nKey, + const sal_Int32 nModifiers) +{ + switch (nModifiers) + { + case 0: + if (mnPendingSlideNumber == -1) + mnPendingSlideNumber = 0; + UpdatePendingSlideNumber(mnPendingSlideNumber * 10 + nKey); + break; + + case awt::KeyModifier::MOD1: + // Ctrl-1, Ctrl-2, and Ctrl-3 are used to switch between views + // (slide view, notes view, normal) + mnPendingSlideNumber = -1; + if (mpWindowManager.get() == NULL) + return; + switch(nKey) + { + case 1: + mpWindowManager->SetViewMode(PresenterWindowManager::VM_Standard); + break; + case 2: + mpWindowManager->SetViewMode(PresenterWindowManager::VM_Notes); + break; + case 3: + mpWindowManager->SetViewMode(PresenterWindowManager::VM_SlideOverview); + break; + default: + // Ignore unsupported key. + break; + } + + default: + // Ignore unsupported modifiers. + break; + } +} + + + + +//----- XFocusListener -------------------------------------------------------- + +void SAL_CALL PresenterController::focusGained (const css::awt::FocusEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterController::focusLost (const css::awt::FocusEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +//----- XMouseListener -------------------------------------------------------- + +void SAL_CALL PresenterController::mousePressed (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; + if (mxMainWindow.is()) + mxMainWindow->setFocus(); +} + + + + +void SAL_CALL PresenterController::mouseReleased (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterController::mouseEntered (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterController::mouseExited (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +//----- XMouseMotionListener -------------------------------------------------- + +void SAL_CALL PresenterController::mouseMoved (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterController::mouseDragged (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +//----------------------------------------------------------------------------- + +void PresenterController::InitializeMainPane (const Reference<XPane>& rxPane) +{ + if ( ! rxPane.is()) + return; + + mpAccessibleObject = new PresenterAccessible( + mxComponentContext, + this, + rxPane); + + LoadTheme(rxPane); + + // Main pane has been created and is now observed by the window + // manager. + mpWindowManager->SetParentPane(rxPane); + mpWindowManager->SetTheme(mpTheme); + + if (mpPaneBorderPainter.get() != NULL) + mpPaneBorderPainter->SetTheme(mpTheme); + + // Add key listener + mxMainWindow = rxPane->getWindow(); + if (mxMainWindow.is()) + { + mxMainWindow->addKeyListener(this); + mxMainWindow->addFocusListener(this); + mxMainWindow->addMouseListener(this); + mxMainWindow->addMouseMotionListener(this); + } + Reference<XPane2> xPane2 (rxPane, UNO_QUERY); + if (xPane2.is()) + xPane2->setVisible(sal_True); + + mpPaintManager.reset(new PresenterPaintManager(mxMainWindow, mxPresenterHelper, mpPaneContainer)); + + mxCanvas = Reference<rendering::XSpriteCanvas>(rxPane->getCanvas(), UNO_QUERY); + + if (mxSlideShowController.is()) + mxSlideShowController->activate(); + + UpdateCurrentSlide(0); +} + + + + +void PresenterController::LoadTheme (const Reference<XPane>& rxPane) +{ + // Create (load) the current theme. + if (rxPane.is()) + mpTheme.reset(new PresenterTheme(mxComponentContext, OUString(), rxPane->getCanvas())); +} + + + + +double PresenterController::GetSlideAspectRatio (void) const +{ + double nSlideAspectRatio (28.0/21.0); + + try + { + if (mxController.is()) + { + Reference<drawing::XDrawPagesSupplier> xSlideSupplier ( + mxController->getModel(), UNO_QUERY_THROW); + Reference<drawing::XDrawPages> xSlides (xSlideSupplier->getDrawPages()); + if (xSlides.is() && xSlides->getCount()>0) + { + Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW); + sal_Int32 nWidth (28000); + sal_Int32 nHeight (21000); + if ((xProperties->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Width"))) >>= nWidth) + && (xProperties->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Height"))) >>= nHeight) + && nHeight > 0) + { + nSlideAspectRatio = double(nWidth) / double(nHeight); + } + } + } + } + catch (RuntimeException&) + { + OSL_ASSERT(false); + } + + return nSlideAspectRatio; +} + + + + +void PresenterController::UpdatePendingSlideNumber (const sal_Int32 nPendingSlideNumber) +{ + mnPendingSlideNumber = nPendingSlideNumber; + + if (mpTheme.get() == NULL) + return; + + if ( ! mxMainWindow.is()) + return; + + PresenterTheme::SharedFontDescriptor pFont ( + mpTheme->GetFont(A2S("PendingSlideNumberFont"))); + if (pFont.get() == NULL) + return; + + pFont->PrepareFont(Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY)); + if ( ! pFont->mxFont.is()) + return; + + const OUString sText (OUString::valueOf(mnPendingSlideNumber)); + rendering::StringContext aContext (sText, 0, sText.getLength()); + Reference<rendering::XTextLayout> xLayout ( + pFont->mxFont->createTextLayout( + aContext, + rendering::TextDirection::WEAK_LEFT_TO_RIGHT, + 0)); +} + + + + +void PresenterController::ThrowIfDisposed (void) const + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterController object has already been disposed")), + const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + } +} + + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterController.hxx b/sdext/source/presenter/PresenterController.hxx new file mode 100644 index 000000000000..b0fe117a47b0 --- /dev/null +++ b/sdext/source/presenter/PresenterController.hxx @@ -0,0 +1,270 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_CONTROLLER_HXX +#define SDEXT_PRESENTER_CONTROLLER_HXX + +#include "PresenterAccessibility.hxx" +#include "PresenterPaneContainer.hxx" +#include "PresenterTheme.hxx" +#include "PresenterSprite.hxx" +#include <cppuhelper/compbase6.hxx> +#include <cppuhelper/basemutex.hxx> +#include <com/sun/star/awt/FontDescriptor.hpp> +#include <com/sun/star/awt/XFocusListener.hpp> +#include <com/sun/star/awt/XKeyListener.hpp> +#include <com/sun/star/awt/XMouseListener.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/presentation/XSlideShowController.hpp> +#include <com/sun/star/presentation/XSlideShowListener.hpp> +#include <com/sun/star/frame/XFrameActionListener.hpp> +#include <com/sun/star/drawing/framework/XConfigurationChangeListener.hpp> +#include <com/sun/star/drawing/framework/XConfigurationController.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/util/Color.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <rtl/ref.hxx> +#include <map> +#include <vector> +#include <boost/function.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/scoped_ptr.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +class PresenterAnimator; +class PresenterCanvasHelper; +class PresenterPaintManager; +class PresenterPaneAnimator; +class PresenterPaneContainer; +class PresenterPaneBorderPainter; +class PresenterTheme; +class PresenterWindowManager; + +namespace { + typedef ::cppu::WeakComponentImplHelper6 < + css::drawing::framework::XConfigurationChangeListener, + css::frame::XFrameActionListener, + css::awt::XKeyListener, + css::awt::XFocusListener, + css::awt::XMouseListener, + css::awt::XMouseMotionListener + > PresenterControllerInterfaceBase; +} + + +/** The controller of the presenter screen is responsible for telling the + individual views which slides to show. Additionally it provides access + to frequently used values of the current theme. +*/ +class PresenterController + : protected ::cppu::BaseMutex, + public PresenterControllerInterfaceBase +{ +public: + static ::rtl::Reference<PresenterController> Instance ( + const css::uno::Reference<css::frame::XFrame>& rxFrame); + + PresenterController ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::frame::XController>& rxController, + const css::uno::Reference<css::presentation::XSlideShowController>& rxSlideShowController, + const rtl::Reference<PresenterPaneContainer>& rpPaneContainer, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxMainPaneId); + ~PresenterController (void); + + virtual void SAL_CALL disposing (void); + + void UpdateCurrentSlide (const sal_Int32 nOffset); + + SharedBitmapDescriptor + GetViewBackground (const ::rtl::OUString& rsViewURL) const; + PresenterTheme::SharedFontDescriptor + GetViewFont (const ::rtl::OUString& rsViewURL) const; + ::boost::shared_ptr<PresenterTheme> GetTheme (void) const; + ::rtl::Reference<PresenterWindowManager> GetWindowManager (void) const; + css::uno::Reference<css::presentation::XSlideShowController> + GetSlideShowController (void) const; + rtl::Reference<PresenterPaneContainer> GetPaneContainer (void) const; + ::rtl::Reference<PresenterPaneBorderPainter> GetPaneBorderPainter (void) const; + ::boost::shared_ptr<PresenterAnimator> GetAnimator (void) const; + ::boost::shared_ptr<PresenterCanvasHelper> GetCanvasHelper (void) const; + css::uno::Reference<css::drawing::XPresenterHelper> GetPresenterHelper (void) const; + ::boost::shared_ptr<PresenterPaintManager> GetPaintManager (void) const; + void HideSlideSorter (void); + double GetSlideAspectRatio (void) const; + void ShowView (const ::rtl::OUString& rsViewURL); + void HideView (const ::rtl::OUString& rsViewURL); + bool IsViewVisible (const ::rtl::OUString& rsViewURL) const; + void DispatchUnoCommand (const ::rtl::OUString& rsCommand) const; + css::uno::Reference<css::frame::XDispatch> GetDispatch ( + const css::util::URL& rURL) const; + css::util::URL CreateURLFromString (const ::rtl::OUString& rsURL) const; + css::uno::Reference<css::drawing::framework::XConfigurationController> + GetConfigurationController (void) const; + css::uno::Reference<css::drawing::XDrawPage> GetCurrentSlide (void) const; + ::rtl::Reference<PresenterAccessible> GetAccessible (void) const; + void SetAccessibilityActiveState (const bool bIsActive); + bool IsAccessibilityActive (void) const; + + void HandleMouseClick (const css::awt::MouseEvent& rEvent); + void UpdatePaneTitles (void); + + /** Request activation or deactivation of (some of) the views according + to the given parameters. + */ + void RequestViews ( + const bool bIsSlideSorterActive, + const bool bIsNotesViewActive, + const bool bIsHelpViewActive); + + // XConfigurationChangeListener + + virtual void SAL_CALL notifyConfigurationChange ( + const com::sun::star::drawing::framework::ConfigurationChangeEvent& rEvent) + throw (com::sun::star::uno::RuntimeException); + + + // XEventListener + + virtual void SAL_CALL disposing ( + const com::sun::star::lang::EventObject& rEvent) + throw (com::sun::star::uno::RuntimeException); + + + // XFrameActionListener + + virtual void SAL_CALL frameAction ( + const css::frame::FrameActionEvent& rEvent) + throw (com::sun::star::uno::RuntimeException); + + + // XKeyListener + + virtual void SAL_CALL keyPressed (const css::awt::KeyEvent& rEvent) + throw (css::uno::RuntimeException); + virtual void SAL_CALL keyReleased (const css::awt::KeyEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XFocusListener + + virtual void SAL_CALL focusGained (const css::awt::FocusEvent& rEvent) + throw (css::uno::RuntimeException); + virtual void SAL_CALL focusLost (const css::awt::FocusEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XMouseListener + + virtual void SAL_CALL mousePressed (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseReleased (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseEntered (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseExited (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XMouseMotionListener + + virtual void SAL_CALL mouseMoved (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseDragged (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + +private: + typedef ::std::map<css::uno::Reference<css::frame::XFrame>,rtl::Reference<PresenterController> > InstanceContainer; + static InstanceContainer maInstances; + + css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + css::uno::Reference<css::rendering::XSpriteCanvas> mxCanvas; + css::uno::Reference<css::frame::XController> mxController; + css::uno::Reference<css::drawing::framework::XConfigurationController> + mxConfigurationController; + css::uno::Reference<css::presentation::XSlideShowController> mxSlideShowController; + css::uno::Reference<css::drawing::framework::XResourceId> mxMainPaneId; + rtl::Reference<PresenterPaneContainer> mpPaneContainer; + sal_Int32 mnCurrentSlideIndex; + css::uno::Reference<css::drawing::XDrawPage> mxCurrentSlide; + css::uno::Reference<css::drawing::XDrawPage> mxNextSlide; + ::rtl::Reference<PresenterWindowManager> mpWindowManager; + ::boost::shared_ptr<PresenterPaneAnimator> mpCurrentPaneAnimation; + sal_Int32 mnWindowBackgroundColor; + ::boost::shared_ptr<PresenterTheme> mpTheme; + css::uno::Reference<css::awt::XWindow> mxMainWindow; + ::rtl::Reference<PresenterPaneBorderPainter> mpPaneBorderPainter; + ::boost::shared_ptr<PresenterAnimator> mpAnimator; + ::boost::shared_ptr<PresenterCanvasHelper> mpCanvasHelper; + css::uno::Reference<css::drawing::XPresenterHelper> mxPresenterHelper; + ::boost::shared_ptr<PresenterPaintManager> mpPaintManager; + sal_Int32 mnPendingSlideNumber; + css::uno::Reference<css::util::XURLTransformer> mxUrlTransformer; + ::rtl::Reference<PresenterAccessible> mpAccessibleObject; + bool mbIsAccessibilityActive; + + void InitializePresenterScreen (void); + void InitializeSlideShowView (const css::uno::Reference<css::uno::XInterface>& rxView); + void GetSlides (const sal_Int32 nOffset); + void UpdateViews (void); + void InitializeMainPane (const css::uno::Reference<css::drawing::framework::XPane>& rxPane); + void LoadTheme (const css::uno::Reference<css::drawing::framework::XPane>& rxPane); + void UpdatePendingSlideNumber (const sal_Int32 nPendingSlideNumber); + + /** This method is called when the user pressed one of the numerical + keys. Depending on the modifier, numeric keys switch to another + slide (no modifier), or change to another view (Ctrl modifier). + @param nKey + Numeric value that is printed on the pressed key. For example + pressing the key '4' will result in the value 4, not the ASCII + code (0x34?). + @param nModifiers + The modifier bit field as provided by the key up event. + */ + void HandleNumericKeyPress (const sal_Int32 nKey, const sal_Int32 nModifiers); + + void ThrowIfDisposed (void) const throw (::com::sun::star::lang::DisposedException); +}; + + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterCurrentSlideObserver.cxx b/sdext/source/presenter/PresenterCurrentSlideObserver.cxx new file mode 100644 index 000000000000..90e55b219390 --- /dev/null +++ b/sdext/source/presenter/PresenterCurrentSlideObserver.cxx @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterCurrentSlideObserver.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace sdext { namespace presenter { + +//===== PresenterCurrentSlideObserver ========================================= + +PresenterCurrentSlideObserver::PresenterCurrentSlideObserver ( + const ::rtl::Reference<PresenterController>& rxPresenterController, + const Reference<presentation::XSlideShowController>& rxSlideShowController) + : PresenterCurrentSlideObserverInterfaceBase(m_aMutex), + mpPresenterController(rxPresenterController), + mxSlideShowController(rxSlideShowController) +{ + if( mpPresenterController.is() ) + { + mpPresenterController->addEventListener(this); + } + + if( mxSlideShowController.is() ) + { + // Listen for events from the slide show controller. + mxSlideShowController->addSlideShowListener(static_cast<XSlideShowListener*>(this)); + } +} + +PresenterCurrentSlideObserver::~PresenterCurrentSlideObserver (void) +{ +} + +void SAL_CALL PresenterCurrentSlideObserver::disposing (void) +{ + // Disconnect form the slide show controller. + if(mxSlideShowController.is()) + { + mxSlideShowController->removeSlideShowListener(static_cast<XSlideShowListener*>(this)); + mxSlideShowController = NULL; + } +} + +//----- XSlideShowListener ---------------------------------------------------- + +void SAL_CALL PresenterCurrentSlideObserver::beginEvent ( + const Reference<animations::XAnimationNode>& rNode) + throw (css::uno::RuntimeException) +{ + (void)rNode; +} + +void SAL_CALL PresenterCurrentSlideObserver::endEvent ( + const Reference<animations::XAnimationNode>& rNode) + throw(css::uno::RuntimeException) +{ + (void)rNode; +} + +void SAL_CALL PresenterCurrentSlideObserver::repeat ( + const css::uno::Reference<css::animations::XAnimationNode>& rNode, + sal_Int32) + throw (com::sun::star::uno::RuntimeException) +{ + (void)rNode; +} + +void SAL_CALL PresenterCurrentSlideObserver::paused (void) + throw (com::sun::star::uno::RuntimeException) +{ +} + +void SAL_CALL PresenterCurrentSlideObserver::resumed (void) + throw (css::uno::RuntimeException) +{ +} + +void SAL_CALL PresenterCurrentSlideObserver::slideEnded (sal_Bool bReverse) + throw (css::uno::RuntimeException) +{ + // Determine whether the new current slide (the one after the one that + // just ended) is the slide past the last slide in the presentation, + // i.e. the one that says something like "click to end presentation...". + if (mxSlideShowController.is() && !bReverse) + if (mxSlideShowController->getNextSlideIndex() < 0) + if( mpPresenterController.is() ) + mpPresenterController->UpdateCurrentSlide(+1); +} + +void SAL_CALL PresenterCurrentSlideObserver::hyperLinkClicked (const rtl::OUString &) + throw (css::uno::RuntimeException) +{ +} + +void SAL_CALL PresenterCurrentSlideObserver::slideTransitionStarted (void) + throw (css::uno::RuntimeException) +{ + if( mpPresenterController.is() ) + mpPresenterController->UpdateCurrentSlide(0); +} + +void SAL_CALL PresenterCurrentSlideObserver::slideTransitionEnded (void) + throw (css::uno::RuntimeException) +{ +} + +void SAL_CALL PresenterCurrentSlideObserver::slideAnimationsEnded (void) + throw (css::uno::RuntimeException) +{ +} + +//----- XEventListener -------------------------------------------------------- + +void SAL_CALL PresenterCurrentSlideObserver::disposing ( + const lang::EventObject& rEvent) + throw (RuntimeException) +{ + if (rEvent.Source == Reference<XInterface>(static_cast<XWeak*>(mpPresenterController.get()))) + dispose(); + else if (rEvent.Source == mxSlideShowController) + mxSlideShowController = NULL; +} + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterCurrentSlideObserver.hxx b/sdext/source/presenter/PresenterCurrentSlideObserver.hxx new file mode 100644 index 000000000000..fc9a5fe18b7a --- /dev/null +++ b/sdext/source/presenter/PresenterCurrentSlideObserver.hxx @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_CURRENT_SLIDE_OBSERVER +#define SDEXT_PRESENTER_CURRENT_SLIDE_OBSERVER + +#include "PresenterController.hxx" +#include <com/sun/star/presentation/XSlideShow.hpp> +#include <com/sun/star/presentation/XSlideShowController.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <cppuhelper/compbase1.hxx> +#include <cppuhelper/basemutex.hxx> +#include <rtl/ref.hxx> +#include <salhelper/timer.hxx> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +namespace { + typedef ::cppu::WeakComponentImplHelper1 < + css::presentation::XSlideShowListener + > PresenterCurrentSlideObserverInterfaceBase; +} + +/** Check periodically the slide show controller and the + frame::XController whether the current slide has changed. If so, + then inform the presenter controller about it. + + Objects of this class have their own lifetime control and destroy + themselves when the presenter controller is diposed. +*/ +class PresenterCurrentSlideObserver + : protected ::cppu::BaseMutex, + public PresenterCurrentSlideObserverInterfaceBase +{ +public: + PresenterCurrentSlideObserver ( + const ::rtl::Reference<PresenterController>& rxPresenterController, + const css::uno::Reference<css::presentation::XSlideShowController>& rxSlideShowController); + virtual ~PresenterCurrentSlideObserver (void); + + virtual void SAL_CALL disposing (void); + + // XSlideShowListener + virtual void SAL_CALL paused( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL resumed( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL slideTransitionStarted( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL slideTransitionEnded( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL slideAnimationsEnded( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL slideEnded(sal_Bool bReverse) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL hyperLinkClicked( const ::rtl::OUString& hyperLink ) throw (::com::sun::star::uno::RuntimeException); + + // XAnimationListener + virtual void SAL_CALL beginEvent( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& Node ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL endEvent( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& Node ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL repeat( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& Node, ::sal_Int32 Repeat ) throw (::com::sun::star::uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing ( + const com::sun::star::lang::EventObject& rEvent) + throw (com::sun::star::uno::RuntimeException); + +private: + ::rtl::Reference<PresenterController> mpPresenterController; + css::uno::Reference<css::presentation::XSlideShowController> mxSlideShowController; +}; + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterExtensionIdentifier.txx b/sdext/source/presenter/PresenterExtensionIdentifier.txx new file mode 100644 index 000000000000..e505fd092bba --- /dev/null +++ b/sdext/source/presenter/PresenterExtensionIdentifier.txx @@ -0,0 +1,41 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_EXTENSION_IDENTIFIER_HXX +#define SDEXT_PRESENTER_EXTENSION_IDENTIFIER_HXX + +namespace sdext { namespace presenter { + +/** The UPDATE_IDENTIFIER part of the string below is replaced by the + makefile.mk with the actual, platform specific, extension identifier. +*/ +const ::rtl::OUString PresenterComponent::gsExtensionIdentifier( + RTL_CONSTASCII_USTRINGPARAM("com.sun.PresenterScreen-UPDATED_PLATFORM")); + +} } + +#endif diff --git a/sdext/source/presenter/PresenterFrameworkObserver.cxx b/sdext/source/presenter/PresenterFrameworkObserver.cxx new file mode 100644 index 000000000000..3142d7606fb2 --- /dev/null +++ b/sdext/source/presenter/PresenterFrameworkObserver.cxx @@ -0,0 +1,216 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterFrameworkObserver.hxx" +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <boost/bind.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; + +using ::rtl::OUString; + +#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) + +namespace sdext { namespace presenter { + +PresenterFrameworkObserver::PresenterFrameworkObserver ( + const css::uno::Reference<css::drawing::framework::XConfigurationController>&rxController, + const OUString& rsEventName, + const Predicate& rPredicate, + const Action& rAction) + : PresenterFrameworkObserverInterfaceBase(m_aMutex), + mxConfigurationController(rxController), + maPredicate(rPredicate), + maAction(rAction) +{ + if ( ! mxConfigurationController.is()) + throw lang::IllegalArgumentException(); + + if (mxConfigurationController->hasPendingRequests()) + { + if (rsEventName.getLength() > 0) + { + mxConfigurationController->addConfigurationChangeListener( + this, + rsEventName, + Any()); + } + mxConfigurationController->addConfigurationChangeListener( + this, + A2S("ConfigurationUpdateEnd"), + Any()); + } + else + { + rAction(maPredicate()); + } +} + + + + +PresenterFrameworkObserver::~PresenterFrameworkObserver (void) +{ +} + + + + +void PresenterFrameworkObserver::RunOnResourceActivation ( + const css::uno::Reference<css::drawing::framework::XConfigurationController>&rxController, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId, + const Action& rAction) +{ + new PresenterFrameworkObserver( + rxController, + A2S("ResourceActivation"), + ::boost::bind(&PresenterFrameworkObserver::HasResource, rxController, rxResourceId), + rAction); +} + + + + +void PresenterFrameworkObserver::RunOnUpdateEnd ( + const css::uno::Reference<css::drawing::framework::XConfigurationController>&rxController, + const Action& rAction) +{ + new PresenterFrameworkObserver( + rxController, + OUString(), + &PresenterFrameworkObserver::True, + rAction); +} + + + + +bool PresenterFrameworkObserver::HasResource ( + const css::uno::Reference<css::drawing::framework::XConfigurationController>&rxController, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId) +{ + return rxController.is() && rxController->getResource(rxResourceId).is(); +} + + + + +bool PresenterFrameworkObserver::True (void) +{ + return true; +} + + + + +bool PresenterFrameworkObserver::False (void) +{ + return false; +} + + + + +void SAL_CALL PresenterFrameworkObserver::disposing (void) +{ + if ( ! maAction.empty()) + maAction(false); + Shutdown(); +} + + + + +void PresenterFrameworkObserver::Shutdown (void) +{ + maAction = Action(); + maPredicate = Predicate(); + + if (mxConfigurationController != NULL) + { + mxConfigurationController->removeConfigurationChangeListener(this); + mxConfigurationController = NULL; + } +} + + + + +void SAL_CALL PresenterFrameworkObserver::disposing (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + if ( ! rEvent.Source.is()) + return; + + if (rEvent.Source == mxConfigurationController) + { + mxConfigurationController = NULL; + if ( ! maAction.empty()) + maAction(false); + } +} + + + + +void SAL_CALL PresenterFrameworkObserver::notifyConfigurationChange ( + const ConfigurationChangeEvent& rEvent) + throw (RuntimeException) +{ + bool bDispose(false); + + Action aAction (maAction); + Predicate aPredicate (maPredicate); + if (rEvent.Type.equals(A2S("ConfigurationUpdateEnd"))) + { + Shutdown(); + aAction(aPredicate); + bDispose = true; + } + else if (aPredicate()) + { + Shutdown(); + aAction(true); + bDispose = true; + } + + if (bDispose) + { + maAction.clear(); + dispose(); + } +} + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterFrameworkObserver.hxx b/sdext/source/presenter/PresenterFrameworkObserver.hxx new file mode 100644 index 000000000000..422055830d6e --- /dev/null +++ b/sdext/source/presenter/PresenterFrameworkObserver.hxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_FRAMEWORK_OBSERVER_HXX +#define SDEXT_PRESENTER_PRESENTER_FRAMEWORK_OBSERVER_HXX + +#include <com/sun/star/drawing/framework/XConfigurationChangeListener.hpp> +#include <com/sun/star/drawing/framework/XConfigurationController.hpp> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase1.hxx> +#include <boost/function.hpp> +#include <boost/noncopyable.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + + +typedef ::cppu::WeakComponentImplHelper1 < + ::com::sun::star::drawing::framework::XConfigurationChangeListener + > PresenterFrameworkObserverInterfaceBase; + +/** Watch the drawing framework for changes and run callbacks when a certain + change takes place. +*/ +class PresenterFrameworkObserver + : private ::boost::noncopyable, + private ::cppu::BaseMutex, + public PresenterFrameworkObserverInterfaceBase +{ +public: + typedef ::boost::function<bool(void)> Predicate; + typedef ::boost::function<void(bool)> Action; + + /** Register an action callback to be run when the specified resource is + activated. The action may be called synchronously when the resource + is already active or asynchronously when the resource is actived in + the future. + @param rxController + The controller gives access to the drawing framework. + @param rxResourceId + The id of the resource to watch for activation. + @param rAction + The callback that is called when the resource is activated. + */ + static void RunOnResourceActivation ( + const css::uno::Reference<css::drawing::framework::XConfigurationController>&rxController, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId, + const Action& rAction); + static void RunOnUpdateEnd ( + const css::uno::Reference<css::drawing::framework::XConfigurationController>&rxController, + const Action& rAction); + + virtual void SAL_CALL disposing (void); + virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + virtual void SAL_CALL notifyConfigurationChange ( + const css::drawing::framework::ConfigurationChangeEvent& rEvent) + throw (css::uno::RuntimeException); + +private: + ::rtl::OUString msEventType; + ::css::uno::Reference<css::drawing::framework::XConfigurationController> mxConfigurationController; + Predicate maPredicate; + Action maAction; + + /** Create a new PresenterFrameworkObserver object. + @param rsEventName + An event name other than ConfigurationUpdateEnd. When the + observer shall only listen for ConfigurationUpdateEnd then pass + an empty name. + @param rPredicate + This functor tests whether the action is to be executed or not. + @param rAction + The functor to execute when the predicate returns true, + e.g. when some resource has been created. + */ + PresenterFrameworkObserver ( + const css::uno::Reference<css::drawing::framework::XConfigurationController>&rxController, + const ::rtl::OUString& rsEventName, + const Predicate& rPredicate, + const Action& rAction); + virtual ~PresenterFrameworkObserver (void); + + void Shutdown (void); + + /** Predicate that returns true when the specified resource is active + with respect to the given configuration controller. + */ + static bool HasResource ( + const css::uno::Reference<css::drawing::framework::XConfigurationController>&rxController, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId); + + /** Predicate that always returns true. + */ + static bool True (void); + + /** Predicate that always returns false. + */ + static bool False (void); +}; + + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterGeometryHelper.cxx b/sdext/source/presenter/PresenterGeometryHelper.cxx new file mode 100644 index 000000000000..2fdc0ea004ea --- /dev/null +++ b/sdext/source/presenter/PresenterGeometryHelper.cxx @@ -0,0 +1,337 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterGeometryHelper.hxx" + +#include <math.h> +#include <algorithm> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace { + +sal_Int32 Right (const awt::Rectangle& rBox) +{ + return rBox.X + rBox.Width - 1; +} + +sal_Int32 Bottom (const awt::Rectangle& rBox) +{ + return rBox.Y + rBox.Height - 1; +} + +sal_Int32 Width (const sal_Int32 nLeft, const sal_Int32 nRight) +{ + return nRight - nLeft + 1; +} + +sal_Int32 Height (const sal_Int32 nTop, const sal_Int32 nBottom) +{ + return nBottom - nTop + 1; +} + + +} // end of anonymous namespace + + + +namespace sdext { namespace presenter { + +sal_Int32 PresenterGeometryHelper::Floor (const double nValue) +{ + return sal::static_int_cast<sal_Int32>(floor(nValue)); +} + + + + +sal_Int32 PresenterGeometryHelper::Ceil (const double nValue) +{ + return sal::static_int_cast<sal_Int32>(ceil(nValue)); +} + + + + +sal_Int32 PresenterGeometryHelper::Round (const double nValue) +{ + return sal::static_int_cast<sal_Int32>(floor(0.5 + nValue)); +} + + + + +awt::Rectangle PresenterGeometryHelper::ConvertRectangle ( + const geometry::RealRectangle2D& rBox) +{ + const sal_Int32 nLeft (Floor(rBox.X1)); + const sal_Int32 nTop (Floor(rBox.Y1)); + const sal_Int32 nRight (Ceil(rBox.X2)); + const sal_Int32 nBottom (Ceil(rBox.Y2)); + return awt::Rectangle (nLeft,nTop,nRight-nLeft,nBottom-nTop); +} + + + + +awt::Rectangle PresenterGeometryHelper::ConvertRectangleWithConstantSize ( + const geometry::RealRectangle2D& rBox) +{ + return awt::Rectangle ( + Round(rBox.X1), + Round(rBox.Y1), + Round(rBox.X2 - rBox.X1), + Round(rBox.Y2 - rBox.Y1)); +} + + + + +geometry::RealRectangle2D PresenterGeometryHelper::ConvertRectangle ( + const css::awt::Rectangle& rBox) +{ + return geometry::RealRectangle2D( + rBox.X, + rBox.Y, + rBox.X + rBox.Width, + rBox.Y + rBox.Height); +} + + + + +awt::Rectangle PresenterGeometryHelper::TranslateRectangle ( + const css::awt::Rectangle& rBox, + const sal_Int32 nXOffset, + const sal_Int32 nYOffset) +{ + return awt::Rectangle(rBox.X + nXOffset, rBox.Y + nYOffset, rBox.Width, rBox.Height); +} + + + + +awt::Rectangle PresenterGeometryHelper::Intersection ( + const css::awt::Rectangle& rBox1, + const css::awt::Rectangle& rBox2) +{ + const sal_Int32 nLeft (::std::max(rBox1.X, rBox2.X)); + const sal_Int32 nTop (::std::max(rBox1.Y, rBox2.Y)); + const sal_Int32 nRight (::std::min(Right(rBox1), Right(rBox2))); + const sal_Int32 nBottom (::std::min(Bottom(rBox1), Bottom(rBox2))); + if (nLeft >= nRight || nTop >= nBottom) + return awt::Rectangle(); + else + return awt::Rectangle(nLeft,nTop, Width(nLeft,nRight), Height(nTop,nBottom)); +} + + + + +geometry::RealRectangle2D PresenterGeometryHelper::Intersection ( + const geometry::RealRectangle2D& rBox1, + const geometry::RealRectangle2D& rBox2) +{ + const double nLeft (::std::max(rBox1.X1, rBox2.X1)); + const double nTop (::std::max(rBox1.Y1, rBox2.Y1)); + const double nRight (::std::min(rBox1.X2, rBox2.X2)); + const double nBottom (::std::min(rBox1.Y2, rBox2.Y2)); + if (nLeft >= nRight || nTop >= nBottom) + return geometry::RealRectangle2D(0,0,0,0); + else + return geometry::RealRectangle2D(nLeft,nTop, nRight, nBottom); +} + + + + +bool PresenterGeometryHelper::IsInside ( + const css::geometry::RealRectangle2D& rBox, + const css::geometry::RealPoint2D& rPoint) +{ + return rBox.X1 <= rPoint.X + && rBox.Y1 <= rPoint.Y + && rBox.X2 >= rPoint.X + && rBox.Y2 >= rPoint.Y; +} + + + + +bool PresenterGeometryHelper::IsInside ( + const css::awt::Rectangle& rBox1, + const css::awt::Rectangle& rBox2) +{ + return rBox1.X >= rBox2.X + && rBox1.Y >= rBox2.Y + && rBox1.X+rBox1.Width <= rBox2.X+rBox2.Width + && rBox1.Y+rBox1.Height <= rBox2.Y+rBox2.Height; +} + + + + +awt::Rectangle PresenterGeometryHelper::Union ( + const css::awt::Rectangle& rBox1, + const css::awt::Rectangle& rBox2) +{ + if (rBox1.Width<=0 || rBox1.Height<=0) + return rBox2; + else if (rBox2.Width<=0 || rBox2.Height<=0) + return rBox1; + + const sal_Int32 nLeft (::std::min(rBox1.X, rBox2.X)); + const sal_Int32 nTop (::std::min(rBox1.Y, rBox2.Y)); + const sal_Int32 nRight (::std::max(Right(rBox1), Right(rBox2))); + const sal_Int32 nBottom (::std::max(Bottom(rBox1), Bottom(rBox2))); + if (nLeft >= nRight || nTop >= nBottom) + return awt::Rectangle(); + else + return awt::Rectangle(nLeft,nTop, Width(nLeft,nRight), Height(nTop,nBottom)); +} + + + + +geometry::RealRectangle2D PresenterGeometryHelper::Union ( + const geometry::RealRectangle2D& rBox1, + const geometry::RealRectangle2D& rBox2) +{ + const double nLeft (::std::min(rBox1.X1, rBox2.X1)); + const double nTop (::std::min(rBox1.Y1, rBox2.Y1)); + const double nRight (::std::max(rBox1.X2, rBox2.X2)); + const double nBottom (::std::max(rBox1.Y2, rBox2.Y2)); + if (nLeft >= nRight || nTop >= nBottom) + return geometry::RealRectangle2D(0,0,0,0); + else + return geometry::RealRectangle2D(nLeft,nTop, nRight, nBottom); +} + + + + +bool PresenterGeometryHelper::AreRectanglesDisjoint ( + const css::awt::Rectangle& rBox1, + const css::awt::Rectangle& rBox2) +{ + return rBox1.X+rBox1.Width <= rBox2.X + || rBox1.Y+rBox1.Height <= rBox2.Y + || rBox1.X >= rBox2.X+rBox2.Width + || rBox1.Y >= rBox2.Y+rBox2.Height; +} + + + + +Reference<rendering::XPolyPolygon2D> PresenterGeometryHelper::CreatePolygon( + const awt::Rectangle& rBox, + const Reference<rendering::XGraphicDevice>& rxDevice) +{ + if ( ! rxDevice.is()) + return NULL; + + Sequence<Sequence<geometry::RealPoint2D> > aPoints(1); + aPoints[0] = Sequence<geometry::RealPoint2D>(4); + aPoints[0][0] = geometry::RealPoint2D(rBox.X, rBox.Y); + aPoints[0][1] = geometry::RealPoint2D(rBox.X, rBox.Y+rBox.Height); + aPoints[0][2] = geometry::RealPoint2D(rBox.X+rBox.Width, rBox.Y+rBox.Height); + aPoints[0][3] = geometry::RealPoint2D(rBox.X+rBox.Width, rBox.Y); + Reference<rendering::XLinePolyPolygon2D> xPolygon ( + rxDevice->createCompatibleLinePolyPolygon(aPoints)); + Reference<rendering::XPolyPolygon2D> xRectangle (xPolygon, UNO_QUERY); + if (xRectangle.is()) + xRectangle->setClosed(0, sal_True); + + return xRectangle; +} + + + + +Reference<rendering::XPolyPolygon2D> PresenterGeometryHelper::CreatePolygon( + const geometry::RealRectangle2D& rBox, + const Reference<rendering::XGraphicDevice>& rxDevice) +{ + if ( ! rxDevice.is()) + return NULL; + + Sequence<Sequence<geometry::RealPoint2D> > aPoints(1); + aPoints[0] = Sequence<geometry::RealPoint2D>(4); + aPoints[0][0] = geometry::RealPoint2D(rBox.X1, rBox.Y1); + aPoints[0][1] = geometry::RealPoint2D(rBox.X1, rBox.Y2); + aPoints[0][2] = geometry::RealPoint2D(rBox.X2, rBox.Y2); + aPoints[0][3] = geometry::RealPoint2D(rBox.X2, rBox.Y1); + Reference<rendering::XLinePolyPolygon2D> xPolygon ( + rxDevice->createCompatibleLinePolyPolygon(aPoints)); + Reference<rendering::XPolyPolygon2D> xRectangle (xPolygon, UNO_QUERY); + if (xRectangle.is()) + xRectangle->setClosed(0, sal_True); + + return xRectangle; +} + + + + +Reference<rendering::XPolyPolygon2D> PresenterGeometryHelper::CreatePolygon( + const ::std::vector<css::awt::Rectangle>& rBoxes, + const Reference<rendering::XGraphicDevice>& rxDevice) +{ + if ( ! rxDevice.is()) + return NULL; + + const sal_Int32 nCount (rBoxes.size()); + Sequence<Sequence<geometry::RealPoint2D> > aPoints(nCount); + for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex) + { + const awt::Rectangle& rBox (rBoxes[nIndex]); + aPoints[nIndex] = Sequence<geometry::RealPoint2D>(4); + aPoints[nIndex][0] = geometry::RealPoint2D(rBox.X, rBox.Y); + aPoints[nIndex][1] = geometry::RealPoint2D(rBox.X, rBox.Y+rBox.Height); + aPoints[nIndex][2] = geometry::RealPoint2D(rBox.X+rBox.Width, rBox.Y+rBox.Height); + aPoints[nIndex][3] = geometry::RealPoint2D(rBox.X+rBox.Width, rBox.Y); + } + + Reference<rendering::XLinePolyPolygon2D> xPolygon ( + rxDevice->createCompatibleLinePolyPolygon(aPoints)); + Reference<rendering::XPolyPolygon2D> xRectangle (xPolygon, UNO_QUERY); + if (xRectangle.is()) + for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex) + xRectangle->setClosed(nIndex, sal_True); + + return xRectangle; +} + + +} } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterGeometryHelper.hxx b/sdext/source/presenter/PresenterGeometryHelper.hxx new file mode 100644 index 000000000000..b5901a68fd8d --- /dev/null +++ b/sdext/source/presenter/PresenterGeometryHelper.hxx @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_GEOMETRY_HELPER_HXX +#define SDEXT_PRESENTER_PRESENTER_GEOMETRY_HELPER_HXX + +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/rendering/XGraphicDevice.hpp> +#include <com/sun/star/rendering/XPolyPolygon2D.hpp> +#include <com/sun/star/geometry/RealRectangle2D.hpp> +#include <vector> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +/** Collection of geometry related convenience functions. +*/ +class PresenterGeometryHelper +{ +public: + static sal_Int32 Round (const double nValue); + static sal_Int32 Floor (const double nValue); + static sal_Int32 Ceil (const double nValue); + + /** Return the bounding box with integer coordinates of the given + rectangle. Note that due to different rounding of the left/top and + the right/bottom border the width of the resulting rectangle may + differ for different positions but constant width and height. + */ + static css::awt::Rectangle ConvertRectangle ( + const css::geometry::RealRectangle2D& rBox); + + /** Convert the given rectangle to integer coordinates so that width and + height remain constant when only the position changes. + */ + static css::awt::Rectangle ConvertRectangleWithConstantSize ( + const css::geometry::RealRectangle2D& rBox); + + static css::geometry::RealRectangle2D ConvertRectangle ( + const css::awt::Rectangle& rBox); + + // static css::awt::Size ConvertSize ( + // const css::geometry::RealSize2D& rSize); + + static css::awt::Rectangle TranslateRectangle ( + const css::awt::Rectangle& rBox, + const sal_Int32 nXOffset, + const sal_Int32 nYOffset); + + static css::awt::Rectangle Intersection ( + const css::awt::Rectangle& rBox1, + const css::awt::Rectangle& rBox2); + + static css::geometry::RealRectangle2D Intersection ( + const css::geometry::RealRectangle2D& rBox1, + const css::geometry::RealRectangle2D& rBox2); + + static bool IsInside ( + const css::geometry::RealRectangle2D& rBox, + const css::geometry::RealPoint2D& rPoint); + + /** Return whether rBox1 is completly inside rBox2. + */ + static bool IsInside ( + const css::awt::Rectangle& rBox1, + const css::awt::Rectangle& rBox2); + + static css::awt::Rectangle Union ( + const css::awt::Rectangle& rBox1, + const css::awt::Rectangle& rBox2); + + static css::geometry::RealRectangle2D Union ( + const css::geometry::RealRectangle2D& rBox1, + const css::geometry::RealRectangle2D& rBox2); + + static bool AreRectanglesDisjoint ( + const css::awt::Rectangle& rBox1, + const css::awt::Rectangle& rBox2); + + static css::uno::Reference<css::rendering::XPolyPolygon2D> CreatePolygon( + const css::awt::Rectangle& rBox, + const css::uno::Reference<css::rendering::XGraphicDevice>& rxDevice); + + static css::uno::Reference<css::rendering::XPolyPolygon2D> CreatePolygon( + const css::geometry::RealRectangle2D& rBox, + const css::uno::Reference<css::rendering::XGraphicDevice>& rxDevice); + + static css::uno::Reference<css::rendering::XPolyPolygon2D> CreatePolygon( + const ::std::vector<css::awt::Rectangle>& rBoxes, + const css::uno::Reference<css::rendering::XGraphicDevice>& rxDevice); + + /** Create a polygon for a rounded rectangle. + */ + /* static css::uno::Reference<css::rendering::XPolyPolygon2D> CreatePolygon( + const css::awt::Rectangle& rBox, + const double nRadius, + const css::uno::Reference<css::rendering::XGraphicDevice>& + rxDevice); + */ +}; + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterHelpView.cxx b/sdext/source/presenter/PresenterHelpView.cxx new file mode 100644 index 000000000000..d8e3a6c0ac5c --- /dev/null +++ b/sdext/source/presenter/PresenterHelpView.cxx @@ -0,0 +1,825 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterHelpView.hxx" +#include "PresenterButton.hxx" +#include "PresenterCanvasHelper.hxx" +#include "PresenterGeometryHelper.hxx" +#include "PresenterHelper.hxx" +#include "PresenterWindowManager.hxx" +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/drawing/framework/XConfigurationController.hpp> +#include <com/sun/star/drawing/framework/XControllerManager.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/TextDirection.hpp> +#include <com/sun/star/util/Color.hpp> +#include <algorithm> +#include <vector> +#include <boost/bind.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; +using ::std::vector; + +#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) + + +namespace sdext { namespace presenter { + +namespace { + const static sal_Int32 gnHorizontalGap (20); + const static sal_Int32 gnVerticalBorder (30); + const static sal_Int32 gnVerticalButtonPadding (12); + + class LineDescriptor + { + public: + LineDescriptor(void); + void AddPart ( + const OUString& rsLine, + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont); + bool IsEmpty (void) const; + + OUString msLine; + geometry::RealSize2D maSize; + double mnVerticalOffset; + + void CalculateSize (const css::uno::Reference<css::rendering::XCanvasFont>& rxFont); + }; + + class LineDescriptorList + { + public: + LineDescriptorList ( + const OUString& rsText, + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, + const sal_Int32 nMaximalWidth); + + void Update ( + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, + const sal_Int32 nMaximalWidth); + + double Paint( + const Reference<rendering::XCanvas>& rxCanvas, + const geometry::RealRectangle2D& rBBox, + const bool bFlushLeft, + const rendering::ViewState& rViewState, + rendering::RenderState& rRenderState, + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) const; + double GetHeight (void) const; + + private: + const OUString msText; + ::boost::shared_ptr<vector<LineDescriptor> > mpLineDescriptors; + + void SplitText (const ::rtl::OUString& rsText, vector<rtl::OUString>& rTextParts); + void FormatText ( + const vector<rtl::OUString>& rTextParts, + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, + const sal_Int32 nMaximalWidth); + }; + + class Block + { + public: + Block (const Block& rBlock); + Block ( + const OUString& rsLeftText, + const OUString& rsRightText, + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, + const sal_Int32 nMaximalWidth); + void Update ( + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, + const sal_Int32 nMaximalWidth); + + LineDescriptorList maLeft; + LineDescriptorList maRight; + }; +} // end of anonymous namespace + +class PresenterHelpView::TextContainer : public vector<boost::shared_ptr<Block> > +{ +}; + + +PresenterHelpView::PresenterHelpView ( + const Reference<uno::XComponentContext>& rxContext, + const Reference<XResourceId>& rxViewId, + const Reference<frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterHelpViewInterfaceBase(m_aMutex), + mxComponentContext(rxContext), + mxViewId(rxViewId), + mxPane(), + mxWindow(), + mxCanvas(), + mpPresenterController(rpPresenterController), + mpFont(), + mpTextContainer(), + mpCloseButton(), + mnSeparatorY(0), + mnMaximalWidth(0) +{ + try + { + // Get the content window via the pane anchor. + Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW); + Reference<XConfigurationController> xCC ( + xCM->getConfigurationController(), UNO_QUERY_THROW); + mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW); + + mxWindow = mxPane->getWindow(); + ProvideCanvas(); + + 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.is()) + { + mpFont = mpPresenterController->GetViewFont(mxViewId->getResourceURL()); + if (mpFont.get() != NULL) + { + mpFont->PrepareFont(mxCanvas); + } + } + + // Create the close button. + mpCloseButton = PresenterButton::Create( + mxComponentContext, + mpPresenterController, + mpPresenterController->GetTheme(), + mxWindow, + mxCanvas, + A2S("HelpViewCloser")); + + ReadHelpStrings(); + Resize(); + } + catch (RuntimeException&) + { + mxViewId = NULL; + mxWindow = NULL; + throw; + } +} + + + + +PresenterHelpView::~PresenterHelpView (void) +{ +} + + + + +void SAL_CALL PresenterHelpView::disposing (void) +{ + mxViewId = NULL; + + if (mpCloseButton.is()) + { + Reference<lang::XComponent> xComponent ( + static_cast<XWeak*>(mpCloseButton.get()), UNO_QUERY); + mpCloseButton = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + + if (mxWindow.is()) + { + mxWindow->removeWindowListener(this); + mxWindow->removePaintListener(this); + } +} + + + + +//----- lang::XEventListener -------------------------------------------------- + +void SAL_CALL PresenterHelpView::disposing (const lang::EventObject& rEventObject) + throw (RuntimeException) +{ + if (rEventObject.Source == mxCanvas) + { + mxCanvas = NULL; + } + else if (rEventObject.Source == mxWindow) + { + mxWindow = NULL; + dispose(); + } +} + + + + +//----- XWindowListener ------------------------------------------------------- + +void SAL_CALL PresenterHelpView::windowResized (const awt::WindowEvent& rEvent) + throw (uno::RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); + Resize(); +} + + + + +void SAL_CALL PresenterHelpView::windowMoved (const awt::WindowEvent& rEvent) + throw (uno::RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); +} + + + + +void SAL_CALL PresenterHelpView::windowShown (const lang::EventObject& rEvent) + throw (uno::RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); + Resize(); +} + + + + +void SAL_CALL PresenterHelpView::windowHidden (const lang::EventObject& rEvent) + throw (uno::RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); +} + + + + +//----- XPaintListener -------------------------------------------------------- + +void SAL_CALL PresenterHelpView::windowPaint (const css::awt::PaintEvent& rEvent) + throw (RuntimeException) +{ + Paint(rEvent.UpdateRect); +} + + + + +void PresenterHelpView::Paint (const awt::Rectangle& rUpdateBox) +{ + ProvideCanvas(); + if ( ! mxCanvas.is()) + return; + + // Clear background. + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + mpPresenterController->GetCanvasHelper()->Paint( + mpPresenterController->GetViewBackground(mxViewId->getResourceURL()), + Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY), + rUpdateBox, + awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height), + awt::Rectangle()); + + // Paint vertical divider. + + rendering::ViewState aViewState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + PresenterGeometryHelper::CreatePolygon(rUpdateBox, mxCanvas->getDevice())); + + rendering::RenderState aRenderState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor); + + mxCanvas->drawLine( + geometry::RealPoint2D(aWindowBox.Width/2, gnVerticalBorder), + geometry::RealPoint2D(aWindowBox.Width/2, mnSeparatorY - gnVerticalBorder), + aViewState, + aRenderState); + + // Paint the horizontal separator. + mxCanvas->drawLine( + geometry::RealPoint2D(0, mnSeparatorY), + geometry::RealPoint2D(aWindowBox.Width, mnSeparatorY), + aViewState, + aRenderState); + + // Paint text. + double nY (gnVerticalBorder); + TextContainer::const_iterator iBlock (mpTextContainer->begin()); + TextContainer::const_iterator iBlockEnd (mpTextContainer->end()); + for ( ; iBlock!=iBlockEnd; ++iBlock) + { + const double nLeftHeight ( + (*iBlock)->maLeft.Paint(mxCanvas, + geometry::RealRectangle2D( + gnHorizontalGap, + nY, + aWindowBox.Width/2 - gnHorizontalGap, + aWindowBox.Height - gnVerticalBorder), + false, + aViewState, + aRenderState, + mpFont->mxFont)); + const double nRightHeight ( + (*iBlock)->maRight.Paint(mxCanvas, + geometry::RealRectangle2D( + aWindowBox.Width/2 + gnHorizontalGap, + nY, + aWindowBox.Width - gnHorizontalGap, + aWindowBox.Height - gnVerticalBorder), + true, + aViewState, + aRenderState, + mpFont->mxFont)); + nY += ::std::max(nLeftHeight,nRightHeight); + } + + Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); + if (xSpriteCanvas.is()) + xSpriteCanvas->updateScreen(sal_False); +} + + + + +void PresenterHelpView::ReadHelpStrings (void) +{ + mpTextContainer.reset(new TextContainer()); + PresenterConfigurationAccess aConfiguration ( + mxComponentContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.extension.PresenterScreen/")), + PresenterConfigurationAccess::READ_ONLY); + Reference<container::XNameAccess> xStrings ( + aConfiguration.GetConfigurationNode(A2S("PresenterScreenSettings/HelpView/HelpStrings")), + UNO_QUERY); + PresenterConfigurationAccess::ForAll( + xStrings, + ::boost::bind(&PresenterHelpView::ProcessString, this, _2)); +} + + + + +void PresenterHelpView::ProcessString ( + const Reference<beans::XPropertySet>& rsProperties) +{ + if ( ! rsProperties.is()) + return; + + OUString sLeftText; + PresenterConfigurationAccess::GetProperty(rsProperties, A2S("Left")) >>= sLeftText; + OUString sRightText; + PresenterConfigurationAccess::GetProperty(rsProperties, A2S("Right")) >>= sRightText; + + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + mpTextContainer->push_back( + ::boost::shared_ptr<Block>( + new Block(sLeftText, sRightText, mpFont->mxFont, mnMaximalWidth))); +} + + + + +void PresenterHelpView::CheckFontSize (void) +{ + if (mpFont.get() == NULL) + return; + + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + if (aWindowBox.Width<=0 || aWindowBox.Height<=0) + return; + + sal_Int32 nBestSize (6); + + // Scaling down and then reformatting can cause the text to be too large + // still. So do this again and again until the text size is + // small enough. Restrict the number of loops. + for (int nLoopCount=0; nLoopCount<5; ++nLoopCount) + { + double nY (gnVerticalBorder); + TextContainer::iterator iBlock (mpTextContainer->begin()); + TextContainer::const_iterator iBlockEnd (mpTextContainer->end()); + for ( ; iBlock!=iBlockEnd; ++iBlock) + nY += ::std::max( + (*iBlock)->maLeft.GetHeight(), + (*iBlock)->maRight.GetHeight()); + + const double nHeightDifference (nY - (aWindowBox.Height-gnVerticalBorder)); + if (nHeightDifference <= 0 && nHeightDifference > -50) + { + // We have found a good font size that is large and leaves not + // too much space below the help text. + return; + } + + // Font is too large. Make it smaller. + + // Use a simple linear transformation to calculate initial guess of + // a size that lets all help text be shown inside the window. + const double nScale (double(aWindowBox.Height-gnVerticalBorder) / nY); + if (nScale > 0.95 && nScale <1.05) + break; + + sal_Int32 nFontSizeGuess (::std::max(sal_Int32(1),sal_Int32(mpFont->mnSize * nScale))); + if (nHeightDifference<0 && mpFont->mnSize>nBestSize) + nBestSize = mpFont->mnSize; + mpFont->mnSize = nFontSizeGuess; + mpFont->mxFont = NULL; + mpFont->PrepareFont(mxCanvas); + + // Reformat blocks. + for (iBlock=mpTextContainer->begin(); iBlock!=iBlockEnd; ++iBlock) + (*iBlock)->Update(mpFont->mxFont, mnMaximalWidth); + } + + if (nBestSize != mpFont->mnSize) + { + mpFont->mnSize = nBestSize; + mpFont->mxFont = NULL; + mpFont->PrepareFont(mxCanvas); + + // Reformat blocks. + for (TextContainer::iterator + iBlock (mpTextContainer->begin()), + iEnd (mpTextContainer->end()); + iBlock!=iEnd; + ++iBlock) + { + (*iBlock)->Update(mpFont->mxFont, mnMaximalWidth); + } + } +} + + + + +//----- XResourceId ----------------------------------------------------------- + +Reference<XResourceId> SAL_CALL PresenterHelpView::getResourceId (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + return mxViewId; +} + + + + +sal_Bool SAL_CALL PresenterHelpView::isAnchorOnly (void) + throw (RuntimeException) +{ + return false; +} + + + + +//----------------------------------------------------------------------------- + +void PresenterHelpView::ProvideCanvas (void) +{ + if ( ! mxCanvas.is() && mxPane.is()) + { + mxCanvas = mxPane->getCanvas(); + if ( ! mxCanvas.is()) + return; + Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY); + if (xComponent.is()) + xComponent->addEventListener(static_cast<awt::XPaintListener*>(this)); + + if (mpCloseButton.is()) + mpCloseButton->SetCanvas(mxCanvas, mxWindow); + } +} + + + + +void PresenterHelpView::Resize (void) +{ + if (mpCloseButton.get() != NULL && mxWindow.is()) + { + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + mnMaximalWidth = (mxWindow->getPosSize().Width - 4*gnHorizontalGap) / 2; + + // Place vertical separator. + mnSeparatorY = aWindowBox.Height + - mpCloseButton->GetSize().Height - gnVerticalButtonPadding; + + mpCloseButton->SetCenter(geometry::RealPoint2D( + aWindowBox.Width/2, + aWindowBox.Height - mpCloseButton->GetSize().Height/2)); + + CheckFontSize(); + } +} + + + + +void PresenterHelpView::ThrowIfDisposed (void) + throw (lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterHelpView has been already disposed")), + const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + } +} + + + + +//===== LineDescritor ========================================================= + +namespace { + +LineDescriptor::LineDescriptor (void) + : msLine(), + maSize(0,0), + mnVerticalOffset(0) +{ +} + + + + +void LineDescriptor::AddPart ( + const OUString& rsLine, + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) +{ + msLine += rsLine; + + CalculateSize(rxFont); +} + + + + +bool LineDescriptor::IsEmpty (void) const +{ + return msLine.getLength()==0; +} + + + + +void LineDescriptor::CalculateSize ( + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) +{ + OSL_ASSERT(rxFont.is()); + + rendering::StringContext aContext (msLine, 0, msLine.getLength()); + Reference<rendering::XTextLayout> xLayout ( + rxFont->createTextLayout(aContext, rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0)); + const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds()); + maSize = css::geometry::RealSize2D(aTextBBox.X2 - aTextBBox.X1, aTextBBox.Y2 - aTextBBox.Y1); + mnVerticalOffset = aTextBBox.Y2; +} + +} // end of anonymous namespace + + + + +//===== LineDescriptorList ==================================================== + +namespace { + +LineDescriptorList::LineDescriptorList ( + const OUString& rsText, + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, + const sal_Int32 nMaximalWidth) + : msText(rsText) +{ + Update(rxFont, nMaximalWidth); +} + + + + +double LineDescriptorList::Paint( + const Reference<rendering::XCanvas>& rxCanvas, + const geometry::RealRectangle2D& rBBox, + const bool bFlushLeft, + const rendering::ViewState& rViewState, + rendering::RenderState& rRenderState, + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) const +{ + if ( ! rxCanvas.is()) + return 0; + + double nY (rBBox.Y1); + vector<LineDescriptor>::const_iterator iLine (mpLineDescriptors->begin()); + vector<LineDescriptor>::const_iterator iEnd (mpLineDescriptors->end()); + for ( ; iLine!=iEnd; ++iLine) + { + double nX (rBBox.X1); + if ( ! bFlushLeft) + nX = rBBox.X2 - iLine->maSize.Width; + rRenderState.AffineTransform.m02 = nX; + rRenderState.AffineTransform.m12 = nY + iLine->maSize.Height - iLine->mnVerticalOffset; + + const rendering::StringContext aContext (iLine->msLine, 0, iLine->msLine.getLength()); + + rxCanvas->drawText ( + aContext, + rxFont, + rViewState, + rRenderState, + rendering::TextDirection::WEAK_LEFT_TO_RIGHT); + + nY += iLine->maSize.Height * 1.2; + } + + return nY - rBBox.Y1; +} + + + + +double LineDescriptorList::GetHeight (void) const +{ + double nHeight (0); + vector<LineDescriptor>::const_iterator iLine (mpLineDescriptors->begin()); + vector<LineDescriptor>::const_iterator iEnd (mpLineDescriptors->end()); + for ( ; iLine!=iEnd; ++iLine) + nHeight += iLine->maSize.Height * 1.2; + + return nHeight; +} + + + + +void LineDescriptorList::Update ( + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, + const sal_Int32 nMaximalWidth) +{ + vector<OUString> aTextParts; + SplitText(msText, aTextParts); + FormatText(aTextParts, rxFont, nMaximalWidth); +} + + + + +void LineDescriptorList::SplitText ( + const OUString& rsText, + vector<OUString>& rTextParts) +{ + const sal_Char cQuote ('\''); + const sal_Char cSeparator (','); + + sal_Int32 nIndex (0); + sal_Int32 nStart (0); + sal_Int32 nLength (rsText.getLength()); + bool bIsQuoted (false); + while (nIndex < nLength) + { + const sal_Int32 nQuoteIndex (rsText.indexOf(cQuote, nIndex)); + const sal_Int32 nSeparatorIndex (rsText.indexOf(cSeparator, nIndex)); + if (nQuoteIndex>=0 && (nSeparatorIndex==-1 || nQuoteIndex<nSeparatorIndex)) + { + bIsQuoted = !bIsQuoted; + nIndex = nQuoteIndex+1; + continue; + } + + const sal_Int32 nNextIndex = nSeparatorIndex; + if (nNextIndex < 0) + { + break; + } + else if ( ! bIsQuoted) + { + rTextParts.push_back(rsText.copy(nStart, nNextIndex-nStart)); + nStart = nNextIndex + 1; + } + nIndex = nNextIndex+1; + } + if (nStart < nLength) + rTextParts.push_back(rsText.copy(nStart, nLength-nStart)); +} + + + + +void LineDescriptorList::FormatText ( + const vector<OUString>& rTextParts, + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, + const sal_Int32 nMaximalWidth) +{ + LineDescriptor aLineDescriptor; + + mpLineDescriptors.reset(new vector<LineDescriptor>()); + + vector<OUString>::const_iterator iPart (rTextParts.begin()); + vector<OUString>::const_iterator iEnd (rTextParts.end()); + for ( ; iPart!=iEnd; ++iPart) + { + if (aLineDescriptor.IsEmpty()) + { + // Avoid empty lines. + aLineDescriptor.AddPart(*iPart, rxFont); + } + else if (PresenterCanvasHelper::GetTextSize( + rxFont, aLineDescriptor.msLine+A2S(", ")+*iPart).Width > nMaximalWidth) + { + aLineDescriptor.AddPart(A2S(","), rxFont); + mpLineDescriptors->push_back(aLineDescriptor); + aLineDescriptor = LineDescriptor(); + aLineDescriptor.AddPart(*iPart, rxFont); + } + else + { + aLineDescriptor.AddPart(A2S(", ")+*iPart, rxFont); + } + } + if ( ! aLineDescriptor.IsEmpty()) + { + mpLineDescriptors->push_back(aLineDescriptor); + } +} + + +} // end of anonymous namespace + + + + +//===== Block ================================================================= + +namespace { + +Block::Block ( + const OUString& rsLeftText, + const OUString& rsRightText, + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, + const sal_Int32 nMaximalWidth) + : maLeft(rsLeftText, rxFont, nMaximalWidth), + maRight(rsRightText, rxFont, nMaximalWidth) +{ +} + + + +void Block::Update ( + const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, + const sal_Int32 nMaximalWidth) +{ + maLeft.Update(rxFont, nMaximalWidth); + maRight.Update(rxFont, nMaximalWidth); +} + +} // end of anonymous namespace + +} } // end of namespace ::sdext::presenter + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterHelpView.hxx b/sdext/source/presenter/PresenterHelpView.hxx new file mode 100644 index 000000000000..2d5e0efdcfc2 --- /dev/null +++ b/sdext/source/presenter/PresenterHelpView.hxx @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_HELP_VIEW_HXX +#define SDEXT_PRESENTER_HELP_VIEW_HXX + +#include "PresenterController.hxx" +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase3.hxx> +#include <com/sun/star/awt/XPaintListener.hpp> +#include <com/sun/star/awt/XWindowListener.hpp> +#include <com/sun/star/drawing/framework/XView.hpp> +#include <com/sun/star/drawing/framework/XResourceId.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/rendering/XSpriteCanvas.hpp> + +namespace css = ::com::sun::star; + +namespace { + typedef cppu::WeakComponentImplHelper3< + css::drawing::framework::XView, + css::awt::XWindowListener, + css::awt::XPaintListener + > PresenterHelpViewInterfaceBase; +} + +namespace sdext { namespace presenter { + +class PresenterButton; + +/** Show help text that describes the defined keys. +*/ +class PresenterHelpView + : private ::cppu::BaseMutex, + public PresenterHelpViewInterfaceBase +{ +public: + explicit PresenterHelpView ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId, + const css::uno::Reference<css::frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~PresenterHelpView (void); + + virtual void SAL_CALL disposing (void); + + // lang::XEventListener + + virtual void SAL_CALL + disposing (const css::lang::EventObject& rEventObject) + throw (css::uno::RuntimeException); + + + // XWindowListener + + virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // XPaintListener + + virtual void SAL_CALL windowPaint (const css::awt::PaintEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XResourceId + + virtual css::uno::Reference<css::drawing::framework::XResourceId> SAL_CALL getResourceId (void) + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isAnchorOnly (void) + throw (com::sun::star::uno::RuntimeException); + +private: + class TextContainer; + + css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + css::uno::Reference<css::drawing::framework::XResourceId> mxViewId; + css::uno::Reference<css::drawing::framework::XPane> mxPane; + css::uno::Reference<css::awt::XWindow> mxWindow; + css::uno::Reference<css::rendering::XCanvas> mxCanvas; + ::rtl::Reference<PresenterController> mpPresenterController; + PresenterTheme::SharedFontDescriptor mpFont; + ::boost::scoped_ptr<TextContainer> mpTextContainer; + ::rtl::Reference<PresenterButton> mpCloseButton; + sal_Int32 mnSeparatorY; + sal_Int32 mnMaximalWidth; + + void ProvideCanvas (void); + void Resize (void); + void Paint (const css::awt::Rectangle& rRedrawArea); + void ReadHelpStrings (void); + void ProcessString ( + const css::uno::Reference<css::beans::XPropertySet>& rsProperties); + + /** Find a font size, so that all text can be displayed at the same + time. + */ + void CheckFontSize (void); + + /** This method throws a DisposedException when the object has already been + disposed. + */ + void ThrowIfDisposed (void) + throw (css::lang::DisposedException); +}; + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterHelper.cxx b/sdext/source/presenter/PresenterHelper.cxx new file mode 100644 index 000000000000..13338aefb212 --- /dev/null +++ b/sdext/source/presenter/PresenterHelper.cxx @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterHelper.hxx" + +#include <com/sun/star/graphic/XGraphicProvider.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/presentation/XPresentationSupplier.hpp> +#include <com/sun/star/presentation/XPresentation2.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::presentation; +using ::rtl::OUString; + +namespace sdext { namespace presenter { + +const OUString PresenterHelper::msPaneURLPrefix( + RTL_CONSTASCII_USTRINGPARAM("private:resource/pane/")); +const OUString PresenterHelper::msCenterPaneURL( + msPaneURLPrefix + OUString(RTL_CONSTASCII_USTRINGPARAM("CenterPane"))); +const OUString PresenterHelper::msFullScreenPaneURL( + msPaneURLPrefix + OUString(RTL_CONSTASCII_USTRINGPARAM("FullScreenPane"))); + +const OUString PresenterHelper::msViewURLPrefix( + RTL_CONSTASCII_USTRINGPARAM("private:resource/view/")); +const OUString PresenterHelper::msPresenterScreenURL( + msViewURLPrefix + OUString(RTL_CONSTASCII_USTRINGPARAM("PresenterScreen"))); +const OUString PresenterHelper::msSlideSorterURL( + msViewURLPrefix + OUString(RTL_CONSTASCII_USTRINGPARAM("SlideSorter"))); + +const OUString PresenterHelper::msResourceActivationEvent( + RTL_CONSTASCII_USTRINGPARAM("ResourceActivation")); +const OUString PresenterHelper::msResourceDeactivationEvent( + RTL_CONSTASCII_USTRINGPARAM("ResourceDeactivation")); + +const OUString PresenterHelper::msDefaultPaneStyle ( + RTL_CONSTASCII_USTRINGPARAM("DefaultPaneStyle")); +const OUString PresenterHelper::msDefaultViewStyle ( + RTL_CONSTASCII_USTRINGPARAM("DefaultViewStyle")); + + +Reference<presentation::XSlideShowController> PresenterHelper::GetSlideShowController ( + const Reference<frame::XController>& rxController) +{ + Reference<presentation::XSlideShowController> xSlideShowController; + + if( rxController.is() ) try + { + Reference<XPresentationSupplier> xPS ( rxController->getModel(), UNO_QUERY_THROW); + + Reference<XPresentation2> xPresentation(xPS->getPresentation(), UNO_QUERY_THROW); + + xSlideShowController = xPresentation->getController(); + } + catch(RuntimeException&) + { + } + + return xSlideShowController; +} + + + + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterHelper.hxx b/sdext/source/presenter/PresenterHelper.hxx new file mode 100644 index 000000000000..75f4cbdd9f0c --- /dev/null +++ b/sdext/source/presenter/PresenterHelper.hxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_VIEW_HELPER_HXX +#define SDEXT_PRESENTER_VIEW_HELPER_HXX + +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/presentation/XSlideShowController.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <boost/noncopyable.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +/** Collection of helper functions that do not fit in anywhere else. + Provide access to frequently used strings of the drawing framework. +*/ +class PresenterHelper + : ::boost::noncopyable +{ +public: + static const ::rtl::OUString msPaneURLPrefix; + static const ::rtl::OUString msCenterPaneURL; + static const ::rtl::OUString msFullScreenPaneURL; + + static const ::rtl::OUString msViewURLPrefix; + static const ::rtl::OUString msPresenterScreenURL; + static const ::rtl::OUString msSlideSorterURL; + + static const ::rtl::OUString msResourceActivationEvent; + static const ::rtl::OUString msResourceDeactivationEvent; + + static const ::rtl::OUString msDefaultPaneStyle; + static const ::rtl::OUString msDefaultViewStyle; + + /** Return the slide show controller of a running presentation that has + the same document as the given framework controller. + @return + When no presentation is running this method returns an empty reference. + */ + static css::uno::Reference<css::presentation::XSlideShowController> GetSlideShowController ( + const css::uno::Reference<css::frame::XController>& rxController); + +private: + PresenterHelper (void); + ~PresenterHelper (void); +}; + +} } // end of namespace presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterNotesView.cxx b/sdext/source/presenter/PresenterNotesView.cxx new file mode 100644 index 000000000000..9cbf93543ef5 --- /dev/null +++ b/sdext/source/presenter/PresenterNotesView.cxx @@ -0,0 +1,810 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterNotesView.hxx" +#include "PresenterButton.hxx" +#include "PresenterCanvasHelper.hxx" +#include "PresenterGeometryHelper.hxx" +#include "PresenterPaintManager.hxx" +#include "PresenterScrollBar.hxx" +#include "PresenterTextView.hxx" +#include <com/sun/star/accessibility/AccessibleTextType.hpp> +#include <com/sun/star/awt/Key.hpp> +#include <com/sun/star/awt/KeyModifier.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/drawing/framework/XControllerManager.hpp> +#include <com/sun/star/drawing/framework/XConfigurationController.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/lang/XServiceName.hpp> +#include <com/sun/star/presentation/XPresentationPage.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/XSpriteCanvas.hpp> +#include <com/sun/star/text/XTextRange.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <boost/bind.hpp> +#include <set> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) + +static const sal_Int32 gnSpaceBelowSeparator (10); +static const sal_Int32 gnSpaceAboveSeparator (10); +static const sal_Int32 gnPartHeight (128); +/** Maximal size of memory used for bitmaps which show the notes text. +*/ +static const sal_Int32 gnMaximalCacheSize (8*1024*1024); +static const double gnLineScrollFactor (1.2); + +namespace sdext { namespace presenter { + +//===== PresenterNotesView ==================================================== + +PresenterNotesView::PresenterNotesView ( + const Reference<XComponentContext>& rxComponentContext, + const Reference<XResourceId>& rxViewId, + const Reference<frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterNotesViewInterfaceBase(m_aMutex), + mxViewId(rxViewId), + mpPresenterController(rpPresenterController), + mxCanvas(), + mxCurrentNotesPage(), + mpScrollBar(), + mxToolBarWindow(), + mxToolBarCanvas(), + mpToolBar(), + mpCloseButton(), + maSeparatorColor(0xffffff), + mnSeparatorYLocation(0), + maTextBoundingBox(), + mpBackground(), + mnTop(0), + mpFont(), + mpTextView() +{ + try + { + Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW); + Reference<XConfigurationController> xCC (xCM->getConfigurationController(), UNO_QUERY_THROW); + Reference<XPane> xPane (xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW); + + mxParentWindow = xPane->getWindow(); + mxCanvas = xPane->getCanvas(); + mpTextView.reset(new PresenterTextView( + rxComponentContext, + mxCanvas, + mpPresenterController->GetPaintManager()->GetInvalidator(mxParentWindow))); + + const OUString sResourceURL (mxViewId->getResourceURL()); + mpFont.reset(new PresenterTheme::FontDescriptor( + rpPresenterController->GetViewFont(sResourceURL))); + maSeparatorColor = mpFont->mnColor; + mpTextView->SetFont(mpFont); + + CreateToolBar(rxComponentContext, rpPresenterController); + + mpCloseButton = PresenterButton::Create( + rxComponentContext, + mpPresenterController, + mpPresenterController->GetTheme(), + mxParentWindow, + mxCanvas, + A2S("NotesViewCloser")); + + if (mxParentWindow.is()) + { + mxParentWindow->addWindowListener(this); + mxParentWindow->addPaintListener(this); + mxParentWindow->addKeyListener(this); + mxParentWindow->setVisible(sal_True); + } + + mpScrollBar = new PresenterVerticalScrollBar( + rxComponentContext, + mxParentWindow, + mpPresenterController->GetPaintManager(), + ::boost::bind(&PresenterNotesView::SetTop, this, _1)); + mpScrollBar->SetBackground( + mpPresenterController->GetViewBackground(mxViewId->getResourceURL())); + + mpScrollBar->SetCanvas(mxCanvas); + + Layout(); + } + catch (RuntimeException&) + { + PresenterNotesView::disposing(); + throw; + } +} + + + + +PresenterNotesView::~PresenterNotesView (void) +{ +} + + + + +void SAL_CALL PresenterNotesView::disposing (void) +{ + if (mxParentWindow.is()) + { + mxParentWindow->removeWindowListener(this); + mxParentWindow->removePaintListener(this); + mxParentWindow->removeKeyListener(this); + mxParentWindow = NULL; + } + + // Dispose tool bar. + { + Reference<XComponent> xComponent (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY); + mpToolBar = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + { + Reference<XComponent> xComponent (mxToolBarCanvas, UNO_QUERY); + mxToolBarCanvas = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + { + Reference<XComponent> xComponent (mxToolBarWindow, UNO_QUERY); + mxToolBarWindow = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + + // Dispose close button + { + Reference<XComponent> xComponent (static_cast<XWeak*>(mpCloseButton.get()), UNO_QUERY); + mpCloseButton = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + + // Create the tool bar. + + mpScrollBar = NULL; + + mxViewId = NULL; +} + + + + +void PresenterNotesView::CreateToolBar ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const ::rtl::Reference<PresenterController>& rpPresenterController) +{ + if (rpPresenterController.get() == NULL) + return; + + Reference<drawing::XPresenterHelper> xPresenterHelper ( + rpPresenterController->GetPresenterHelper()); + if ( ! xPresenterHelper.is()) + return; + + // Create a new window as container of the tool bar. + mxToolBarWindow = xPresenterHelper->createWindow( + mxParentWindow, + sal_False, + sal_True, + sal_False, + sal_False); + mxToolBarCanvas = xPresenterHelper->createSharedCanvas ( + Reference<rendering::XSpriteCanvas>(mxCanvas, UNO_QUERY), + mxParentWindow, + mxCanvas, + mxParentWindow, + mxToolBarWindow); + + // Create the tool bar. + mpToolBar = new PresenterToolBar( + rxContext, + mxToolBarWindow, + mxToolBarCanvas, + rpPresenterController, + PresenterToolBar::Left); + mpToolBar->Initialize( + A2S("PresenterScreenSettings/ToolBars/NotesToolBar")); +} + + + + +void PresenterNotesView::SetSlide (const Reference<drawing::XDrawPage>& rxNotesPage) +{ + static const ::rtl::OUString sNotesShapeName ( + A2S("com.sun.star.presentation.NotesShape")); + static const ::rtl::OUString sTextShapeName ( + A2S("com.sun.star.drawing.TextShape")); + + Reference<container::XIndexAccess> xIndexAccess (rxNotesPage, UNO_QUERY); + if (xIndexAccess.is()) + { + ::rtl::OUString sText; + + // Iterate over all shapes and find the one that holds the text. + sal_Int32 nCount (xIndexAccess->getCount()); + for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex) + { + + Reference<lang::XServiceName> xServiceName ( + xIndexAccess->getByIndex(nIndex), UNO_QUERY); + if (xServiceName.is() + && xServiceName->getServiceName().equals(sNotesShapeName)) + { + Reference<text::XTextRange> xText (xServiceName, UNO_QUERY); + if (xText.is()) + { + sText += xText->getString(); + } + } + else + { + Reference<drawing::XShapeDescriptor> xShapeDescriptor ( + xIndexAccess->getByIndex(nIndex), UNO_QUERY); + if (xShapeDescriptor.is()) + { + ::rtl::OUString sType (xShapeDescriptor->getShapeType()); + if (sType.equals(sNotesShapeName) || sType.equals(sTextShapeName)) + { + Reference<text::XTextRange> xText ( + xIndexAccess->getByIndex(nIndex), UNO_QUERY); + if (xText.is()) + { + sText += xText->getString(); + mpTextView->SetText(Reference<text::XText>(xText, UNO_QUERY)); + } + } + } + } + } + + Layout(); + + if (mpScrollBar.get() != NULL) + { + mpScrollBar->SetThumbPosition(0, false); + UpdateScrollBar(); + } + + Invalidate(); + } +} + + + + +//----- lang::XEventListener ------------------------------------------------- + +void SAL_CALL PresenterNotesView::disposing (const lang::EventObject& rEventObject) + throw (RuntimeException) +{ + if (rEventObject.Source == mxParentWindow) + mxParentWindow = NULL; +} + + + + +//----- XWindowListener ------------------------------------------------------- + +void SAL_CALL PresenterNotesView::windowResized (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + Layout(); +} + + + + +void SAL_CALL PresenterNotesView::windowMoved (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterNotesView::windowShown (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterNotesView::windowHidden (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; +} + + + + +//----- XPaintListener -------------------------------------------------------- + +void SAL_CALL PresenterNotesView::windowPaint (const awt::PaintEvent& rEvent) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + if ( ! mbIsPresenterViewActive) + return; + + ::osl::MutexGuard aSolarGuard (::osl::Mutex::getGlobalMutex()); + Paint(rEvent.UpdateRect); +} + + + + +//----- XResourceId ----------------------------------------------------------- + +Reference<XResourceId> SAL_CALL PresenterNotesView::getResourceId (void) + throw (RuntimeException) +{ + return mxViewId; +} + + + + +sal_Bool SAL_CALL PresenterNotesView::isAnchorOnly (void) + throw (RuntimeException) +{ + return false; +} + + + + +//----- XDrawView ------------------------------------------------------------- + +void SAL_CALL PresenterNotesView::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide) + throw (RuntimeException) +{ + // Get the associated notes page. + mxCurrentNotesPage = NULL; + try + { + Reference<presentation::XPresentationPage> xPresentationPage(rxSlide, UNO_QUERY); + if (xPresentationPage.is()) + mxCurrentNotesPage = xPresentationPage->getNotesPage(); + } + catch (RuntimeException&) + { + } + + SetSlide(mxCurrentNotesPage); +} + + + + +Reference<drawing::XDrawPage> SAL_CALL PresenterNotesView::getCurrentPage (void) + throw (RuntimeException) +{ + return NULL; +} + + + + +//----- XKeyListener ---------------------------------------------------------- + +void SAL_CALL PresenterNotesView::keyPressed (const awt::KeyEvent& rEvent) + throw (RuntimeException) +{ + switch (rEvent.KeyCode) + { + case awt::Key::A: + Scroll(-gnLineScrollFactor * mpFont->mnSize); + break; + + case awt::Key::Y: + case awt::Key::Z: + Scroll(+gnLineScrollFactor * mpFont->mnSize); + break; + + case awt::Key::S: + ChangeFontSize(-1); + break; + + case awt::Key::G: + ChangeFontSize(+1); + break; + + case awt::Key::H: + if (mpTextView) + mpTextView->MoveCaret( + -1, + (rEvent.Modifiers == awt::KeyModifier::SHIFT) + ? cssa::AccessibleTextType::CHARACTER + : cssa::AccessibleTextType::WORD); + break; + + case awt::Key::L: + if (mpTextView) + mpTextView->MoveCaret( + +1, + (rEvent.Modifiers == awt::KeyModifier::SHIFT) + ? cssa::AccessibleTextType::CHARACTER + : cssa::AccessibleTextType::WORD); + break; + } +} + + + + +void SAL_CALL PresenterNotesView::keyReleased (const awt::KeyEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; +} + + + + +//----------------------------------------------------------------------------- + +void PresenterNotesView::Layout (void) +{ + if ( ! mxParentWindow.is()) + return; + + awt::Rectangle aWindowBox (mxParentWindow->getPosSize()); + geometry::RealRectangle2D aNewTextBoundingBox (0,0,aWindowBox.Width, aWindowBox.Height); + + // Size the tool bar and the horizontal separator above it. + if (mxToolBarWindow.is()) + { + const geometry::RealSize2D aToolBarSize (mpToolBar->GetMinimalSize()); + const sal_Int32 nToolBarHeight = sal_Int32(aToolBarSize.Height + 0.5); + mxToolBarWindow->setPosSize(0, aWindowBox.Height - nToolBarHeight, + sal_Int32(aToolBarSize.Width + 0.5), nToolBarHeight, + awt::PosSize::POSSIZE); + aNewTextBoundingBox.Y2 -= nToolBarHeight; + + mnSeparatorYLocation = aWindowBox.Height - nToolBarHeight - gnSpaceBelowSeparator; + aNewTextBoundingBox.Y2 = mnSeparatorYLocation - gnSpaceAboveSeparator; + + // Place the close button. + if (mpCloseButton.get() != NULL) + mpCloseButton->SetCenter(geometry::RealPoint2D( + (aWindowBox.Width + aToolBarSize.Width) / 2, + aWindowBox.Height - aToolBarSize.Height/2)); + } + + // Check whether the vertical scroll bar is necessary. + if (mpScrollBar.get() != NULL) + { + bool bShowVerticalScrollbar (false); + try + { + const double nTextBoxHeight (aNewTextBoundingBox.Y2 - aNewTextBoundingBox.Y1); + const double nHeight (mpTextView->GetTotalTextHeight()); + if (nHeight > nTextBoxHeight) + { + bShowVerticalScrollbar = true; + aNewTextBoundingBox.X2 -= mpScrollBar->GetSize(); + } + mpScrollBar->SetTotalSize(nHeight); + } + catch(beans::UnknownPropertyException&) + { + OSL_ASSERT(false); + } + + mpScrollBar->SetVisible(bShowVerticalScrollbar); + mpScrollBar->SetPosSize( + geometry::RealRectangle2D( + aNewTextBoundingBox.X2, + aNewTextBoundingBox.X1, + aNewTextBoundingBox.X2 + mpScrollBar->GetSize(), + aNewTextBoundingBox.Y2)); + if ( ! bShowVerticalScrollbar) + mpScrollBar->SetThumbPosition(0, false); + + UpdateScrollBar(); + } + + // Has the text area has changed it position or size? + if (aNewTextBoundingBox.X1 != maTextBoundingBox.X1 + || aNewTextBoundingBox.Y1 != maTextBoundingBox.Y1 + || aNewTextBoundingBox.X2 != maTextBoundingBox.X2 + || aNewTextBoundingBox.Y2 != maTextBoundingBox.Y2) + { + maTextBoundingBox = aNewTextBoundingBox; + + mpTextView->SetLocation( + geometry::RealPoint2D( + aNewTextBoundingBox.X1, + aNewTextBoundingBox.Y1)); + mpTextView->SetSize( + geometry::RealSize2D( + aNewTextBoundingBox.X2 - aNewTextBoundingBox.X1, + aNewTextBoundingBox.Y2 - aNewTextBoundingBox.Y1)); + } +} + + + + +void PresenterNotesView::Paint (const awt::Rectangle& rUpdateBox) +{ + if ( ! mxParentWindow.is()) + return; + if ( ! mxCanvas.is()) + return; + + if (mpBackground.get() == NULL) + mpBackground = mpPresenterController->GetViewBackground(mxViewId->getResourceURL()); + + if (rUpdateBox.Y < maTextBoundingBox.Y2 + && rUpdateBox.X < maTextBoundingBox.X2) + { + PaintText(rUpdateBox); + } + + mpTextView->Paint(rUpdateBox); + + if (rUpdateBox.Y + rUpdateBox.Height > maTextBoundingBox.Y2) + { + PaintToolBar(rUpdateBox); + } +} + + + + +void PresenterNotesView::PaintToolBar (const awt::Rectangle& rUpdateBox) +{ + awt::Rectangle aWindowBox (mxParentWindow->getPosSize()); + + rendering::ViewState aViewState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL); + rendering::RenderState aRenderState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + + if (mpBackground.get() != NULL) + { + // Paint the background. + mpPresenterController->GetCanvasHelper()->Paint( + mpBackground, + mxCanvas, + rUpdateBox, + awt::Rectangle(0,sal_Int32(maTextBoundingBox.Y2),aWindowBox.Width,aWindowBox.Height), + awt::Rectangle()); + } + + // Paint the horizontal separator. + OSL_ASSERT(mxViewId.is()); + PresenterCanvasHelper::SetDeviceColor(aRenderState, maSeparatorColor); + + mxCanvas->drawLine( + geometry::RealPoint2D(0,mnSeparatorYLocation), + geometry::RealPoint2D(aWindowBox.Width,mnSeparatorYLocation), + aViewState, + aRenderState); +} + + + + +void PresenterNotesView::PaintText (const awt::Rectangle& rUpdateBox) +{ + const awt::Rectangle aBox (PresenterGeometryHelper::Intersection(rUpdateBox, + PresenterGeometryHelper::ConvertRectangle(maTextBoundingBox))); + + if (aBox.Width <= 0 || aBox.Height <= 0) + return; + + rendering::ViewState aViewState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + PresenterGeometryHelper::CreatePolygon(aBox, mxCanvas->getDevice())); + rendering::RenderState aRenderState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(3), + rendering::CompositeOperation::SOURCE); + + if (mpBackground.get() != NULL) + { + // Paint the background. + mpPresenterController->GetCanvasHelper()->Paint( + mpBackground, + mxCanvas, + rUpdateBox, + aBox, + awt::Rectangle()); + } + + Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); + if (xSpriteCanvas.is()) + xSpriteCanvas->updateScreen(sal_False); +} + + + + +void PresenterNotesView::Invalidate (void) +{ + mpPresenterController->GetPaintManager()->Invalidate( + mxParentWindow, + PresenterGeometryHelper::ConvertRectangle(maTextBoundingBox)); +} + + + + +void PresenterNotesView::Scroll (const double rnDistance) +{ + try + { + mnTop += rnDistance; + mpTextView->SetOffset(0, mnTop); + + UpdateScrollBar(); + Invalidate(); + } + catch (beans::UnknownPropertyException&) + {} +} + + + + +void PresenterNotesView::SetTop (const double nTop) +{ + try + { + mnTop = nTop; + mpTextView->SetOffset(0, mnTop); + + UpdateScrollBar(); + Invalidate(); + } + catch (beans::UnknownPropertyException&) + {} +} + + + + +void PresenterNotesView::ChangeFontSize (const sal_Int32 nSizeChange) +{ + const sal_Int32 nNewSize (mpFont->mnSize + nSizeChange); + if (nNewSize > 5) + { + mpFont->mnSize = nNewSize; + mpFont->mxFont = NULL; + mpTextView->SetFont(mpFont); + + Layout(); + UpdateScrollBar(); + Invalidate(); + + // Write the new font size to the configuration to make it persistent. + try + { + const OUString sStyleName (mpPresenterController->GetTheme()->GetStyleName( + mxViewId->getResourceURL())); + ::boost::shared_ptr<PresenterConfigurationAccess> pConfiguration ( + mpPresenterController->GetTheme()->GetNodeForViewStyle( + sStyleName, + PresenterConfigurationAccess::READ_WRITE)); + if (pConfiguration.get()==NULL || ! pConfiguration->IsValid()) + return; + + pConfiguration->GoToChild(A2S("Font")); + pConfiguration->SetProperty(A2S("Size"), Any((sal_Int32)(nNewSize+0.5))); + pConfiguration->CommitChanges(); + } + catch (Exception&) + { + OSL_ASSERT(false); + } + } +} + + + + +::boost::shared_ptr<PresenterTextView> PresenterNotesView::GetTextView (void) const +{ + return mpTextView; +} + + + + +void PresenterNotesView::UpdateScrollBar (void) +{ + if (mpScrollBar.get() != NULL) + { + try + { + mpScrollBar->SetTotalSize(mpTextView->GetTotalTextHeight()); + } + catch(beans::UnknownPropertyException&) + { + OSL_ASSERT(false); + } + + mpScrollBar->SetLineHeight(mpFont->mnSize*1.2); + mpScrollBar->SetThumbPosition(mnTop, false); + + mpScrollBar->SetThumbSize(maTextBoundingBox.Y2 - maTextBoundingBox.Y1); + mpScrollBar->CheckValues(); + } +} + + + + +void PresenterNotesView::ThrowIfDisposed (void) + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + A2S("PresenterNotesView object has already been disposed"), + static_cast<uno::XWeak*>(this)); + } +} + + + + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterNotesView.hxx b/sdext/source/presenter/PresenterNotesView.hxx new file mode 100644 index 000000000000..282f86465dc6 --- /dev/null +++ b/sdext/source/presenter/PresenterNotesView.hxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_NOTES_VIEW2_HXX +#define SDEXT_PRESENTER_NOTES_VIEW2_HXX + +#include "PresenterController.hxx" +#include "PresenterToolBar.hxx" +#include "PresenterViewFactory.hxx" +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase5.hxx> +#include <com/sun/star/awt/ActionEvent.hpp> +#include <com/sun/star/awt/XActionListener.hpp> +#include <com/sun/star/awt/XButton.hpp> +#include <com/sun/star/awt/XControl.hpp> +#include <com/sun/star/awt/XTextComponent.hpp> +#include <com/sun/star/awt/XWindowListener.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/XDrawView.hpp> +#include <com/sun/star/drawing/framework/XView.hpp> +#include <com/sun/star/drawing/framework/XResourceId.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <rtl/ref.hxx> +#include <boost/shared_ptr.hpp> + +namespace css = ::com::sun::star; + +namespace { + typedef cppu::WeakComponentImplHelper5< + css::awt::XWindowListener, + css::awt::XPaintListener, + css::drawing::framework::XView, + css::drawing::XDrawView, + css::awt::XKeyListener + > PresenterNotesViewInterfaceBase; +} + +namespace sdext { namespace presenter { + +class PresenterButton; +class PresenterScrollBar; +class PresenterTextView; + + +/** A drawing framework view of the notes of a slide. At the moment this is + a simple text view that does not show the original formatting of the + notes text. +*/ +class PresenterNotesView + : private ::cppu::BaseMutex, + public PresenterNotesViewInterfaceBase, + public CachablePresenterView +{ +public: + explicit PresenterNotesView ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId, + const css::uno::Reference<css::frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~PresenterNotesView (void); + + virtual void SAL_CALL disposing (void); + + /** Typically called from setCurrentSlide() with the notes page that is + associed with the slide given to setCurrentSlide(). + + Iterates over all text shapes on the given notes page and diplays + the concatenated text of these. + */ + void SetSlide ( + const css::uno::Reference<css::drawing::XDrawPage>& rxNotesPage); + + void ChangeFontSize (const sal_Int32 nSizeChange); + + ::boost::shared_ptr<PresenterTextView> GetTextView (void) const; + + + // lang::XEventListener + + virtual void SAL_CALL + disposing (const css::lang::EventObject& rEventObject) + throw (css::uno::RuntimeException); + + + // XWindowListener + + virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // XPaintListener + + virtual void SAL_CALL windowPaint (const css::awt::PaintEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XResourceId + + virtual css::uno::Reference<css::drawing::framework::XResourceId> SAL_CALL getResourceId (void) + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isAnchorOnly (void) + throw (com::sun::star::uno::RuntimeException); + + + // XDrawView + + virtual void SAL_CALL setCurrentPage ( + const css::uno::Reference<css::drawing::XDrawPage>& rxSlide) + throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::drawing::XDrawPage> SAL_CALL getCurrentPage (void) + throw (css::uno::RuntimeException); + + + // XKeyListener + + virtual void SAL_CALL keyPressed (const css::awt::KeyEvent& rEvent) + throw (css::uno::RuntimeException); + virtual void SAL_CALL keyReleased (const css::awt::KeyEvent& rEvent) + throw (css::uno::RuntimeException); + +private: + css::uno::Reference<css::drawing::framework::XResourceId> mxViewId; + ::rtl::Reference<PresenterController> mpPresenterController; + css::uno::Reference<css::awt::XWindow> mxParentWindow; + css::uno::Reference<css::rendering::XCanvas> mxCanvas; + css::uno::Reference<css::drawing::XDrawPage> mxCurrentNotesPage; + ::rtl::Reference<PresenterScrollBar> mpScrollBar; + css::uno::Reference<css::awt::XWindow> mxToolBarWindow; + css::uno::Reference<css::rendering::XCanvas> mxToolBarCanvas; + ::rtl::Reference<PresenterToolBar> mpToolBar; + ::rtl::Reference<PresenterButton> mpCloseButton; + css::util::Color maSeparatorColor; + sal_Int32 mnSeparatorYLocation; + css::geometry::RealRectangle2D maTextBoundingBox; + SharedBitmapDescriptor mpBackground; + double mnTop; + PresenterTheme::SharedFontDescriptor mpFont; + ::boost::shared_ptr<PresenterTextView> mpTextView; + + void CreateToolBar ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const ::rtl::Reference<PresenterController>& rpPresenterController); + void Layout (void); + void Paint (const css::awt::Rectangle& rUpdateBox); + void PaintToolBar (const css::awt::Rectangle& rUpdateBox); + void PaintText (const css::awt::Rectangle& rUpdateBox); + void Invalidate (void); + void Scroll (const double nDistance); + void SetTop (const double nTop); + void UpdateScrollBar (void); + void MoveCaret (const sal_Int32 nDistance); + + /** This method throws a DisposedException when the object has already been + disposed. + */ + void ThrowIfDisposed (void) + throw (css::lang::DisposedException); +}; + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPaintManager.cxx b/sdext/source/presenter/PresenterPaintManager.cxx new file mode 100644 index 000000000000..e934130d9ec2 --- /dev/null +++ b/sdext/source/presenter/PresenterPaintManager.cxx @@ -0,0 +1,178 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterPaintManager.hxx" + +#include "PresenterPaneContainer.hxx" +#include <com/sun/star/awt/InvalidateStyle.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <boost/bind.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace sdext { namespace presenter { + +PresenterPaintManager::PresenterPaintManager ( + const css::uno::Reference<css::awt::XWindow>& rxParentWindow, + const css::uno::Reference<css::drawing::XPresenterHelper>& rxPresenterHelper, + const rtl::Reference<PresenterPaneContainer>& rpPaneContainer) + : mxParentWindow(rxParentWindow), + mxParentWindowPeer(rxParentWindow, UNO_QUERY), + mxPresenterHelper(rxPresenterHelper), + mpPaneContainer(rpPaneContainer) +{ +} + + + + +::boost::function<void(const css::awt::Rectangle& rRepaintBox)> + PresenterPaintManager::GetInvalidator ( + const css::uno::Reference<css::awt::XWindow>& rxWindow, + const bool bSynchronous) +{ + return ::boost::bind( + static_cast<void (PresenterPaintManager::*)( + const css::uno::Reference<css::awt::XWindow>&, + const css::awt::Rectangle&, + const bool)>(&PresenterPaintManager::Invalidate), + this, + rxWindow, + _1, + bSynchronous); +} + + + + +void PresenterPaintManager::Invalidate ( + const css::uno::Reference<css::awt::XWindow>& rxWindow, + const bool bSynchronous) +{ + sal_Int16 nInvalidateMode (awt::InvalidateStyle::CHILDREN); + if (bSynchronous) + nInvalidateMode |= awt::InvalidateStyle::UPDATE; + + PresenterPaneContainer::SharedPaneDescriptor pDescriptor( + mpPaneContainer->FindContentWindow(rxWindow)); + if (pDescriptor.get()==NULL || ! pDescriptor->mbIsOpaque) + nInvalidateMode |= awt::InvalidateStyle::TRANSPARENT; + else + nInvalidateMode |= awt::InvalidateStyle::NOTRANSPARENT; + + Invalidate(rxWindow, nInvalidateMode); +} + + + + +void PresenterPaintManager::Invalidate ( + const css::uno::Reference<css::awt::XWindow>& rxWindow, + const sal_Int16 nInvalidateFlags) +{ + if ((nInvalidateFlags & awt::InvalidateStyle::TRANSPARENT) != 0) + { + // Window is transparent and parent window(s) have to be painted as + // well. Invalidate the parent explicitly. + if (mxPresenterHelper.is() && mxParentWindowPeer.is()) + { + const awt::Rectangle aBBox ( + mxPresenterHelper->getWindowExtentsRelative(rxWindow, mxParentWindow)); + mxParentWindowPeer->invalidateRect(aBBox, nInvalidateFlags); + } + } + else + { + Reference<awt::XWindowPeer> xPeer (rxWindow, UNO_QUERY); + if (xPeer.is()) + xPeer->invalidate(nInvalidateFlags); + } +} + + + + +void PresenterPaintManager::Invalidate ( + const css::uno::Reference<css::awt::XWindow>& rxWindow, + const css::awt::Rectangle& rRepaintBox, + const bool bSynchronous) +{ + sal_Int16 nInvalidateMode (awt::InvalidateStyle::CHILDREN); + if (bSynchronous) + nInvalidateMode |= awt::InvalidateStyle::UPDATE; + + PresenterPaneContainer::SharedPaneDescriptor pDescriptor( + mpPaneContainer->FindContentWindow(rxWindow)); + if (pDescriptor.get()==NULL || ! pDescriptor->mbIsOpaque) + nInvalidateMode |= awt::InvalidateStyle::TRANSPARENT; + else + nInvalidateMode |= awt::InvalidateStyle::NOTRANSPARENT; + + Invalidate(rxWindow, rRepaintBox, nInvalidateMode); +} + + + + +void PresenterPaintManager::Invalidate ( + const css::uno::Reference<css::awt::XWindow>& rxWindow, + const css::awt::Rectangle& rRepaintBox, + const sal_Int16 nInvalidateFlags) +{ + if ((nInvalidateFlags & awt::InvalidateStyle::TRANSPARENT) != 0) + { + // Window is transparent and parent window(s) have to be painted as + // well. Invalidate the parent explicitly. + if (mxPresenterHelper.is() && mxParentWindowPeer.is()) + { + const awt::Rectangle aBBox ( + mxPresenterHelper->getWindowExtentsRelative(rxWindow, mxParentWindow)); + mxParentWindowPeer->invalidateRect( + awt::Rectangle( + rRepaintBox.X + aBBox.X, + rRepaintBox.Y + aBBox.Y, + rRepaintBox.Width, + rRepaintBox.Height), + nInvalidateFlags); + } + } + else + { + Reference<awt::XWindowPeer> xPeer (rxWindow, UNO_QUERY); + if (xPeer.is()) + xPeer->invalidateRect(rRepaintBox, nInvalidateFlags); + } +} + +} } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPaintManager.hxx b/sdext/source/presenter/PresenterPaintManager.hxx new file mode 100644 index 000000000000..421edbeb171b --- /dev/null +++ b/sdext/source/presenter/PresenterPaintManager.hxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_PAINT_MANAGER_HXX +#define SDEXT_PRESENTER_PRESENTER_PAINT_MANAGER_HXX + +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <rtl/ref.hxx> +#include <boost/function.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +class PresenterPaneContainer; + +/** Synchronize painting of windows and canvases. At the moment there is + just some processing of invalidate calls. + This could be extended to process incoming windowPaint() calls. +*/ +class PresenterPaintManager +{ +public: + /** Create paint manager with the window that is the top node in the + local window hierarchy. + */ + PresenterPaintManager ( + const css::uno::Reference<css::awt::XWindow>& rxParentWindow, + const css::uno::Reference<css::drawing::XPresenterHelper>& rxPresenterHelper, + const rtl::Reference<PresenterPaneContainer>& rpPaneContainer); + + ::boost::function<void(const css::awt::Rectangle& rRepaintBox)> + GetInvalidator ( + const css::uno::Reference<css::awt::XWindow>& rxWindow, + const bool bSynchronous = false); + + /** Request a repaint of the whole window. + @param rxWindow + May be the parent window or one of its descendents. + */ + void Invalidate ( + const css::uno::Reference<css::awt::XWindow>& rxWindow, + const bool bSynchronous = false); + void Invalidate ( + const css::uno::Reference<css::awt::XWindow>& rxWindow, + const sal_Int16 nInvalidateFlags); + + /** Request a repaint of a part of a window. + @param rxWindow + May be the parent window or one of its descendents. + */ + void Invalidate ( + const css::uno::Reference<css::awt::XWindow>& rxWindow, + const css::awt::Rectangle& rRepaintBox, + const bool bSynchronous = false); + void Invalidate ( + const css::uno::Reference<css::awt::XWindow>& rxWindow, + const css::awt::Rectangle& rRepaintBox, + const sal_Int16 nInvalidateFlags); + +private: + css::uno::Reference<css::awt::XWindow> mxParentWindow; + css::uno::Reference<css::awt::XWindowPeer> mxParentWindowPeer; + css::uno::Reference<css::drawing::XPresenterHelper> mxPresenterHelper; + ::rtl::Reference<PresenterPaneContainer> mpPaneContainer; +}; + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPane.cxx b/sdext/source/presenter/PresenterPane.cxx new file mode 100644 index 000000000000..096e5615fcbe --- /dev/null +++ b/sdext/source/presenter/PresenterPane.cxx @@ -0,0 +1,237 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterPane.hxx" +#include "PresenterController.hxx" +#include "PresenterPaintManager.hxx" +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/drawing/CanvasFeature.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <osl/mutex.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +namespace sdext { namespace presenter { + +//===== PresenterPane ========================================================= + +PresenterPane::PresenterPane ( + const Reference<XComponentContext>& rxContext, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterPaneBase(rxContext, rpPresenterController), + maBoundingBox() +{ + Reference<lang::XMultiComponentFactory> xFactory ( + mxComponentContext->getServiceManager(), UNO_QUERY_THROW); + mxPresenterHelper = Reference<drawing::XPresenterHelper>( + xFactory->createInstanceWithContext( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.PresenterHelper")), + mxComponentContext), + UNO_QUERY_THROW); +} + + + + +PresenterPane::~PresenterPane (void) +{ +} + + + + +//----- XPane ----------------------------------------------------------------- + +Reference<awt::XWindow> SAL_CALL PresenterPane::getWindow (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + return mxContentWindow; +} + + + + +Reference<rendering::XCanvas> SAL_CALL PresenterPane::getCanvas (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + return mxContentCanvas; +} + + + + +//----- XWindowListener ------------------------------------------------------- + +void SAL_CALL PresenterPane::windowResized (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + PresenterPaneBase::windowResized(rEvent); + + Invalidate(maBoundingBox); + + LayoutContextWindow(); + ToTop(); + + UpdateBoundingBox(); + Invalidate(maBoundingBox); +} + + + + + +void SAL_CALL PresenterPane::windowMoved (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + PresenterPaneBase::windowMoved(rEvent); + + Invalidate(maBoundingBox); + + ToTop(); + + UpdateBoundingBox(); + Invalidate(maBoundingBox); +} + + + + +void SAL_CALL PresenterPane::windowShown (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + PresenterPaneBase::windowShown(rEvent); + + ToTop(); + + if (mxContentWindow.is()) + { + LayoutContextWindow(); + mxContentWindow->setVisible(sal_True); + } + + UpdateBoundingBox(); + Invalidate(maBoundingBox); +} + + + + +void SAL_CALL PresenterPane::windowHidden (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + PresenterPaneBase::windowHidden(rEvent); + + if (mxContentWindow.is()) + mxContentWindow->setVisible(sal_False); +} + + + + +//----- XPaintListener -------------------------------------------------------- + +void SAL_CALL PresenterPane::windowPaint (const awt::PaintEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); + + PaintBorder(rEvent.UpdateRect); +} + + + + +//----------------------------------------------------------------------------- + + +void PresenterPane::CreateCanvases ( + const Reference<awt::XWindow>& rxParentWindow, + const Reference<rendering::XSpriteCanvas>& rxParentCanvas) +{ + if ( ! mxPresenterHelper.is()) + return; + if ( ! rxParentWindow.is()) + return; + if ( ! rxParentCanvas.is()) + return; + + mxBorderCanvas = mxPresenterHelper->createSharedCanvas( + rxParentCanvas, + rxParentWindow, + Reference<rendering::XCanvas>(rxParentCanvas, UNO_QUERY), + rxParentWindow, + mxBorderWindow); + mxContentCanvas = mxPresenterHelper->createSharedCanvas( + rxParentCanvas, + rxParentWindow, + Reference<rendering::XCanvas>(rxParentCanvas, UNO_QUERY), + rxParentWindow, + mxContentWindow); + + PaintBorder(mxBorderWindow->getPosSize()); +} + + + + +void PresenterPane::Invalidate (const css::awt::Rectangle& rRepaintBox) +{ + // Invalidate the parent window to be able to invalidate an area outside + // the current window area. + mpPresenterController->GetPaintManager()->Invalidate(mxParentWindow, rRepaintBox); +} + + + + +void PresenterPane::UpdateBoundingBox (void) +{ + if (mxBorderWindow.is() && IsVisible()) + maBoundingBox = mxBorderWindow->getPosSize(); + else + maBoundingBox = awt::Rectangle(); +} + + +} } // end of namespace ::sd::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPane.hxx b/sdext/source/presenter/PresenterPane.hxx new file mode 100644 index 000000000000..303bb0c6f5ed --- /dev/null +++ b/sdext/source/presenter/PresenterPane.hxx @@ -0,0 +1,121 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SD_PRESENTER_PRESENTER_PANE_HXX +#define SD_PRESENTER_PRESENTER_PANE_HXX + +#include "PresenterPaneBase.hxx" +#include <com/sun/star/awt/XMouseListener.hpp> +#include <com/sun/star/awt/XMouseMotionListener.hpp> +#include <com/sun/star/awt/XWindowListener.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/drawing/framework/XPaneBorderPainter.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/rendering/XCanvas.hpp> +#include <rtl/ref.hxx> +#include <boost/noncopyable.hpp> + +namespace css = ::com::sun::star; + + +namespace sdext { namespace presenter { + +/** Pane used by the presenter screen. Pane objects are stored in the + PresenterPaneContainer. Sizes and positions are controlled + by the PresenterWindowManager. Interactive positioning and resizing is + managed by the PresenterPaneBorderManager. Borders around panes are + painted by the PresenterPaneBorderPainter. +*/ +class PresenterPane : public PresenterPaneBase +{ +public: + PresenterPane ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~PresenterPane (void); + + static ::rtl::OUString getImplementationName_static (void); + static css::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static (void); + static css::uno::Reference<css::uno::XInterface> Create( + const css::uno::Reference<css::uno::XComponentContext>& rxContext) + SAL_THROW((css::uno::Exception)); + + + // XPane + + css::uno::Reference<css::awt::XWindow> SAL_CALL getWindow (void) + throw (css::uno::RuntimeException); + + css::uno::Reference<css::rendering::XCanvas> SAL_CALL getCanvas (void) + throw (css::uno::RuntimeException); + + + // XWindowListener + + virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // XPaintListener + + virtual void SAL_CALL windowPaint (const css::awt::PaintEvent& rEvent) + throw (css::uno::RuntimeException); + + +private: + /** Store the bounding box so that when the window is resized or moved + we still know the old position and size. + */ + css::awt::Rectangle maBoundingBox; + + virtual void CreateCanvases ( + const css::uno::Reference<css::awt::XWindow>& rxParentWindow, + const css::uno::Reference<css::rendering::XSpriteCanvas>& rxParentCanvas); + + void Invalidate ( + const css::awt::Rectangle& rRepaintBox); + void UpdateBoundingBox (void); +}; + +} } // end of namespace ::sd::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPaneAnimator.cxx b/sdext/source/presenter/PresenterPaneAnimator.cxx new file mode 100644 index 000000000000..f3864045b768 --- /dev/null +++ b/sdext/source/presenter/PresenterPaneAnimator.cxx @@ -0,0 +1,1426 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterPaneAnimator.hxx" + +#include "PresenterAnimation.hxx" +#include "PresenterAnimator.hxx" +#include "PresenterCanvasHelper.hxx" +#include "PresenterController.hxx" +#include "PresenterGeometryHelper.hxx" +#include "PresenterPaintManager.hxx" +#include "PresenterPaneContainer.hxx" +#include "PresenterPaneFactory.hxx" +#include "PresenterSprite.hxx" +#include "PresenterSpritePane.hxx" +#include "PresenterWindowManager.hxx" + +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <boost/bind.hpp> +#include <boost/bind/protect.hpp> +#include <boost/enable_shared_from_this.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; +using ::std::vector; + +namespace sdext { namespace presenter { + +namespace { + + class PaneGroup; + + class PresenterPaneAnimatorBase + : public ::boost::enable_shared_from_this<PresenterPaneAnimatorBase>, + public PresenterPaneAnimator + { + public: + PresenterPaneAnimatorBase ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const bool bAnimate, + const EndActions& rShowEndActions, + const EndActions& rEndEndActions); + virtual ~PresenterPaneAnimatorBase (void); + + typedef ::std::vector< ::boost::function<void()> > EndOperators; + + void ActivatePanes (void); + void ActivatePane ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId); + void RestoreFrozenWindows (void); + void FreezePanes (const Reference<rendering::XSpriteCanvas>& rxCanvas); + + protected: + ::rtl::Reference<PresenterController> mpPresenterController; + ::rtl::Reference<PresenterPaneContainer> mpPaneContainer; + ::rtl::Reference<PresenterWindowManager> mpWindowManager; + ::std::vector< ::boost::shared_ptr<PaneGroup> > maPaneGroups; + css::uno::Reference<css::drawing::framework::XResourceId> mxCenterPaneId; + bool mbDoAnimation; + EndActions maShowEndActions; + EndActions maHideEndActions; + + void DeactivatePanes (void); + void ResizePane ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const geometry::RealRectangle2D& rBox); + void DeactivatePane ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId); + }; + + + class UnfoldInCenterAnimator : public PresenterPaneAnimatorBase + { + public: + UnfoldInCenterAnimator ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const bool bAnimate, + const EndActions& rShowEndActions, + const EndActions& rEndEndActions); + + virtual ~UnfoldInCenterAnimator (void); + + virtual void ShowPane (void); + + virtual void HidePane (void); + + private: + geometry::RealRectangle2D maCenterPaneBox; + + void SetupPaneGroups (void); + geometry::RealRectangle2D MovePanesAway ( + const css::geometry::RealRectangle2D& rFreeCenterArea); + }; + + + class MoveInFromBottomAnimator : public PresenterPaneAnimatorBase + { + public: + MoveInFromBottomAnimator( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const bool bAnimate, + const EndActions& rShowEndActions, + const EndActions& rEndEndActions); + virtual ~MoveInFromBottomAnimator (void); + + virtual void ShowPane (void); + virtual void HidePane (void); + + private: + ::boost::shared_ptr<PresenterSprite> maNewPaneSprite; + geometry::RealRectangle2D maCenterPaneBox; + + void CreateShowAnimation ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const EndOperators& rpEndOperators, + const css::uno::Reference<css::rendering::XSpriteCanvas>& rxSpriteCanvas, + const bool bAnimate, + const css::geometry::RealPoint2D& rStartLocation, + const css::geometry::RealPoint2D& rEndLocation); + }; + + + class TransparentOverlayAnimator : public PresenterPaneAnimatorBase + { + public: + TransparentOverlayAnimator( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const bool bAnimate, + const EndActions& rShowEndActions, + const EndActions& rEndEndActions); + virtual ~TransparentOverlayAnimator (void); + + virtual void ShowPane (void); + virtual void HidePane (void); + + private: + PresenterSprite maBackgroundSprite; + void CreateBackgroundSprite (void); + }; + + + class PaneDescriptor + { + public: + PresenterPaneContainer::SharedPaneDescriptor mpPaneDescriptor; + + PaneDescriptor (const PresenterPaneContainer::SharedPaneDescriptor& rpDescriptor); + void Restore (void) const; + private: + double mnLeft; + double mnTop; + double mnRight; + double mnBottom; + }; + + class MultiAnimation : public PresenterAnimation + { + public: + typedef ::boost::function<void(double)> Animation; + MultiAnimation (const sal_uInt32 nDuration); + void AddAnimation (const Animation& rAnimation); + virtual void Run (const double nProgress, const sal_uInt64 nCurrentTime); + private: + vector<Animation> maAnimations; + }; + + + class PaneGroup + { + public: + PaneGroup (void); + ~PaneGroup (void); + void AddPane (const PresenterPaneContainer::SharedPaneDescriptor& rpPane); + void CreateSubstitution (const Reference<rendering::XSpriteCanvas>& rxCanvas); + void ThawPanes (void); + void Restore (void); + ::boost::shared_ptr<PresenterSprite> GetSubstitution (void) const; + css::geometry::RealRectangle2D GetOriginalBoundingBox (void) const; + css::geometry::RealRectangle2D GetCurrentBoundingBox (void) const; + void MovePanes ( + const double nXOffset, + const double nYOffset, + const ::rtl::Reference<PresenterWindowManager>& rpWindowManager); + void ActivatePanes (void); + void DeactivatePanes (void); + void HidePanes (void); + void ShowPanes (void); + + private: + vector<PaneDescriptor> maPanes; + awt::Rectangle maOriginalBoundingBox; + css::geometry::RealRectangle2D maCurrentBoundingBox; + ::boost::shared_ptr<PresenterSprite> mpSubstitution; + + }; + typedef ::boost::shared_ptr<PaneGroup> SharedPaneGroup; + + void InterpolatePosition ( + const ::boost::function<void(geometry::RealPoint2D)>& rSetter, + double nP, + const geometry::RealPoint2D rInitialBox, + const geometry::RealPoint2D rFinalBox); + + template<typename T> + void InterpolateValue ( + const ::boost::function<void(T)>& rSetter, + double nP, + const T aInitialValue, + const T aFinalValue); + + void SpriteTransform( + const rtl::Reference<PresenterPaneContainer>& rpPaneContainer, + const Reference<XResourceId>& rxPaneId, + const Reference<awt::XWindow>& rxSpriteOwnerWindow, + const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager, + const bool bAppear, + const double nX, + const double nInitialTop, + const double nFinalTop, + const double nP); + + void SpritePaneMove ( + const rtl::Reference<PresenterPaneContainer>& rpPaneContainer, + const Reference<XResourceId>& rxPaneId, + const geometry::RealPoint2D& rLocation); + + geometry::RealPoint2D GetLocation (const geometry::RealRectangle2D& rBox); + geometry::RealSize2D GetSize (const geometry::RealRectangle2D& rBox); + + +} // end of anonymous namespace + + + + +//============================================================================= + + +::boost::shared_ptr<PresenterPaneAnimator> CreateUnfoldInCenterAnimator ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const bool bAnimate, + const EndActions& rShowEndActions, + const EndActions& rEndEndActions) +{ + return ::boost::shared_ptr<PresenterPaneAnimator>( + new UnfoldInCenterAnimator(rxPaneId, rpPresenterController, bAnimate, + rShowEndActions, rEndEndActions)); +} + + + + +::boost::shared_ptr<PresenterPaneAnimator> CreateMoveInFromBottomAnimator ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const bool bAnimate, + const EndActions& rShowEndActions, + const EndActions& rEndEndActions) +{ + return ::boost::shared_ptr<PresenterPaneAnimator>( + new MoveInFromBottomAnimator(rxPaneId, rpPresenterController, bAnimate, + rShowEndActions, rEndEndActions)); +} + + + + +::boost::shared_ptr<PresenterPaneAnimator> CreateTransparentOverlay ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const bool bAnimate, + const EndActions& rShowEndActions, + const EndActions& rEndEndActions) +{ + return ::boost::shared_ptr<PresenterPaneAnimator>( + new TransparentOverlayAnimator(rxPaneId, rpPresenterController, bAnimate, + rShowEndActions, rEndEndActions)); +} + + + + +//===== PresenterPaneAnimator ================================================= + +namespace { + +PresenterPaneAnimatorBase::PresenterPaneAnimatorBase ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const bool bAnimate, + const EndActions& rShowEndActions, + const EndActions& rHideEndActions) + : mpPresenterController(rpPresenterController), + mpPaneContainer(rpPresenterController->GetPaneContainer()), + mpWindowManager(rpPresenterController->GetWindowManager()), + maPaneGroups(), + mxCenterPaneId(rxPaneId), + mbDoAnimation(bAnimate), + maShowEndActions(rShowEndActions), + maHideEndActions(rHideEndActions) +{ +} + + + + +PresenterPaneAnimatorBase::~PresenterPaneAnimatorBase (void) +{ +} + + + + +void PresenterPaneAnimatorBase::FreezePanes (const Reference<rendering::XSpriteCanvas>& rxCanvas) +{ + ::std::vector<SharedPaneGroup>::const_iterator iGroup; + for (iGroup=maPaneGroups.begin(); iGroup!=maPaneGroups.end(); ++iGroup) + { + (*iGroup)->CreateSubstitution(rxCanvas); + (*iGroup)->GetSubstitution()->MoveTo(GetLocation((*iGroup)->GetOriginalBoundingBox())); + } +} + + + + +void PresenterPaneAnimatorBase::ActivatePanes (void) +{ + ActivatePane(mxCenterPaneId); + + ::std::vector<SharedPaneGroup>::const_iterator iGroup; + for (iGroup=maPaneGroups.begin(); iGroup!=maPaneGroups.end(); ++iGroup) + { + (*iGroup)->ShowPanes(); + (*iGroup)->ActivatePanes(); + (*iGroup)->GetSubstitution()->Hide(); + } + + mpWindowManager->Update(); +} + + + + +void PresenterPaneAnimatorBase::DeactivatePanes (void) +{ + ::std::vector<SharedPaneGroup>::const_iterator iGroup; + for (iGroup=maPaneGroups.begin(); iGroup!=maPaneGroups.end(); ++iGroup) + { + (*iGroup)->GetSubstitution()->Show(); + (*iGroup)->DeactivatePanes(); + (*iGroup)->HidePanes(); + } + + mpWindowManager->Update(); +} + + + + +void PresenterPaneAnimatorBase::ResizePane ( + const Reference<drawing::framework::XResourceId>& rxPaneId, + const geometry::RealRectangle2D& rBox) +{ + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPaneContainer->FindPaneId(rxPaneId)); + if (pDescriptor.get() != NULL) + { + mpWindowManager->SetPanePosSizeAbsolute ( + rxPaneId->getResourceURL(), + rBox.X1, + rBox.Y1, + rBox.X2-rBox.X1, + rBox.Y2-rBox.Y1); + mpWindowManager->Layout(); + if ( ! pDescriptor->maSpriteProvider.empty()) + { + pDescriptor->maSpriteProvider()->Resize(GetSize(rBox)); + } + } +} + + + + +void PresenterPaneAnimatorBase::RestoreFrozenWindows (void) +{ + ::std::vector<SharedPaneGroup>::const_iterator iGroup; + for (iGroup=maPaneGroups.begin(); iGroup!=maPaneGroups.end(); ++iGroup) + { + (*iGroup)->Restore(); + (*iGroup)->ShowPanes(); + (*iGroup)->ActivatePanes(); + (*iGroup)->GetSubstitution()->Hide(); + } + maPaneGroups.clear(); + + ActivatePane(mxCenterPaneId); + + mpWindowManager->Update(); +} + + + + +void PresenterPaneAnimatorBase::ActivatePane ( + const Reference<drawing::framework::XResourceId>& rxPaneId) +{ + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPaneContainer->FindPaneId(rxPaneId)); + if (pDescriptor.get() != NULL) + pDescriptor->SetActivationState(true); +} + + + + +void PresenterPaneAnimatorBase::DeactivatePane ( + const Reference<drawing::framework::XResourceId>& rxPaneId) +{ + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPaneContainer->FindPaneId(rxPaneId)); + if (pDescriptor.get() != NULL) + pDescriptor->SetActivationState(false); +} + + + + +//===== UnfoldInCenterAnimator ================================================ + +UnfoldInCenterAnimator::UnfoldInCenterAnimator ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const bool bAnimate, + const EndActions& rShowEndActions, + const EndActions& rEndEndActions) + : PresenterPaneAnimatorBase(rxPaneId, rpPresenterController, bAnimate, + rShowEndActions, rEndEndActions) +{ +} + + + + +UnfoldInCenterAnimator::~UnfoldInCenterAnimator (void) +{ +} + + + + +void UnfoldInCenterAnimator::ShowPane (void) +{ + OSL_ASSERT(mpWindowManager.get()!=NULL); + + Reference<awt::XWindow> xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY); + if ( ! xParentWindow.is()) + return; + + Reference<rendering::XSpriteCanvas> xCanvas (mpWindowManager->GetParentCanvas(), UNO_QUERY); + if ( ! xCanvas.is()) + return; + + Reference<rendering::XBitmap> xParentBitmap (xCanvas, UNO_QUERY); + if ( ! xParentBitmap.is()) + return; + + Reference<rendering::XGraphicDevice> xDevice(xCanvas->getDevice()); + if ( ! xDevice.is()) + return; + + awt::Rectangle aWindowBox (xParentWindow->getPosSize()); + + // Create two pane groups that will be moved together. One contains the + // notes view, the other group contains all other panes. + SetupPaneGroups(); + + // Setup the places where the two pane groups are moved to. + maCenterPaneBox + = MovePanesAway(geometry::RealRectangle2D(0,200,aWindowBox.Width, aWindowBox.Height-200)); + + // Setup the final size of the new pane so that it fits into the space + // between the two pane groups. + ResizePane(mxCenterPaneId, maCenterPaneBox); + + // Avoid that the center pane updates its previews while being animated. + DeactivatePane(mxCenterPaneId); + + // Replace the pane groups with sprites that look like the panes but can + // be moved around much faster. + FreezePanes(xCanvas); + + // The vertical center of the new pane. + const double nY0 ((maPaneGroups[0]->GetOriginalBoundingBox().Y2 + + maPaneGroups[1]->GetOriginalBoundingBox().Y1) / 2); + + // Make sure that the new pane is painted once before the animation starts. + SpriteTransform( + mpPaneContainer, + mxCenterPaneId, + xParentWindow, + mpPresenterController->GetPaintManager(), + true, + maCenterPaneBox.X1, + nY0, + maCenterPaneBox.Y1, + 0); + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPaneContainer->FindPaneId(mxCenterPaneId)); + if (pDescriptor.get() != NULL) + { + mpPresenterController->GetPaintManager()->Invalidate( + pDescriptor->mxBorderWindow, + true); + } + + // Animate the upper and lower window bitmaps. + ::boost::shared_ptr<MultiAnimation> pMultiAnimation ( + new MultiAnimation(mbDoAnimation ? 500 : 0)); + + // Animate the pane group sprites to be moved up or down. + vector<SharedPaneGroup>::const_iterator iGroup; + for (iGroup=maPaneGroups.begin(); iGroup!=maPaneGroups.end(); ++iGroup) + { + pMultiAnimation->AddAnimation( + ::boost::bind( + InterpolatePosition, + ::boost::protect(::boost::bind( + &PresenterSprite::MoveTo, (*iGroup)->GetSubstitution(), _1)), + _1, + GetLocation((*iGroup)->GetOriginalBoundingBox()), + GetLocation((*iGroup)->GetCurrentBoundingBox()))); + } + + // Animate the new center pane to expand. + pMultiAnimation->AddAnimation( + ::boost::bind( + SpriteTransform, + mpPaneContainer, + mxCenterPaneId, + xParentWindow, + mpPresenterController->GetPaintManager(), + true, + maCenterPaneBox.X1, + nY0, + maCenterPaneBox.Y1, + _1)); + + // Call updateScreen after each animation step. + if (xCanvas.is()) + pMultiAnimation->AddAnimation( + ::boost::bind(&rendering::XSpriteCanvas::updateScreen, xCanvas, sal_False)); + + // Activate the panes when the animation is over. + pMultiAnimation->AddEndCallback( + ::boost::bind(&PresenterPaneAnimatorBase::ActivatePanes, shared_from_this())); + EndActions::const_iterator iAction; + for (iAction=maShowEndActions.begin(); iAction!=maShowEndActions.end(); ++iAction) + pMultiAnimation->AddEndCallback(*iAction); + + // Start the animation. + ::boost::shared_ptr<PresenterAnimator> pAnimator (mpPresenterController->GetAnimator()); + OSL_ASSERT(pAnimator.get()!=NULL); + pAnimator->AddAnimation(SharedPresenterAnimation(pMultiAnimation)); + + mpWindowManager->Update(); +} + + + + +void UnfoldInCenterAnimator::HidePane (void) +{ + OSL_ASSERT(mpWindowManager.get()!=NULL); + + Reference<awt::XWindow> xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY); + if ( ! xParentWindow.is()) + return; + + DeactivatePanes(); + DeactivatePane(mxCenterPaneId); + + ::boost::shared_ptr<PresenterAnimator> pAnimator (mpPresenterController->GetAnimator()); + const awt::Rectangle aWindowBox (xParentWindow->getPosSize()); + const rendering::ViewState aViewState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL); + const rendering::RenderState aRenderState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + + // Animate the uppder and lower window bitmaps. + Reference<rendering::XSpriteCanvas> xSpriteCanvas (mpWindowManager->GetParentCanvas(), UNO_QUERY); + ::boost::shared_ptr<MultiAnimation> pMultiAnimation (new MultiAnimation(mbDoAnimation ? 500 : 1)); + + vector<SharedPaneGroup>::const_iterator iGroup; + for (iGroup=maPaneGroups.begin(); iGroup!=maPaneGroups.end(); ++iGroup) + { + pMultiAnimation->AddAnimation( + ::boost::bind( + InterpolatePosition, + ::boost::protect(::boost::bind( + &PresenterSprite::MoveTo, (*iGroup)->GetSubstitution(), _1)), + _1, + GetLocation((*iGroup)->GetCurrentBoundingBox()), + GetLocation((*iGroup)->GetOriginalBoundingBox()))); + } + + // Animate the new center pane to collapse. + const double nY0 ((maPaneGroups[0]->GetOriginalBoundingBox().Y2 + + maPaneGroups[1]->GetOriginalBoundingBox().Y1) / 2); + pMultiAnimation->AddAnimation( + ::boost::bind( + SpriteTransform, + mpPaneContainer, + mxCenterPaneId, + xParentWindow, + mpPresenterController->GetPaintManager(), + false, + maCenterPaneBox.X1, + nY0, + maCenterPaneBox.Y1, + _1)); + + if (mbDoAnimation) + { + pMultiAnimation->AddAnimation( + ::boost::bind(&rendering::XSpriteCanvas::updateScreen, xSpriteCanvas, sal_False)); + } + pMultiAnimation->AddEndCallback( + ::boost::bind(&PresenterPaneAnimatorBase::RestoreFrozenWindows, shared_from_this())); + EndActions::const_iterator iAction; + for (iAction=maHideEndActions.begin(); iAction!=maHideEndActions.end(); ++iAction) + pMultiAnimation->AddEndCallback(*iAction); + + pAnimator->AddAnimation(SharedPresenterAnimation(pMultiAnimation)); +} + + + + +void UnfoldInCenterAnimator::SetupPaneGroups (void) +{ + maPaneGroups.clear(); + + // Setup the upper pane group. + SharedPaneGroup pUpperPanes (new PaneGroup()); + pUpperPanes->AddPane(mpPaneContainer->FindPaneURL( + PresenterPaneFactory::msCurrentSlidePreviewPaneURL)); + pUpperPanes->AddPane(mpPaneContainer->FindPaneURL( + PresenterPaneFactory::msNextSlidePreviewPaneURL)); + pUpperPanes->AddPane(mpPaneContainer->FindPaneURL( + PresenterPaneFactory::msToolBarPaneURL)); + pUpperPanes->AddPane(mpPaneContainer->FindPaneURL( + PresenterPaneFactory::msHelpPaneURL)); + maPaneGroups.push_back(pUpperPanes); + + // Setup the lower pane group. + SharedPaneGroup pLowerPanes (new PaneGroup()); + pLowerPanes->AddPane(mpPaneContainer->FindPaneURL( + PresenterPaneFactory::msNotesPaneURL)); + maPaneGroups.push_back(pLowerPanes); +} + + + + +geometry::RealRectangle2D UnfoldInCenterAnimator::MovePanesAway ( + const geometry::RealRectangle2D& rFreeCenterArea) +{ + SharedPaneGroup aUpperPanes = maPaneGroups[0]; + SharedPaneGroup aLowerPanes = maPaneGroups[1]; + + // Move upper pane group out of the way. + const double nTop (rFreeCenterArea.Y1); + const double nUpperVerticalOffset (nTop - aUpperPanes->GetOriginalBoundingBox().Y2); + aUpperPanes->MovePanes(0, nUpperVerticalOffset, mpWindowManager); + + // Move lower pane group out of the way. + const double nBottom (rFreeCenterArea.Y2); + const double nLowerVerticalOffset (nBottom - aLowerPanes->GetOriginalBoundingBox().Y1); + aLowerPanes->MovePanes(0, nLowerVerticalOffset, mpWindowManager); + + return geometry::RealRectangle2D( + ::std::min( + aUpperPanes->GetOriginalBoundingBox().X1, + aLowerPanes->GetOriginalBoundingBox().X1), + nTop+20, + ::std::max( + aUpperPanes->GetOriginalBoundingBox().X2, + aLowerPanes->GetOriginalBoundingBox().X2), + nBottom-20); +} + + + + +//===== MoveInFromBottomAnimator ============================================== + +MoveInFromBottomAnimator::MoveInFromBottomAnimator ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const bool bAnimate, + const EndActions& rShowEndActions, + const EndActions& rEndEndActions) + : PresenterPaneAnimatorBase(rxPaneId, rpPresenterController, bAnimate, + rShowEndActions, rEndEndActions), + maNewPaneSprite() +{ +} + + + + +MoveInFromBottomAnimator::~MoveInFromBottomAnimator (void) +{ +} + + + + +void MoveInFromBottomAnimator::ShowPane (void) +{ + OSL_ASSERT(mpWindowManager.get()!=NULL); + + Reference<awt::XWindow> xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY); + if ( ! xParentWindow.is()) + return; + + Reference<rendering::XSpriteCanvas> xCanvas (mpWindowManager->GetParentCanvas(), UNO_QUERY); + if ( ! xCanvas.is()) + return; + + Reference<rendering::XBitmap> xParentBitmap (xCanvas, UNO_QUERY); + if ( ! xParentBitmap.is()) + return; + + Reference<rendering::XGraphicDevice> xDevice(xCanvas->getDevice()); + if ( ! xDevice.is()) + return; + + awt::Rectangle aWindowBox (xParentWindow->getPosSize()); + + // Create a pane group that just contains the notes view. + SharedPaneGroup pLowerPanes (new PaneGroup()); + pLowerPanes->AddPane(mpPaneContainer->FindPaneURL( + PresenterPaneFactory::msNotesPaneURL)); + maPaneGroups.push_back(pLowerPanes); + + // Deactivate the panes that will take place in the animation. + pLowerPanes->DeactivatePanes(); + DeactivatePane(mxCenterPaneId); + + // Set the size of the new pane. + maCenterPaneBox = pLowerPanes->GetOriginalBoundingBox(); + ResizePane(mxCenterPaneId, maCenterPaneBox); + + geometry::RealPoint2D aStartLocation (maCenterPaneBox.X1, aWindowBox.Height); + geometry::RealPoint2D aEndLocation (maCenterPaneBox.X1, maCenterPaneBox.Y1); + + // Get the sprite of the new pane, make it visible and move it to the + // start location. + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPaneContainer->FindPaneId(mxCenterPaneId)); + if (pDescriptor.get() != NULL) + { + if (pDescriptor->mxBorderWindow.is()) + pDescriptor->mxBorderWindow->setVisible(sal_True); + + maNewPaneSprite = pDescriptor->maSpriteProvider(); + if (maNewPaneSprite.get() != NULL) + { + maNewPaneSprite->MoveTo(aStartLocation); + maNewPaneSprite->Show(); + } + xCanvas->updateScreen(sal_False); + } + + CreateShowAnimation( + mxCenterPaneId, + maShowEndActions, + xCanvas, + mbDoAnimation, + aStartLocation, + aEndLocation); + + mpWindowManager->Update(); +} + + + + +void MoveInFromBottomAnimator::HidePane (void) +{ + OSL_ASSERT(mpWindowManager.get()!=NULL); + + Reference<awt::XWindow> xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY); + if ( ! xParentWindow.is()) + return; + + Reference<rendering::XSpriteCanvas> xCanvas (mpWindowManager->GetParentCanvas(), UNO_QUERY); + if ( ! xCanvas.is()) + return; + + DeactivatePanes(); + DeactivatePane(mxCenterPaneId); + + SharedPaneGroup aPanes (maPaneGroups[0]); + + aPanes->ShowPanes(); + + ::boost::shared_ptr<MultiAnimation> pMultiAnimation ( + new MultiAnimation(mbDoAnimation ? 500 : 0)); + awt::Rectangle aWindowBox (xParentWindow->getPosSize()); + + // Animate the new center pane to collapse. + pMultiAnimation->AddAnimation( + ::boost::bind( + InterpolatePosition, + ::boost::protect(::boost::bind(&SpritePaneMove, mpPaneContainer, mxCenterPaneId, _1)), + _1, + geometry::RealPoint2D(maCenterPaneBox.X1, maCenterPaneBox.Y1), + geometry::RealPoint2D(maCenterPaneBox.X1, aWindowBox.Height))); + + if (mbDoAnimation) + { + pMultiAnimation->AddAnimation( + ::boost::bind(&rendering::XSpriteCanvas::updateScreen, xCanvas, sal_False)); + } + pMultiAnimation->AddEndCallback( + ::boost::bind(&PresenterPaneAnimatorBase::RestoreFrozenWindows, shared_from_this())); + EndActions::const_iterator iAction; + for (iAction=maHideEndActions.begin(); iAction!=maHideEndActions.end(); ++iAction) + pMultiAnimation->AddEndCallback(*iAction); + + ::boost::shared_ptr<PresenterAnimator> pAnimator (mpPresenterController->GetAnimator()); + pAnimator->AddAnimation(SharedPresenterAnimation(pMultiAnimation)); +} + + + + +void MoveInFromBottomAnimator::CreateShowAnimation ( + const Reference<drawing::framework::XResourceId>& rxPaneId, + const EndOperators& rEndOperators, + const Reference<rendering::XSpriteCanvas>& rxSpriteCanvas, + const bool bAnimate, + const geometry::RealPoint2D& rStartLocation, + const geometry::RealPoint2D& rEndLocation) +{ + // Animate the uppder and lower window bitmaps. + ::boost::shared_ptr<MultiAnimation> pMultiAnimation (new MultiAnimation(bAnimate ? 500 : 0)); + + // Animate new pane to move in from the buttom. + pMultiAnimation->AddAnimation( + ::boost::bind( + InterpolatePosition, + ::boost::protect(::boost::bind(&SpritePaneMove, mpPaneContainer, rxPaneId, _1)), + _1, + rStartLocation, + rEndLocation)); + + // Call updateScreen after each animation step. + if (rxSpriteCanvas.is()) + pMultiAnimation->AddAnimation( + ::boost::bind(&rendering::XSpriteCanvas::updateScreen, rxSpriteCanvas, sal_False)); + + // Activate the panes when the animation is over. + pMultiAnimation->AddEndCallback( + ::boost::bind(&PaneGroup::HidePanes, maPaneGroups[0])); + pMultiAnimation->AddEndCallback( + ::boost::bind(&PresenterPaneAnimatorBase::ActivatePane, shared_from_this(), mxCenterPaneId)); + EndActions::const_iterator iAction; + for (iAction=rEndOperators.begin(); iAction!=rEndOperators.end(); ++iAction) + pMultiAnimation->AddEndCallback(*iAction); + + // Start the animation. + ::boost::shared_ptr<PresenterAnimator> pAnimator (mpPresenterController->GetAnimator()); + OSL_ASSERT(pAnimator.get()!=NULL); + pAnimator->AddAnimation(SharedPresenterAnimation(pMultiAnimation)); +} + + + + + +//===== TransparentOverlayAnimator ============================================ + +TransparentOverlayAnimator::TransparentOverlayAnimator ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const bool bAnimate, + const EndActions& rShowEndActions, + const EndActions& rEndEndActions) + : PresenterPaneAnimatorBase( + rxPaneId, + rpPresenterController, + bAnimate, + rShowEndActions, + rEndEndActions), + maBackgroundSprite() +{ +} + + + + +TransparentOverlayAnimator::~TransparentOverlayAnimator (void) +{ +} + + + + +void TransparentOverlayAnimator::ShowPane (void) +{ + EndActions::const_iterator iAction; + for (iAction=maShowEndActions.begin(); iAction!=maShowEndActions.end(); ++iAction) + (*iAction)(); + + CreateBackgroundSprite(); + + Reference<awt::XWindow> xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY); + if (xParentWindow.is()) + { + const awt::Rectangle aWindowBox (xParentWindow->getPosSize()); + SharedPaneGroup pAllPanes (new PaneGroup()); + pAllPanes->AddPane(mpPaneContainer->FindPaneURL( + PresenterPaneFactory::msCurrentSlidePreviewPaneURL)); + pAllPanes->AddPane(mpPaneContainer->FindPaneURL( + PresenterPaneFactory::msNextSlidePreviewPaneURL)); + pAllPanes->AddPane(mpPaneContainer->FindPaneURL( + PresenterPaneFactory::msToolBarPaneURL)); + pAllPanes->AddPane(mpPaneContainer->FindPaneURL( + PresenterPaneFactory::msHelpPaneURL)); + pAllPanes->AddPane(mpPaneContainer->FindPaneURL( + PresenterPaneFactory::msNotesPaneURL)); + maPaneGroups.push_back(pAllPanes); + pAllPanes->DeactivatePanes(); + mpWindowManager->Update(); + } + + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPaneContainer->FindPaneId(mxCenterPaneId)); + if (pDescriptor.get() != NULL) + { + PresenterSpritePane* pPane = dynamic_cast<PresenterSpritePane*>( + pDescriptor->mxPane.get()); + if (pPane != NULL) + pPane->ShowTransparentBorder(); + + pDescriptor->SetActivationState(true); + if (pDescriptor->mxBorderWindow.is()) + pDescriptor->mxBorderWindow->setVisible(sal_True); + } +} + + + + +void TransparentOverlayAnimator::HidePane (void) +{ + maPaneGroups[0]->ActivatePanes(); + EndActions::const_iterator iAction; + for (iAction=maHideEndActions.begin(); iAction!=maHideEndActions.end(); ++iAction) + (*iAction)(); + mpWindowManager->Update(); +} + + + + +void TransparentOverlayAnimator::CreateBackgroundSprite (void) +{ + Reference<awt::XWindow> xParentWindow (mpWindowManager->GetParentWindow(), UNO_QUERY); + Reference<rendering::XSpriteCanvas> xParentCanvas (mpWindowManager->GetParentCanvas(), UNO_QUERY); + if (xParentWindow.is() && xParentCanvas.is()) + { + const awt::Rectangle aWindowBox (xParentWindow->getPosSize()); + maBackgroundSprite.SetFactory(xParentCanvas); + maBackgroundSprite.Resize( + geometry::RealSize2D(aWindowBox.Width, aWindowBox.Height)); + maBackgroundSprite.MoveTo( + geometry::RealPoint2D(aWindowBox.X, aWindowBox.Y)); + maBackgroundSprite.SetAlpha(0.5); + maBackgroundSprite.Show(); + + Reference<rendering::XCanvas> xCanvas (maBackgroundSprite.GetCanvas()); + + if (xCanvas.is()) + { + rendering::ViewState aViewState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL); + + rendering::RenderState aRenderState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x80808080)); + + Reference<rendering::XPolyPolygon2D> xPolygon ( + PresenterGeometryHelper::CreatePolygon(aWindowBox, xCanvas->getDevice())); + if (xPolygon.is()) + xCanvas->fillPolyPolygon( + xPolygon, + aViewState, + aRenderState); + } + } +} + + + + +//===== PaneGroup ============================================================= + +PaneGroup::PaneGroup (void) + : maPanes(), + maOriginalBoundingBox(), + maCurrentBoundingBox(), + mpSubstitution(new PresenterSprite()) +{ +} + + + + +PaneGroup::~PaneGroup (void) +{ + mpSubstitution.reset(); +} + + + + +void PaneGroup::AddPane (const PresenterPaneContainer::SharedPaneDescriptor& rpPane) +{ + OSL_ASSERT(rpPane.get() != NULL); + + if (rpPane->mxBorderWindow.is()) + { + PaneDescriptor aDescriptor (rpPane); + maPanes.push_back(aDescriptor); + maOriginalBoundingBox = PresenterGeometryHelper::Union( + maOriginalBoundingBox, + rpPane->mxBorderWindow->getPosSize()); + } +} + + + + +void PaneGroup::CreateSubstitution (const Reference<rendering::XSpriteCanvas>& rxCanvas) +{ + // Get the bitmap of the background. + Reference<rendering::XBitmap> xBackgroundBitmap (rxCanvas, UNO_QUERY); + if ( ! xBackgroundBitmap.is()) + return; + + // Create the sprite. + mpSubstitution->SetFactory(rxCanvas); + mpSubstitution->Resize( + geometry::RealSize2D(maOriginalBoundingBox.Width, maOriginalBoundingBox.Height)); + + // Fill it with the background inside the bounding box. + const rendering::ViewState aViewState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL); + const rendering::RenderState aRenderState ( + geometry::AffineMatrix2D(1,0,-maOriginalBoundingBox.X, 0,1,-maOriginalBoundingBox.Y), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + + Reference<rendering::XCanvas> xSpriteCanvas (mpSubstitution->GetCanvas()); + if (xSpriteCanvas.is()) + xSpriteCanvas->drawBitmap(xBackgroundBitmap, aViewState, aRenderState); +} + + + + +void PaneGroup::Restore (void) +{ + vector<PaneDescriptor>::iterator iPane; + for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane) + { + iPane->Restore(); + } +} + + + +::boost::shared_ptr<PresenterSprite> PaneGroup::GetSubstitution (void) const +{ + return mpSubstitution; +} + + + + +geometry::RealRectangle2D PaneGroup::GetOriginalBoundingBox (void) const +{ + return geometry::RealRectangle2D( + maOriginalBoundingBox.X, + maOriginalBoundingBox.Y, + maOriginalBoundingBox.X + maOriginalBoundingBox.Width, + maOriginalBoundingBox.Y + maOriginalBoundingBox.Height); +} + + + + +geometry::RealRectangle2D PaneGroup::GetCurrentBoundingBox (void) const +{ + return maCurrentBoundingBox; +} + + + + +void PaneGroup::MovePanes ( + const double nXOffset, + const double nYOffset, + const ::rtl::Reference<PresenterWindowManager>& rpWindowManager + ) +{ + awt::Rectangle aBBox; + vector<PaneDescriptor>::iterator iPane; + for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane) + { + awt::Rectangle aBox (iPane->mpPaneDescriptor->mxBorderWindow->getPosSize()); + aBox.X += sal_Int32(nXOffset); + aBox.Y += sal_Int32(nYOffset); + rpWindowManager->SetPanePosSizeAbsolute( + iPane->mpPaneDescriptor->mxPaneId->getResourceURL(), + aBox.X, + aBox.Y, + aBox.Width, + aBox.Height); + aBBox = PresenterGeometryHelper::Union(aBBox, aBox); + } + maCurrentBoundingBox = geometry::RealRectangle2D( + aBBox.X, aBBox.Y, aBBox.X+aBBox.Width, aBBox.Y+aBBox.Height); +} + + + + +void PaneGroup::ActivatePanes (void) +{ + vector<PaneDescriptor>::iterator iPane; + for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane) + { + iPane->mpPaneDescriptor->SetActivationState(true); + } +} + + + + +void PaneGroup::DeactivatePanes (void) +{ + vector<PaneDescriptor>::iterator iPane; + for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane) + { + iPane->mpPaneDescriptor->SetActivationState(false); + } +} + + + + +void PaneGroup::ShowPanes (void) +{ + vector<PaneDescriptor>::iterator iPane; + for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane) + { + iPane->mpPaneDescriptor->mxBorderWindow->setVisible(sal_True); + iPane->mpPaneDescriptor->mxContentWindow->setVisible(sal_True); + } +} + + + + +void PaneGroup::HidePanes (void) +{ + vector<PaneDescriptor>::iterator iPane; + for (iPane=maPanes.begin(); iPane!=maPanes.end(); ++iPane) + { + iPane->mpPaneDescriptor->mxBorderWindow->setVisible(sal_False); + iPane->mpPaneDescriptor->mxContentWindow->setVisible(sal_False); + } +} + + + + +//===== PaneDescriptor ======================================================== + +PaneDescriptor::PaneDescriptor (const PresenterPaneContainer::SharedPaneDescriptor& rpDescriptor) + : mpPaneDescriptor(rpDescriptor), + mnLeft(rpDescriptor->mnLeft), + mnTop(rpDescriptor->mnTop), + mnRight(rpDescriptor->mnRight), + mnBottom(rpDescriptor->mnBottom) +{ +} + + + + +void PaneDescriptor::Restore (void) const +{ + mpPaneDescriptor->mnLeft = mnLeft; + mpPaneDescriptor->mnTop = mnTop; + mpPaneDescriptor->mnRight = mnRight; + mpPaneDescriptor->mnBottom = mnBottom; +} + + + + +//===== MultiAnimation ======================================================== + +MultiAnimation::MultiAnimation (const sal_uInt32 nDuration) + : PresenterAnimation(0, nDuration, 1000/50), + maAnimations() +{ +} + + + + +void MultiAnimation::AddAnimation (const Animation& rAnimation) +{ + maAnimations.push_back(rAnimation); +} + + + + +void MultiAnimation::Run (const double nProgress, const sal_uInt64 nCurrentTime) +{ + (void)nCurrentTime; + vector<Animation>::const_iterator iAnimation (maAnimations.begin()); + vector<Animation>::const_iterator iEnd (maAnimations.end()); + for ( ; iAnimation!=iEnd; ++iAnimation) + (*iAnimation)(nProgress); +} + + + + +//===== functors ============================================================== + +void InterpolatePosition ( + const ::boost::function<void(geometry::RealPoint2D)>& rSetter, + double nP, + const geometry::RealPoint2D rInitialBox, + const geometry::RealPoint2D rFinalBox) +{ + const double nQ (1 - nP); + + OSL_TRACE("InterpolatePosition %f\n", nP); + rSetter( + geometry::RealPoint2D( + nQ * rInitialBox.X + nP * rFinalBox.X, + nQ * rInitialBox.Y + nP * rFinalBox.Y)); +} + + + + +template<typename T> + void InterpolateValue ( + const ::boost::function<void(T)>& rSetter, + double nP, + const T aInitialValue, + const T aFinalValue) +{ + const double nQ (1 - nP); + + rSetter(T(nQ * aInitialValue + nP * aFinalValue)); +} + + + + +void SpriteTransform( + const rtl::Reference<PresenterPaneContainer>& rpPaneContainer, + const Reference<XResourceId>& rxPaneId, + const Reference<awt::XWindow>& rxSpriteOwnerWindow, + const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager, + const bool bAppear, + const double nX, + const double nInitialTop, + const double nFinalTop, + const double nP) +{ + OSL_ASSERT(rpPaintManager.get()!=NULL); + + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + rpPaneContainer->FindPaneId(rxPaneId)); + if (pDescriptor.get() != NULL + && ! pDescriptor->maSpriteProvider.empty() + && pDescriptor->mxBorderWindow.is()) + { + ::boost::shared_ptr<PresenterSprite> pSprite (pDescriptor->maSpriteProvider()); + if (pSprite.get()) + { + // There seems to be a problem with sprites not correctly + // invalidating the background when being transformed. As a + // workaround invalidate the background in the bounding box of + // the sprite before the transformation. + rpPaintManager->Invalidate( + rxSpriteOwnerWindow, + awt::Rectangle( + sal::static_int_cast<sal_Int32>(pSprite->GetLocation().X), + sal::static_int_cast<sal_Int32>(pSprite->GetLocation().Y), + sal::static_int_cast<sal_Int32>(pSprite->GetSize().Width), + sal::static_int_cast<sal_Int32>(pSprite->GetSize().Height))); + + const double nYScale (bAppear ? nP : 1-nP); + pSprite->Transform(geometry::AffineMatrix2D( + 1, 0, 0, + 0, nYScale, 0)); + pSprite->MoveTo( + geometry::RealPoint2D(nX, nYScale*nFinalTop + (1-nYScale)*nInitialTop)); + pSprite->Show(); + + pDescriptor->mxBorderWindow->setVisible(sal_True); + } + } +} + + + + +void SpritePaneMove ( + const rtl::Reference<PresenterPaneContainer>& rpPaneContainer, + const Reference<XResourceId>& rxPaneId, + const geometry::RealPoint2D& rLocation) +{ + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + rpPaneContainer->FindPaneId(rxPaneId)); + if (pDescriptor.get() != NULL + && ! pDescriptor->maSpriteProvider.empty() + && pDescriptor->mxBorderWindow.is()) + { + ::boost::shared_ptr<PresenterSprite> pSprite (pDescriptor->maSpriteProvider()); + if (pSprite.get() != NULL) + { + pDescriptor->mxBorderWindow->setVisible(sal_True); + pSprite->MoveTo(rLocation); + } + } +} + + + + +geometry::RealPoint2D GetLocation (const geometry::RealRectangle2D& rBox) +{ + return geometry::RealPoint2D(rBox.X1, rBox.Y1); +} + + + + +geometry::RealSize2D GetSize (const geometry::RealRectangle2D& rBox) +{ + return geometry::RealSize2D(rBox.X2-rBox.X1, rBox.Y2-rBox.Y1); +} + +} // end of anonymous namespace + + + + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPaneAnimator.hxx b/sdext/source/presenter/PresenterPaneAnimator.hxx new file mode 100644 index 000000000000..1e044b4a647b --- /dev/null +++ b/sdext/source/presenter/PresenterPaneAnimator.hxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_PANE_ANIMATOR_HXXs +#define SDEXT_PRESENTER_PRESENTER_PANE_ANIMATOR_HXX + +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/drawing/framework/XResourceId.hpp> +#include <com/sun/star/geometry/RealPoint2D.hpp> +#include <com/sun/star/rendering/XBitmap.hpp> +#include <com/sun/star/rendering/XSprite.hpp> +#include <com/sun/star/rendering/XSpriteCanvas.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <rtl/ref.hxx> +#include <vector> +#include <boost/function.hpp> +#include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +class PresenterController; +class PresenterPaneContainer; +class PresenterWindowManager; + +/** Base class for different types of pane animations. Each of these + animations either shows or hides a single pane. +*/ +class PresenterPaneAnimator + : private ::boost::noncopyable +{ +public: + virtual void ShowPane (void) = 0; + virtual void HidePane (void) = 0; + +protected: + virtual ~PresenterPaneAnimator (void) {}; +}; + + +typedef ::std::vector< ::boost::function<void()> > EndActions; + +::boost::shared_ptr<PresenterPaneAnimator> CreateUnfoldInCenterAnimator ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const bool bAnimate, + const EndActions& rShowEndActions, + const EndActions& rEndEndActions); + +::boost::shared_ptr<PresenterPaneAnimator> CreateMoveInFromBottomAnimator ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const bool bAnimate, + const EndActions& rShowEndActions, + const EndActions& rEndEndActions); + +::boost::shared_ptr<PresenterPaneAnimator> CreateTransparentOverlay ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const bool bAnimate, + const EndActions& rShowEndActions, + const EndActions& rEndEndActions); + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPaneBase.cxx b/sdext/source/presenter/PresenterPaneBase.cxx new file mode 100644 index 000000000000..39283673c23d --- /dev/null +++ b/sdext/source/presenter/PresenterPaneBase.cxx @@ -0,0 +1,561 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterPaneBase.hxx" +#include "PresenterCanvasHelper.hxx" +#include "PresenterController.hxx" +#include "PresenterGeometryHelper.hxx" +#include "PresenterPaintManager.hxx" +#include "PresenterTextView.hxx" +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/awt/XWindow2.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/drawing/CanvasFeature.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/TexturingMode.hpp> +#include <osl/mutex.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +namespace sdext { namespace presenter { + +//===== PresenterPaneBase ===================================================== + +PresenterPaneBase::PresenterPaneBase ( + const Reference<XComponentContext>& rxContext, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterPaneBaseInterfaceBase(m_aMutex), + mpPresenterController(rpPresenterController), + mxParentWindow(), + mxBorderWindow(), + mxBorderCanvas(), + mxContentWindow(), + mxContentCanvas(), + mxPaneId(), + mxBorderPainter(), + mxPresenterHelper(), + msTitle(), + mxComponentContext(rxContext), + mpViewBackground(), + mbHasCallout(false), + maCalloutAnchor() +{ + if (mpPresenterController.get() != NULL) + mxPresenterHelper = mpPresenterController->GetPresenterHelper(); +} + + + + +PresenterPaneBase::~PresenterPaneBase (void) +{ +} + + + + +void PresenterPaneBase::disposing (void) +{ + if (mxBorderWindow.is()) + { + mxBorderWindow->removeWindowListener(this); + mxBorderWindow->removePaintListener(this); + } + + { + Reference<XComponent> xComponent (mxContentCanvas, UNO_QUERY); + mxContentCanvas = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + + { + Reference<XComponent> xComponent (mxContentWindow, UNO_QUERY); + mxContentWindow = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + + { + Reference<XComponent> xComponent (mxBorderCanvas, UNO_QUERY); + mxBorderCanvas = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + + { + Reference<XComponent> xComponent (mxBorderWindow, UNO_QUERY); + mxBorderWindow = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + + mxComponentContext = NULL; +} + + + + +void PresenterPaneBase::SetTitle (const OUString& rsTitle) +{ + msTitle = rsTitle; + + OSL_ASSERT(mpPresenterController.get()!=NULL); + OSL_ASSERT(mpPresenterController->GetPaintManager().get()!=NULL); + + mpPresenterController->GetPaintManager()->Invalidate(mxBorderWindow); +} + + + + +::rtl::OUString PresenterPaneBase::GetTitle (void) const +{ + return msTitle; +} + + + + +Reference<drawing::framework::XPaneBorderPainter> + PresenterPaneBase::GetPaneBorderPainter (void) const +{ + return mxBorderPainter; +} + + + + +void PresenterPaneBase::SetCalloutAnchor (const css::awt::Point& rCalloutAnchor) +{ + mbHasCallout = true; + // Anchor is given in the coorindate system of the parent window. + // Transform it into the local coordinate system. + maCalloutAnchor = rCalloutAnchor; + const awt::Rectangle aBorderBox (mxBorderWindow->getPosSize()); + maCalloutAnchor.X -= aBorderBox.X; + maCalloutAnchor.Y -= aBorderBox.Y; + + // Move the bottom of the border window so that it goes through the + // callout anchor (special case for bottom callout). + sal_Int32 nHeight (rCalloutAnchor.Y - aBorderBox.Y); + if (mxBorderPainter.is() && mxPaneId.is()) + nHeight += mxBorderPainter->getCalloutOffset(mxPaneId->getResourceURL()).Y; + + if (nHeight != aBorderBox.Height) + { + mxBorderWindow->setPosSize( + aBorderBox.X, + aBorderBox.Y, + aBorderBox.Width, + nHeight, + awt::PosSize::HEIGHT); + } + + mpPresenterController->GetPaintManager()->Invalidate(mxBorderWindow); +} + + + + +awt::Point PresenterPaneBase::GetCalloutAnchor (void) const +{ + return maCalloutAnchor; +} + + + + +::boost::shared_ptr<PresenterTextView> PresenterPaneBase::GetTextViewForTitle (void) +{ + ::boost::shared_ptr<PresenterTextView> pTextView( + new PresenterTextView( + mxComponentContext, + mxBorderCanvas)); + pTextView->SetText(msTitle); + return pTextView; +} + + + + +//----- XInitialization ------------------------------------------------------- + +void SAL_CALL PresenterPaneBase::initialize (const Sequence<Any>& rArguments) + throw (Exception, RuntimeException) +{ + ThrowIfDisposed(); + + if ( ! mxComponentContext.is()) + { + throw RuntimeException( + OUString(RTL_CONSTASCII_USTRINGPARAM("PresenterSpritePane: missing component context")), + static_cast<XWeak*>(this)); + } + + if (rArguments.getLength() == 5 || rArguments.getLength() == 6) + { + try + { + // Get the resource id from the first argument. + if ( ! (rArguments[0] >>= mxPaneId)) + { + throw lang::IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("PresenterPane: invalid pane id")), + static_cast<XWeak*>(this), + 0); + } + + if ( ! (rArguments[1] >>= mxParentWindow)) + { + throw lang::IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("PresenterPane: invalid parent window")), + static_cast<XWeak*>(this), + 1); + } + + Reference<rendering::XSpriteCanvas> xParentCanvas; + if ( ! (rArguments[2] >>= xParentCanvas)) + { + throw lang::IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("PresenterPane: invalid parent canvas")), + static_cast<XWeak*>(this), + 2); + } + + if ( ! (rArguments[3] >>= msTitle)) + { + throw lang::IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("PresenterPane: invalid title")), + static_cast<XWeak*>(this), + 3); + } + + if ( ! (rArguments[4] >>= mxBorderPainter)) + { + throw lang::IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("PresenterPane: invalid border painter")), + static_cast<XWeak*>(this), + 4); + } + + bool bIsWindowVisibleOnCreation (true); + if (rArguments.getLength()>5 && ! (rArguments[5] >>= bIsWindowVisibleOnCreation)) + { + throw lang::IllegalArgumentException( + OUString(RTL_CONSTASCII_USTRINGPARAM("PresenterPane: invalid window visibility flag")), + static_cast<XWeak*>(this), + 5); + } + + CreateWindows(mxParentWindow, bIsWindowVisibleOnCreation); + + if (mxBorderWindow.is()) + { + mxBorderWindow->addWindowListener(this); + mxBorderWindow->addPaintListener(this); + } + + CreateCanvases(mxParentWindow, xParentCanvas); + + // Raise new windows. + ToTop(); + } + catch (Exception&) + { + mxContentWindow = NULL; + mxComponentContext = NULL; + throw; + } + } + else + { + throw RuntimeException( + OUString(RTL_CONSTASCII_USTRINGPARAM("PresenterSpritePane: invalid number of arguments")), + static_cast<XWeak*>(this)); + } +} + + + + +//----- XResourceId ----------------------------------------------------------- + +Reference<XResourceId> SAL_CALL PresenterPaneBase::getResourceId (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + return mxPaneId; +} + + + + +sal_Bool SAL_CALL PresenterPaneBase::isAnchorOnly (void) + throw (RuntimeException) +{ + return true; +} + + + + +//----- XWindowListener ------------------------------------------------------- + +void SAL_CALL PresenterPaneBase::windowResized (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); +} + + + + + +void SAL_CALL PresenterPaneBase::windowMoved (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); +} + + + + +void SAL_CALL PresenterPaneBase::windowShown (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); +} + + + + +void SAL_CALL PresenterPaneBase::windowHidden (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); +} + + + + +//----- lang::XEventListener -------------------------------------------------- + +void SAL_CALL PresenterPaneBase::disposing (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + if (rEvent.Source == mxBorderWindow) + { + mxBorderWindow = NULL; + } +} + + + + +//----------------------------------------------------------------------------- + + +void PresenterPaneBase::CreateWindows ( + const Reference<awt::XWindow>& rxParentWindow, + const bool bIsWindowVisibleOnCreation) +{ + if (mxPresenterHelper.is() && rxParentWindow.is()) + { + + mxBorderWindow = mxPresenterHelper->createWindow( + rxParentWindow, + sal_False, + bIsWindowVisibleOnCreation, + sal_False, + sal_False); + mxContentWindow = mxPresenterHelper->createWindow( + mxBorderWindow, + sal_False, + bIsWindowVisibleOnCreation, + sal_False, + sal_False); + } +} + + + + +Reference<awt::XWindow> PresenterPaneBase::GetBorderWindow (void) const +{ + return mxBorderWindow; +} + + + + +void PresenterPaneBase::ToTop (void) +{ + if (mxPresenterHelper.is()) + mxPresenterHelper->toTop(mxContentWindow); +} + + + + +void PresenterPaneBase::SetBackground (const SharedBitmapDescriptor& rpBackground) +{ + mpViewBackground = rpBackground; +} + + + + +void PresenterPaneBase::PaintBorderBackground ( + const awt::Rectangle& rBorderBox, + const awt::Rectangle& rUpdateBox) +{ + (void)rBorderBox; + (void)rUpdateBox; + /* + // The outer box of the border is given. We need the center and inner + // box as well. + awt::Rectangle aCenterBox ( + mxBorderPainter->removeBorder( + mxPaneId->getResourceURL(), + rBorderBox, + drawing::framework::BorderType_OUTER_BORDER)); + awt::Rectangle aInnerBox ( + mxBorderPainter->removeBorder( + mxPaneId->getResourceURL(), + rBorderBox, + drawing::framework::BorderType_TOTAL_BORDER)); + mpPresenterController->GetCanvasHelper()->Paint( + mpViewBackground, + mxBorderCanvas, + rUpdateBox, + aCenterBox, + aInnerBox); + */ +} + + + + +void PresenterPaneBase::PaintBorder (const awt::Rectangle& rUpdateBox) +{ + OSL_ASSERT(mxPaneId.is()); + + if (mxBorderPainter.is() && mxBorderWindow.is() && mxBorderCanvas.is()) + { + awt::Rectangle aBorderBox (mxBorderWindow->getPosSize()); + awt::Rectangle aLocalBorderBox (0,0, aBorderBox.Width, aBorderBox.Height); + + PaintBorderBackground(aLocalBorderBox, rUpdateBox); + + if (mbHasCallout) + mxBorderPainter->paintBorderWithCallout( + mxPaneId->getResourceURL(), + mxBorderCanvas, + aLocalBorderBox, + rUpdateBox, + msTitle, + maCalloutAnchor); + else + mxBorderPainter->paintBorder( + mxPaneId->getResourceURL(), + mxBorderCanvas, + aLocalBorderBox, + rUpdateBox, + msTitle); + } +} + + + + +void PresenterPaneBase::LayoutContextWindow (void) +{ + OSL_ASSERT(mxPaneId.is()); + OSL_ASSERT(mxBorderWindow.is()); + OSL_ASSERT(mxContentWindow.is()); + if (mxBorderPainter.is() && mxPaneId.is() && mxBorderWindow.is() && mxContentWindow.is()) + { + const awt::Rectangle aBorderBox (mxBorderWindow->getPosSize()); + const awt::Rectangle aInnerBox (mxBorderPainter->removeBorder( + mxPaneId->getResourceURL(), + aBorderBox, + drawing::framework::BorderType_TOTAL_BORDER)); + mxContentWindow->setPosSize( + aInnerBox.X - aBorderBox.X, + aInnerBox.Y - aBorderBox.Y, + aInnerBox.Width, + aInnerBox.Height, + awt::PosSize::POSSIZE); + } +} + + + + +bool PresenterPaneBase::IsVisible (void) const +{ + Reference<awt::XWindow2> xWindow2 (mxBorderPainter, UNO_QUERY); + if (xWindow2.is()) + return xWindow2->isVisible(); + + return false; +} + + + + +void PresenterPaneBase::ThrowIfDisposed (void) + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterPane object has already been disposed")), + static_cast<uno::XWeak*>(this)); + } +} + + + + +} } // end of namespace ::sd::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPaneBase.hxx b/sdext/source/presenter/PresenterPaneBase.hxx new file mode 100644 index 000000000000..16ea4e515299 --- /dev/null +++ b/sdext/source/presenter/PresenterPaneBase.hxx @@ -0,0 +1,176 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SD_PRESENTER_PRESENTER_PANE_BASE_HXX +#define SD_PRESENTER_PRESENTER_PANE_BASE_HXX + +#include "PresenterTheme.hxx" +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase4.hxx> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/XMouseListener.hpp> +#include <com/sun/star/awt/XMouseMotionListener.hpp> +#include <com/sun/star/awt/XWindowListener.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/drawing/framework/XPaneBorderPainter.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/util/Color.hpp> +#include <com/sun/star/rendering/XCanvas.hpp> +#include <rtl/ref.hxx> +#include <boost/noncopyable.hpp> + +namespace css = ::com::sun::star; +namespace cssu = ::com::sun::star::uno; + + +namespace sdext { namespace presenter { + +class PresenterController; +class PresenterTextView; + +namespace { + typedef ::cppu::WeakComponentImplHelper4 < + css::drawing::framework::XPane, + css::lang::XInitialization, + css::awt::XWindowListener, + css::awt::XPaintListener + > PresenterPaneBaseInterfaceBase; +} + + +/** Base class of the panes used by the presenter screen. Pane objects are + stored in the PresenterPaneContainer. Sizes and positions are + controlled by the PresenterWindowManager. Interactive positioning and + resizing is managed by the PresenterPaneBorderManager. Borders around + panes are painted by the PresenterPaneBorderPainter. +*/ +class PresenterPaneBase + : protected ::cppu::BaseMutex, + private ::boost::noncopyable, + public PresenterPaneBaseInterfaceBase +{ +public: + PresenterPaneBase ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~PresenterPaneBase (void); + + virtual void SAL_CALL disposing (void); + + css::uno::Reference<css::awt::XWindow> GetBorderWindow (void) const; + void SetBackground (const SharedBitmapDescriptor& rpBackground); + void SetTitle (const ::rtl::OUString& rsTitle); + ::rtl::OUString GetTitle (void) const; + css::uno::Reference<css::drawing::framework::XPaneBorderPainter> GetPaneBorderPainter (void) const; + void SetCalloutAnchor (const css::awt::Point& rAnchorPosition); + css::awt::Point GetCalloutAnchor (void) const; + + ::boost::shared_ptr<PresenterTextView> GetTextViewForTitle (void); + + // XInitialization + + virtual void SAL_CALL initialize (const css::uno::Sequence<css::uno::Any>& rArguments) + throw (css::uno::Exception, css::uno::RuntimeException); + + + // XResourceId + + virtual css::uno::Reference<css::drawing::framework::XResourceId> SAL_CALL getResourceId (void) + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isAnchorOnly (void) + throw (com::sun::star::uno::RuntimeException); + + + // XWindowListener + + virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // lang::XEventListener + + virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + +protected: + ::rtl::Reference<PresenterController> mpPresenterController; + css::uno::Reference<css::awt::XWindow> mxParentWindow; + css::uno::Reference<css::awt::XWindow> mxBorderWindow; + css::uno::Reference<css::rendering::XCanvas> mxBorderCanvas; + css::uno::Reference<css::awt::XWindow> mxContentWindow; + css::uno::Reference<css::rendering::XCanvas> mxContentCanvas; + css::uno::Reference<css::drawing::framework::XResourceId> mxPaneId; + css::uno::Reference<css::drawing::framework::XPaneBorderPainter> mxBorderPainter; + css::uno::Reference<css::drawing::XPresenterHelper> mxPresenterHelper; + ::rtl::OUString msTitle; + css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + SharedBitmapDescriptor mpViewBackground; + bool mbHasCallout; + css::awt::Point maCalloutAnchor; + + virtual void CreateCanvases ( + const css::uno::Reference<css::awt::XWindow>& rxParentWindow, + const css::uno::Reference<css::rendering::XSpriteCanvas>& rxParentCanvas) = 0; + + void CreateWindows ( + const css::uno::Reference<css::awt::XWindow>& rxParentWindow, + const bool bIsWindowVisibleOnCreation); + void PaintBorderBackground ( + const css::awt::Rectangle& rCenterBox, + const css::awt::Rectangle& rUpdateBox); + void PaintBorder (const css::awt::Rectangle& rUpdateRectangle); + void ToTop (void); + void LayoutContextWindow (void); + bool IsVisible (void) const; + + /** This method throws a DisposedException when the object has already been + disposed. + */ + void ThrowIfDisposed (void) + throw (css::lang::DisposedException); +}; + +} } // end of namespace ::sd::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPaneBorderManager.cxx b/sdext/source/presenter/PresenterPaneBorderManager.cxx new file mode 100644 index 000000000000..6150d0ce8914 --- /dev/null +++ b/sdext/source/presenter/PresenterPaneBorderManager.cxx @@ -0,0 +1,585 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +// The body of this file is only used when PresenterWindowManager defines +// the preprocessor symbol ENABLE_PANE_RESIZING, which by default is not the +// case. +#ifdef ENABLE_PANE_RESIZING + +#include "PresenterPaneBorderManager.hxx" +#include "PresenterController.hxx" +#include "PresenterPaintManager.hxx" +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/awt/SystemPointer.hpp> +#include <com/sun/star/awt/WindowAttribute.hpp> +#include <com/sun/star/awt/WindowDescriptor.hpp> +#include <com/sun/star/awt/WindowClass.hpp> +#include <com/sun/star/awt/XWindow2.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <cppuhelper/compbase1.hxx> +#include <osl/mutex.hxx> +#include <boost/weak_ptr.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace sdext { namespace presenter { + +//===== Service =============================================================== + + +OUString PresenterPaneBorderManager::getImplementationName_static (void) +{ + return OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.PresenterPaneBorderManager")); +} + + + + +Sequence<OUString> PresenterPaneBorderManager::getSupportedServiceNames_static (void) +{ + static const ::rtl::OUString sServiceName( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.PresenterPaneBorderManager")); + return Sequence<rtl::OUString>(&sServiceName, 1); +} + + + + +Reference<XInterface> PresenterPaneBorderManager::Create (const Reference<uno::XComponentContext>& rxContext) + SAL_THROW((css::uno::Exception)) +{ + return Reference<XInterface>(static_cast<XWeak*>( + new PresenterPaneBorderManager(rxContext, NULL))); +} + + + + +//===== PresenterPaneBorderManager ============================================ + +PresenterPaneBorderManager::PresenterPaneBorderManager ( + const Reference<XComponentContext>& rxContext, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterPaneBorderManagerInterfaceBase(m_aMutex), + mpPresenterController(rpPresenterController), + mxComponentContext(rxContext), + mxPresenterHelper(), + maWindowList(), + mnPointerType(), + maDragAnchor(), + meDragType(Outside), + mxOuterDragWindow(), + mxInnerDragWindow(), + mxPointer() +{ + Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager()); + if (xFactory.is()) + { + mxPointer = Reference<awt::XPointer>( + xFactory->createInstanceWithContext( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Pointer")), + rxContext), + UNO_QUERY_THROW); + + mxPresenterHelper = Reference<drawing::XPresenterHelper>( + xFactory->createInstanceWithContext( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.PresenterHelper")), + rxContext), + UNO_QUERY_THROW); + } +} + + + + +PresenterPaneBorderManager::~PresenterPaneBorderManager (void) +{ +} + + + + +void PresenterPaneBorderManager::disposing (void) +{ + WindowList::const_iterator iDescriptor; + for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor) + { + iDescriptor->first->removeMouseListener(this); + iDescriptor->first->removeMouseMotionListener(this); + } + maWindowList.clear(); +} + + + + +namespace { +const static sal_Int32 mnOutside = 0; +const static sal_Int32 mnLeft = 0x01; +const static sal_Int32 mnHorizontalCenter = 0x02; +const static sal_Int32 mnRight = 0x04; +const static sal_Int32 mnTop = 0x10; +const static sal_Int32 mnVerticalCenter = 0x20; +const static sal_Int32 mnBottom = 0x40; +} + +PresenterPaneBorderManager::BorderElement + PresenterPaneBorderManager::ClassifyBorderElementUnderMouse ( + const Reference<awt::XWindow>& rxOuterWindow, + const Reference<awt::XWindow>& rxInnerWindow, + const awt::Point aPosition) const +{ + OSL_ASSERT(rxOuterWindow.is()); + OSL_ASSERT(rxInnerWindow.is()); + + awt::Rectangle aOuterBox (rxOuterWindow->getPosSize()); + const awt::Rectangle aInnerBox (rxInnerWindow->getPosSize()); + + // Coordinates of the pointer position are given in the window + // coordinate system. Therefore the upper left corner of the outer box + // is the origin. + aOuterBox.X = 0; + aOuterBox.Y = 0; + + sal_Int32 nCode = 0; + + // Add horizontal classification to nCode. + if (aPosition.X < aInnerBox.X) + if (aPosition.X < aOuterBox.X) + nCode = mnOutside; + else + nCode = mnLeft; + else if (aPosition.X >= aInnerBox.X+aInnerBox.Width) + if (aPosition.X >= aOuterBox.X+aOuterBox.Width) + nCode = mnOutside; + else + nCode = mnRight; + else + nCode = mnHorizontalCenter; + + // Add vertical classification to nCode. + if (aPosition.Y < aInnerBox.Y) + if (aPosition.Y < aOuterBox.Y) + nCode |= mnOutside; + else + nCode |= mnTop; + else if (aPosition.Y >= aInnerBox.Y+aInnerBox.Height) + if (aPosition.Y >= aOuterBox.Y+aOuterBox.Height) + nCode |= mnOutside; + else + nCode |= mnBottom; + else + nCode |= mnVerticalCenter; + + // Translate bits in nCode into BorderElement value. + switch (nCode) + { + case mnOutside | mnOutside: + case mnOutside | mnLeft: + case mnOutside | mnRight: + case mnOutside | mnHorizontalCenter: + case mnTop | mnOutside: + case mnBottom | mnOutside: + case mnVerticalCenter | mnOutside: + default: + return Outside; + + case mnVerticalCenter | mnHorizontalCenter: + return Content; + + case mnTop | mnLeft: + return TopLeft; + + case mnTop | mnRight: + return TopRight; + + case mnTop | mnHorizontalCenter: + return Top; + + case mnBottom | mnLeft: + return BottomLeft; + + case mnBottom | mnRight: + return BottomRight; + + case mnBottom | mnHorizontalCenter: + return Bottom; + + case mnVerticalCenter | mnLeft: + return Left; + + case mnVerticalCenter | mnRight: + return Right; + } +} + + + + +//----- XInitialization ------------------------------------------------------- + +void SAL_CALL PresenterPaneBorderManager::initialize (const Sequence<Any>& rArguments) + throw (Exception, RuntimeException) +{ + ThrowIfDisposed(); + + if (rArguments.getLength()%2 == 1 && mxComponentContext.is()) + { + try + { + mxParentWindow = Reference<awt::XWindow>(rArguments[0], UNO_QUERY_THROW); + + // Get the outer and inner windows from the argument list and + // build a window list of it. + for (sal_Int32 nIndex=1; nIndex<rArguments.getLength(); nIndex+=2) + { + Reference<awt::XWindow> xOuterWindow (rArguments[nIndex], UNO_QUERY_THROW); + Reference<awt::XWindow> xInnerWindow (rArguments[nIndex+1], UNO_QUERY_THROW); + + maWindowList.push_back(WindowDescriptor(xOuterWindow,xInnerWindow)); + + xOuterWindow->addMouseListener(this); + xOuterWindow->addMouseMotionListener(this); + } + } + catch (RuntimeException&) + { + PresenterPaneBorderManager::disposing(); + throw; + } + } + else + { + throw RuntimeException( + OUString(RTL_CONSTASCII_USTRINGPARAM("PresenterPane: invalid number of arguments")), + static_cast<XWeak*>(this)); + } +} + + + + +//----- XMouseListener -------------------------------------------------------- + +void SAL_CALL PresenterPaneBorderManager::mousePressed (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + ThrowIfDisposed(); + ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex()); + + // Find window descriptor of the window that has been clicked. + WindowList::const_iterator iDescriptor; + for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor) + if (iDescriptor->first == rEvent.Source) + break; + + if (iDescriptor != maWindowList.end()) + { + // Prepare dragging. + mxOuterDragWindow = iDescriptor->first; + mxInnerDragWindow = iDescriptor->second; + OSL_ASSERT(mxOuterDragWindow.is() && mxInnerDragWindow.is()); + const awt::Rectangle aOuterBox (mxOuterDragWindow->getPosSize()); + maDragAnchor.X = rEvent.X + aOuterBox.X; + maDragAnchor.Y = rEvent.Y + aOuterBox.Y; + meDragType = ClassifyBorderElementUnderMouse( + mxOuterDragWindow, + mxInnerDragWindow, + awt::Point(rEvent.X, rEvent.Y)); + } +} + + + + +void SAL_CALL PresenterPaneBorderManager::mouseReleased (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); + ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex()); + + ReleaseMouse(mxOuterDragWindow); + meDragType = PresenterPaneBorderManager::Outside; + mxOuterDragWindow = NULL; + mxInnerDragWindow = NULL; +} + + + + +void SAL_CALL PresenterPaneBorderManager::mouseEntered (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterPaneBorderManager::mouseExited (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); + ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex()); + + ReleaseMouse(mxOuterDragWindow); + meDragType = PresenterPaneBorderManager::Outside; + mxOuterDragWindow = NULL; + mxInnerDragWindow = NULL; +} + + + + +//----- XMouseMotionListener -------------------------------------------------- + +void SAL_CALL PresenterPaneBorderManager::mouseMoved (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + ThrowIfDisposed(); + ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex()); + + WindowList::const_iterator iDescriptor; + for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor) + if (iDescriptor->first == rEvent.Source) + break; + if (iDescriptor != maWindowList.end()) + { + // Choose pointer shape according to position in the window border. + switch (ClassifyBorderElementUnderMouse( + iDescriptor->first, + iDescriptor->second, + awt::Point(rEvent.X,rEvent.Y))) + { + case PresenterPaneBorderManager::Top: + mnPointerType = awt::SystemPointer::MOVE; + break; + case PresenterPaneBorderManager::TopLeft: + mnPointerType = awt::SystemPointer::WINDOW_NWSIZE; + break; + case PresenterPaneBorderManager::TopRight: + mnPointerType = awt::SystemPointer::WINDOW_NESIZE; + break; + case PresenterPaneBorderManager::Left: + mnPointerType = awt::SystemPointer::WINDOW_WSIZE; + break; + case PresenterPaneBorderManager::Right: + mnPointerType = awt::SystemPointer::WINDOW_ESIZE; + break; + case PresenterPaneBorderManager::BottomLeft: + mnPointerType = awt::SystemPointer::WINDOW_SWSIZE; + break; + case PresenterPaneBorderManager::BottomRight: + mnPointerType = awt::SystemPointer::WINDOW_SESIZE; + break; + case PresenterPaneBorderManager::Bottom: + mnPointerType = awt::SystemPointer::WINDOW_SSIZE; + break; + + case PresenterPaneBorderManager::Content: + case PresenterPaneBorderManager::Outside: + default: + mnPointerType = awt::SystemPointer::ARROW; + break; + } + + // Make the pointer shape visible. + Reference<awt::XWindowPeer> xPeer (iDescriptor->first, UNO_QUERY); + if (xPeer.is()) + { + if (mxPointer.is()) + mxPointer->setType(mnPointerType); + xPeer->setPointer(mxPointer); + } + } +} + + + + +void SAL_CALL PresenterPaneBorderManager::mouseDragged (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + ThrowIfDisposed(); + ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex()); + + if ( ! mxOuterDragWindow.is()) + return; + + CaptureMouse(mxOuterDragWindow); + + const awt::Rectangle aOldBox (mxOuterDragWindow->getPosSize()); + const sal_Int32 nX = rEvent.X + aOldBox.X; + const sal_Int32 nY = rEvent.Y + aOldBox.Y; + const sal_Int32 nDiffX = nX - maDragAnchor.X; + const sal_Int32 nDiffY = nY - maDragAnchor.Y; + maDragAnchor.X = nX; + maDragAnchor.Y = nY; + + const sal_Int32 nOldRight = aOldBox.X + aOldBox.Width; + const sal_Int32 nOldBottom = aOldBox.Y + aOldBox.Height; + + awt::Rectangle aBox (aOldBox); + sal_Int32 nRight = aBox.X + aBox.Width; + sal_Int32 nBottom = aBox.Y + aBox.Height; + + // Update position and/or size according to initial pointer position + // inside the window border. + switch (meDragType) + { + case PresenterPaneBorderManager::Top: + aBox.X += nDiffX; aBox.Y += nDiffY; + nRight += nDiffX; nBottom += nDiffY; + break; + case PresenterPaneBorderManager::TopLeft: + aBox.X += nDiffX; aBox.Y += nDiffY; + break; + case PresenterPaneBorderManager::TopRight: + nRight += nDiffX; aBox.Y += nDiffY; + break; + case PresenterPaneBorderManager::Left: + aBox.X += nDiffX; + break; + case PresenterPaneBorderManager::Right: + nRight += nDiffX; + break; + case PresenterPaneBorderManager::BottomLeft: + aBox.X += nDiffX; nBottom += nDiffY; + break; + case PresenterPaneBorderManager::BottomRight: + nRight += nDiffX; nBottom += nDiffY; + break; + case PresenterPaneBorderManager::Bottom: + nBottom += nDiffY; + break; + default: break; + } + + aBox.Width = nRight - aBox.X; + aBox.Height = nBottom - aBox.Y; + if (aBox.Width > 20 + && aBox.Height > 20) + { + // Set position and/or size of the border window to the new values. + sal_Int16 nFlags (0); + if (aBox.X != aOldBox.X) + nFlags |= awt::PosSize::X; + if (aBox.Y != aOldBox.Y) + nFlags |= awt::PosSize::Y; + if (aBox.Width != aOldBox.Width) + nFlags |= awt::PosSize::WIDTH; + if (aBox.Height != aOldBox.Height) + nFlags |= awt::PosSize::HEIGHT; + mxOuterDragWindow->setPosSize(aBox.X, aBox.Y, aBox.Width, aBox.Height, nFlags); + + // Invalidate that is or was covered by the border window before and + // after the move/resize. + if (mpPresenterController.get() != NULL) + { + const sal_Int32 nLeft = ::std::min(aOldBox.X,aBox.X); + const sal_Int32 nTop = ::std::min(aOldBox.Y,aBox.Y); + const sal_Int32 nWidth = ::std::max(nOldRight,nRight) - nLeft; + const sal_Int32 nHeight = ::std::max(nOldBottom,nBottom) - nTop; + + OSL_ASSERT(mpPresenterController->GetPaintManager().get()!=NULL); + mpPresenterController->GetPaintManager()->Invalidate( + mxParentWindow, + ::awt::Rectangle(nLeft,nTop,nWidth-1,nHeight-1)); + } + } +} + + + + +//----- lang::XEventListener -------------------------------------------------- + +void SAL_CALL PresenterPaneBorderManager::disposing (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + WindowList::iterator iDescriptor; + for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor) + if (iDescriptor->first == rEvent.Source) + { + maWindowList.erase(iDescriptor); + break; + } +} + + + + +//----------------------------------------------------------------------------- + + +void PresenterPaneBorderManager::CaptureMouse (const Reference<awt::XWindow>& rxWindow) +{ + if (mxPresenterHelper.is()) + mxPresenterHelper->captureMouse(rxWindow); +} + + + + +void PresenterPaneBorderManager::ReleaseMouse (const Reference<awt::XWindow>& rxWindow) +{ + if (mxPresenterHelper.is()) + mxPresenterHelper->releaseMouse(rxWindow); +} + + + + +void PresenterPaneBorderManager::ThrowIfDisposed (void) + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterPaneBorderManager object has already been disposed")), + static_cast<uno::XWeak*>(this)); + } +} + + + + +} } // end of namespace ::sd::presenter + +#endif // ENABLE_PANE_RESIZING + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPaneBorderManager.hxx b/sdext/source/presenter/PresenterPaneBorderManager.hxx new file mode 100644 index 000000000000..b9b25f330cfa --- /dev/null +++ b/sdext/source/presenter/PresenterPaneBorderManager.hxx @@ -0,0 +1,176 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_PANE_BORDER_MANAGER_HXX +#define SDEXT_PRESENTER_PRESENTER_PANE_BORDER_MANAGER_HXX + +// The body of this file is only used when PresenterWindowManager defines +// the preprocessor symbol ENABLE_PANE_RESIZING, which by default is not the +// case. +#ifdef ENABLE_PANE_RESIZING + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase3.hxx> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/awt/XGraphics.hpp> +#include <com/sun/star/awt/XMouseListener.hpp> +#include <com/sun/star/awt/XMouseMotionListener.hpp> +#include <com/sun/star/awt/XPointer.hpp> +#include <com/sun/star/awt/XWindowListener.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/rendering/XCanvas.hpp> +#include <rtl/ref.hxx> +#include <tools/svborder.hxx> +#include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> + +namespace css = ::com::sun::star; + + +namespace sdext { namespace presenter { + +class PresenterController; + +namespace { + typedef ::cppu::WeakComponentImplHelper3 < + css::lang::XInitialization, + css::awt::XMouseListener, + css::awt::XMouseMotionListener + > PresenterPaneBorderManagerInterfaceBase; +} + + +/** Manage the interactive moving and resizing of panes. +*/ +class PresenterPaneBorderManager + : private ::boost::noncopyable, + protected ::cppu::BaseMutex, + public PresenterPaneBorderManagerInterfaceBase +{ +public: + PresenterPaneBorderManager ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~PresenterPaneBorderManager (void); + + virtual void SAL_CALL disposing (void); + + + static ::rtl::OUString getImplementationName_static (void); + static css::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static (void); + static css::uno::Reference<css::uno::XInterface> Create( + const css::uno::Reference<css::uno::XComponentContext>& rxContext) + SAL_THROW((css::uno::Exception)); + + + // XInitialization + + virtual void SAL_CALL initialize (const css::uno::Sequence<css::uno::Any>& rArguments) + throw (css::uno::Exception, css::uno::RuntimeException); + + + // XMouseListener + + virtual void SAL_CALL mousePressed (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseReleased (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseEntered (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseExited (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XMouseMotionListener + + virtual void SAL_CALL mouseMoved (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseDragged (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + + // lang::XEventListener + virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + +private: + enum BorderElement { Top, TopLeft, TopRight, Left, Right, BottomLeft, BottomRight, Bottom, + Content, Outside }; + + ::rtl::Reference<PresenterController> mpPresenterController; + css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + css::uno::Reference<css::drawing::XPresenterHelper> mxPresenterHelper; + /** The parent window is stored so that it can be invalidated when one + of its children is resized or moved. It is assumed to be the parent + window of all outer windows stored in maWindowList. + */ + css::uno::Reference<css::awt::XWindow> mxParentWindow; + typedef ::std::pair<css::uno::Reference<css::awt::XWindow>, + css::uno::Reference<css::awt::XWindow> > WindowDescriptor; + typedef ::std::vector<WindowDescriptor> WindowList; + WindowList maWindowList; + + sal_Int32 mnPointerType; + css::awt::Point maDragAnchor; + BorderElement meDragType; + css::uno::Reference<css::awt::XWindow> mxOuterDragWindow; + css::uno::Reference<css::awt::XWindow> mxInnerDragWindow; + css::uno::Reference<css::awt::XPointer> mxPointer; + + BorderElement ClassifyBorderElementUnderMouse ( + const css::uno::Reference<css::awt::XWindow>& rxOuterDragWindow, + const css::uno::Reference<css::awt::XWindow>& rxInnerDragWindow, + const css::awt::Point aPosition) const; + void CreateWindows (const css::uno::Reference<css::awt::XWindow>& rxParentWindow); + void CaptureMouse (const css::uno::Reference<css::awt::XWindow>& rxWindow); + void ReleaseMouse (const css::uno::Reference<css::awt::XWindow>& rxWindow); + + /** This method throws a DisposedException when the object has already been + disposed. + */ + void ThrowIfDisposed (void) + throw (css::lang::DisposedException); +}; + +} } // end of namespace ::sd::presenter + +#endif // ENABLE_PANE_RESIZING + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPaneBorderPainter.cxx b/sdext/source/presenter/PresenterPaneBorderPainter.cxx new file mode 100644 index 000000000000..7a27dda1806b --- /dev/null +++ b/sdext/source/presenter/PresenterPaneBorderPainter.cxx @@ -0,0 +1,1104 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterPaneBorderPainter.hxx" +#include "PresenterCanvasHelper.hxx" +#include "PresenterConfigurationAccess.hxx" +#include "PresenterGeometryHelper.hxx" +#include "PresenterTheme.hxx" +#include <com/sun/star/awt/FontDescriptor.hpp> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/awt/SimpleFontMetric.hpp> +#include <com/sun/star/awt/XFont.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/graphic/XGraphicRenderer.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/FillRule.hpp> +#include <com/sun/star/rendering/TextDirection.hpp> +#include <com/sun/star/rendering/XIntegerBitmap.hpp> +#include <com/sun/star/rendering/XSpriteCanvas.hpp> +#include <map> +#include <vector> +#include <boost/shared_ptr.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define A2S(s) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))) + +namespace sdext { namespace presenter { + +namespace { + class BorderSize + { + public: + BorderSize (void); + BorderSize (const BorderSize& rBorderSize); + BorderSize& operator= (const BorderSize& rBoderSize); + sal_Int32 mnLeft; + sal_Int32 mnTop; + sal_Int32 mnRight; + sal_Int32 mnBottom; + }; + + class RendererPaneStyle + { + public: + RendererPaneStyle ( + const ::boost::shared_ptr<PresenterTheme>& rpTheme, + const OUString& rsStyleName); + + awt::Rectangle AddBorder ( + const awt::Rectangle& rBox, + drawing::framework::BorderType eBorderType) const; + awt::Rectangle RemoveBorder ( + const awt::Rectangle& rBox, + drawing::framework::BorderType eBorderType) const; + const Reference<rendering::XCanvasFont> GetFont ( + const Reference<rendering::XCanvas>& rxCanvas) const; + + SharedBitmapDescriptor mpTopLeft; + SharedBitmapDescriptor mpTop; + SharedBitmapDescriptor mpTopRight; + SharedBitmapDescriptor mpLeft; + SharedBitmapDescriptor mpRight; + SharedBitmapDescriptor mpBottomLeft; + SharedBitmapDescriptor mpBottom; + SharedBitmapDescriptor mpBottomRight; + SharedBitmapDescriptor mpBottomCallout; + SharedBitmapDescriptor mpBackground; + SharedBitmapDescriptor mpEmpty; + PresenterTheme::SharedFontDescriptor mpFont; + sal_Int32 mnFontXOffset; + sal_Int32 mnFontYOffset; + enum Anchor { AnchorLeft, AnchorRight, AnchorCenter } meFontAnchor; + BorderSize maInnerBorderSize; + BorderSize maOuterBorderSize; + BorderSize maTotalBorderSize; + enum Side { Left, Top, Right, Bottom }; + private: + void UpdateBorderSizes (void); + SharedBitmapDescriptor GetBitmap( + const ::boost::shared_ptr<PresenterTheme>& rpTheme, + const OUString& rsStyleName, + const OUString& rsBitmapName); + }; +} + + + +class PresenterPaneBorderPainter::Renderer +{ +public: + Renderer ( + const Reference<XComponentContext>& rxContext, + const ::boost::shared_ptr<PresenterTheme>& rpTheme); + ~Renderer (void); + + void SetCanvas (const Reference<rendering::XCanvas>& rxCanvas); + void PaintBorder ( + const OUString& rsTitle, + const awt::Rectangle& rBBox, + const awt::Rectangle& rUpdateBox, + const OUString& rsPaneURL); + void PaintTitle ( + const OUString& rsTitle, + const ::boost::shared_ptr<RendererPaneStyle>& rpStyle, + const awt::Rectangle& rUpdateBox, + const awt::Rectangle& rOuterBox, + const awt::Rectangle& rInnerBox, + const bool bPaintBackground); + void SetupClipping ( + const awt::Rectangle& rUpdateBox, + const awt::Rectangle& rOuterBox, + const OUString& rsPaneStyleName); + ::boost::shared_ptr<RendererPaneStyle> GetRendererPaneStyle (const OUString& rsResourceURL); + void SetCalloutAnchor ( + const awt::Point& rCalloutAnchor); + +private: + ::boost::shared_ptr<PresenterTheme> mpTheme; + typedef ::std::map<OUString, ::boost::shared_ptr<RendererPaneStyle> > RendererPaneStyleContainer; + RendererPaneStyleContainer maRendererPaneStyles; + Reference<rendering::XCanvas> mxCanvas; + Reference<drawing::XPresenterHelper> mxPresenterHelper; + css::rendering::ViewState maViewState; + Reference<rendering::XPolyPolygon2D> mxViewStateClip; + bool mbHasCallout; + awt::Point maCalloutAnchor; + + void PaintBitmap( + const awt::Rectangle& rBox, + const awt::Rectangle& rUpdateBox, + const sal_Int32 nXPosition, + const sal_Int32 nYPosition, + const sal_Int32 nStartOffset, + const sal_Int32 nEndOffset, + const bool bExpand, + const SharedBitmapDescriptor& rpBitmap, + const SharedBitmapDescriptor& rpBackgroundBitmap); +}; + + + + +// ===== PresenterPaneBorderPainter =========================================== + +PresenterPaneBorderPainter::PresenterPaneBorderPainter ( + const Reference<XComponentContext>& rxContext) + : PresenterPaneBorderPainterInterfaceBase(m_aMutex), + mxContext(rxContext), + mpTheme(), + mpRenderer() +{ +} + + + + +PresenterPaneBorderPainter::~PresenterPaneBorderPainter (void) +{ +} + + + + +//----- XPaneBorderPainter ---------------------------------------------------- + +awt::Rectangle SAL_CALL PresenterPaneBorderPainter::addBorder ( + const rtl::OUString& rsPaneBorderStyleName, + const css::awt::Rectangle& rRectangle, + drawing::framework::BorderType eBorderType) + throw(css::uno::RuntimeException) +{ + ThrowIfDisposed(); + + ProvideTheme(); + + return AddBorder(rsPaneBorderStyleName, rRectangle, eBorderType); +} + + + + +awt::Rectangle SAL_CALL PresenterPaneBorderPainter::removeBorder ( + const rtl::OUString& rsPaneBorderStyleName, + const css::awt::Rectangle& rRectangle, + drawing::framework::BorderType eBorderType) + throw(css::uno::RuntimeException) +{ + ThrowIfDisposed(); + + ProvideTheme(); + + return RemoveBorder(rsPaneBorderStyleName, rRectangle, eBorderType); +} + + + + +void SAL_CALL PresenterPaneBorderPainter::paintBorder ( + const rtl::OUString& rsPaneBorderStyleName, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rOuterBorderRectangle, + const css::awt::Rectangle& rRepaintArea, + const rtl::OUString& rsTitle) + throw(css::uno::RuntimeException) +{ + ThrowIfDisposed(); + + // Early reject paints completely outside the repaint area. + if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width + || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height + || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X + || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y) + { + return; + } + ProvideTheme(rxCanvas); + + if (mpRenderer.get() != NULL) + { + mpRenderer->SetCanvas(rxCanvas); + mpRenderer->SetupClipping( + rRepaintArea, + rOuterBorderRectangle, + rsPaneBorderStyleName); + mpRenderer->PaintBorder( + rsTitle, + rOuterBorderRectangle, + rRepaintArea, + rsPaneBorderStyleName); + } +} + + + + +void SAL_CALL PresenterPaneBorderPainter::paintBorderWithCallout ( + const rtl::OUString& rsPaneBorderStyleName, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rOuterBorderRectangle, + const css::awt::Rectangle& rRepaintArea, + const rtl::OUString& rsTitle, + const css::awt::Point& rCalloutAnchor) + throw(css::uno::RuntimeException) +{ + ThrowIfDisposed(); + + // Early reject paints completely outside the repaint area. + if (rRepaintArea.X >= rOuterBorderRectangle.X+rOuterBorderRectangle.Width + || rRepaintArea.Y >= rOuterBorderRectangle.Y+rOuterBorderRectangle.Height + || rRepaintArea.X+rRepaintArea.Width <= rOuterBorderRectangle.X + || rRepaintArea.Y+rRepaintArea.Height <= rOuterBorderRectangle.Y) + { + return; + } + ProvideTheme(rxCanvas); + + if (mpRenderer.get() != NULL) + { + mpRenderer->SetCanvas(rxCanvas); + mpRenderer->SetupClipping( + rRepaintArea, + rOuterBorderRectangle, + rsPaneBorderStyleName); + mpRenderer->SetCalloutAnchor(rCalloutAnchor); + mpRenderer->PaintBorder( + rsTitle, + rOuterBorderRectangle, + rRepaintArea, + rsPaneBorderStyleName); + } +} + + + + +awt::Point SAL_CALL PresenterPaneBorderPainter::getCalloutOffset ( + const rtl::OUString& rsPaneBorderStyleName) + throw(css::uno::RuntimeException) +{ + ThrowIfDisposed(); + ProvideTheme(); + if (mpRenderer.get() != NULL) + { + const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle( + mpRenderer->GetRendererPaneStyle(rsPaneBorderStyleName)); + if (pRendererPaneStyle.get() != NULL + && pRendererPaneStyle->mpBottomCallout.get() != NULL) + { + return awt::Point ( + 0, + pRendererPaneStyle->mpBottomCallout->mnHeight + - pRendererPaneStyle->mpBottomCallout->mnYHotSpot); + } + } + + return awt::Point(0,0); +} + + + + +//----------------------------------------------------------------------------- + +bool PresenterPaneBorderPainter::ProvideTheme (const Reference<rendering::XCanvas>& rxCanvas) +{ + bool bModified (false); + + if ( ! mxContext.is()) + return false; + + if (mpTheme.get() != NULL) + { + // Check if the theme already has a canvas. + if ( ! mpTheme->HasCanvas()) + { + mpTheme->ProvideCanvas(rxCanvas); + bModified = true; + } + } + else + { + mpTheme.reset(new PresenterTheme(mxContext, OUString(), rxCanvas)); + bModified = true; + } + + if (mpTheme.get() != NULL && bModified) + { + if (mpRenderer.get() == NULL) + mpRenderer.reset(new Renderer(mxContext, mpTheme)); + else + mpRenderer->SetCanvas(rxCanvas); + } + + return bModified; +} + + + + +bool PresenterPaneBorderPainter::ProvideTheme (void) +{ + if (mpTheme.get() == NULL) + { + // Create a theme without bitmaps (no canvas => no bitmaps). + return ProvideTheme(NULL); + } + else + { + // When there already is a theme then without a canvas we can not + // add anything new. + return false; + } +} + + + + +bool PresenterPaneBorderPainter::HasTheme (void) const +{ + return mpTheme.get()!=NULL && mpRenderer.get()!=NULL; +} + + + + +void PresenterPaneBorderPainter::SetTheme (const ::boost::shared_ptr<PresenterTheme>& rpTheme) +{ + mpTheme = rpTheme; + if (mpRenderer.get() == NULL) + mpRenderer.reset(new Renderer(mxContext, mpTheme)); +} + + + + +awt::Rectangle PresenterPaneBorderPainter::AddBorder ( + const ::rtl::OUString& rsPaneURL, + const awt::Rectangle& rInnerBox, + const css::drawing::framework::BorderType eBorderType) const +{ + if (mpRenderer.get() != NULL) + { + const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL)); + if (pRendererPaneStyle.get() != NULL) + return pRendererPaneStyle->AddBorder(rInnerBox, eBorderType); + } + return rInnerBox; +} + + + + +awt::Rectangle PresenterPaneBorderPainter::RemoveBorder ( + const ::rtl::OUString& rsPaneURL, + const css::awt::Rectangle& rOuterBox, + const css::drawing::framework::BorderType eBorderType) const +{ + if (mpRenderer.get() != NULL) + { + const ::boost::shared_ptr<RendererPaneStyle> pRendererPaneStyle(mpRenderer->GetRendererPaneStyle(rsPaneURL)); + if (pRendererPaneStyle.get() != NULL) + return pRendererPaneStyle->RemoveBorder(rOuterBox, eBorderType); + } + return rOuterBox; +} + + + + +void PresenterPaneBorderPainter::ThrowIfDisposed (void) const + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterPaneBorderPainter object has already been disposed")), + const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + } +} + + + + +//===== PresenterPaneBorderPainter::Renderer ===================================== + + +PresenterPaneBorderPainter::Renderer::Renderer ( + const Reference<XComponentContext>& rxContext, + const ::boost::shared_ptr<PresenterTheme>& rpTheme) + : mpTheme(rpTheme), + maRendererPaneStyles(), + mxCanvas(), + mxPresenterHelper(), + maViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL), + mxViewStateClip(), + mbHasCallout(false), + maCalloutAnchor() +{ + (void)rxContext; + + Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager()); + if (xFactory.is()) + { + mxPresenterHelper = Reference<drawing::XPresenterHelper>( + xFactory->createInstanceWithContext( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.PresenterHelper")), + rxContext), + UNO_QUERY_THROW); + } +} + + + + +PresenterPaneBorderPainter::Renderer::~Renderer (void) +{ +} + + + + +void PresenterPaneBorderPainter::Renderer::SetCanvas (const Reference<rendering::XCanvas>& rxCanvas) +{ + if (mxCanvas != rxCanvas) + { + mxCanvas = rxCanvas; + } +} + + + + +void PresenterPaneBorderPainter::Renderer::PaintBorder ( + const OUString& rsTitle, + const awt::Rectangle& rBBox, + const awt::Rectangle& rUpdateBox, + const OUString& rsPaneURL) +{ + if ( ! mxCanvas.is()) + return; + + // Create the outer and inner border of the, ahm, border. + ::boost::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneURL)); + if (pStyle.get() == NULL) + return; + + awt::Rectangle aOuterBox (rBBox); + awt::Rectangle aCenterBox ( + pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_OUTER_BORDER)); + awt::Rectangle aInnerBox ( + pStyle->RemoveBorder(aOuterBox, drawing::framework::BorderType_TOTAL_BORDER)); + + // Prepare references for all used bitmaps. + SharedBitmapDescriptor pTop (pStyle->mpTop); + SharedBitmapDescriptor pTopLeft (pStyle->mpTopLeft); + SharedBitmapDescriptor pTopRight (pStyle->mpTopRight); + SharedBitmapDescriptor pLeft (pStyle->mpLeft); + SharedBitmapDescriptor pRight (pStyle->mpRight); + SharedBitmapDescriptor pBottomLeft (pStyle->mpBottomLeft); + SharedBitmapDescriptor pBottomRight (pStyle->mpBottomRight); + SharedBitmapDescriptor pBottom (pStyle->mpBottom); + SharedBitmapDescriptor pBackground (pStyle->mpBackground); + + // Paint the sides. + PaintBitmap(aCenterBox, rUpdateBox, 0,-1, + pTopLeft->mnXOffset, pTopRight->mnXOffset, true, pTop, pBackground); + PaintBitmap(aCenterBox, rUpdateBox, -1,0, + pTopLeft->mnYOffset, pBottomLeft->mnYOffset, true, pLeft, pBackground); + PaintBitmap(aCenterBox, rUpdateBox, +1,0, + pTopRight->mnYOffset, pBottomRight->mnYOffset, true, pRight, pBackground); + if (mbHasCallout && pStyle->mpBottomCallout->GetNormalBitmap().is()) + { + const sal_Int32 nCalloutWidth (pStyle->mpBottomCallout->mnWidth); + sal_Int32 nCalloutX (maCalloutAnchor.X - pStyle->mpBottomCallout->mnXHotSpot + - (aCenterBox.X - aOuterBox.X)); + if (nCalloutX < pBottomLeft->mnXOffset + aCenterBox.X) + nCalloutX = pBottomLeft->mnXOffset + aCenterBox.X; + if (nCalloutX > pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width) + nCalloutX = pBottomRight->mnXOffset + aCenterBox.X + aCenterBox.Width; + // Paint bottom callout. + PaintBitmap(aCenterBox, rUpdateBox, 0,+1, nCalloutX,0, false, pStyle->mpBottomCallout, pBackground); + // Paint regular bottom bitmap left and right. + PaintBitmap(aCenterBox, rUpdateBox, 0,+1, + pBottomLeft->mnXOffset, nCalloutX-aCenterBox.Width, true, pBottom, pBackground); + PaintBitmap(aCenterBox, rUpdateBox, 0,+1, + nCalloutX+nCalloutWidth, pBottomRight->mnXOffset, true, pBottom, pBackground); + } + else + { + // Stretch the bottom bitmap over the full width. + PaintBitmap(aCenterBox, rUpdateBox, 0,+1, + pBottomLeft->mnXOffset, pBottomRight->mnXOffset, true, pBottom, pBackground); + } + + // Paint the corners. + PaintBitmap(aCenterBox, rUpdateBox, -1,-1, 0,0, false, pTopLeft, pBackground); + PaintBitmap(aCenterBox, rUpdateBox, +1,-1, 0,0, false, pTopRight, pBackground); + PaintBitmap(aCenterBox, rUpdateBox, -1,+1, 0,0, false, pBottomLeft, pBackground); + PaintBitmap(aCenterBox, rUpdateBox, +1,+1, 0,0, false, pBottomRight, pBackground); + + // Paint the title. + PaintTitle(rsTitle, pStyle, rUpdateBox, aOuterBox, aInnerBox, false); + + // In a double buffering environment request to make the changes visible. + Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); + if (xSpriteCanvas.is()) + xSpriteCanvas->updateScreen(sal_False); +} + + + + +void PresenterPaneBorderPainter::Renderer::PaintTitle ( + const OUString& rsTitle, + const ::boost::shared_ptr<RendererPaneStyle>& rpStyle, + const awt::Rectangle& rUpdateBox, + const awt::Rectangle& rOuterBox, + const awt::Rectangle& rInnerBox, + bool bPaintBackground) +{ + if ( ! mxCanvas.is()) + return; + + if (rsTitle.getLength() == 0) + return; + + Reference<rendering::XCanvasFont> xFont (rpStyle->GetFont(mxCanvas)); + if ( ! xFont.is()) + return; + + rendering::StringContext aContext ( + rsTitle, + 0, + rsTitle.getLength()); + Reference<rendering::XTextLayout> xLayout (xFont->createTextLayout( + aContext, + rendering::TextDirection::WEAK_LEFT_TO_RIGHT, + 0)); + if ( ! xLayout.is()) + return; + + geometry::RealRectangle2D aBox (xLayout->queryTextBounds()); + const double nTextHeight = aBox.Y2 - aBox.Y1; + const double nTextWidth = aBox.X2 - aBox.X1; + double nX = rInnerBox.X + (rInnerBox.Width - nTextWidth)/2; + const sal_Int32 nTitleBarHeight = rInnerBox.Y - rOuterBox.Y - 1; + double nY = rOuterBox.Y + (nTitleBarHeight - nTextHeight) / 2 - aBox.Y1; + if (nY >= rInnerBox.Y) + nY = rInnerBox.Y - 1; + switch (rpStyle->meFontAnchor) + { + default: + case RendererPaneStyle::AnchorLeft: + nX = rInnerBox.X; + break; + case RendererPaneStyle::AnchorRight: + nX = rInnerBox.X + rInnerBox.Width - nTextWidth; + break; + case RendererPaneStyle::AnchorCenter: + nX = rInnerBox.X + (rInnerBox.Width - nTextWidth)/2; + break; + } + nX += rpStyle->mnFontXOffset; + nY += rpStyle->mnFontYOffset; + + if (rUpdateBox.X >= nX+nTextWidth + || rUpdateBox.Y >= nY+nTextHeight + || rUpdateBox.X+rUpdateBox.Width <= nX + || rUpdateBox.Y+rUpdateBox.Height <= nY) + { + return; + } + + rendering::RenderState aRenderState( + geometry::AffineMatrix2D(1,0,nX, 0,1,nY), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + + if (bPaintBackground) + { + PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x00ffffff)); + Sequence<Sequence<geometry::RealPoint2D> > aPolygons(1); + aPolygons[0] = Sequence<geometry::RealPoint2D>(4); + aPolygons[0][0] = geometry::RealPoint2D(0, -nTextHeight); + aPolygons[0][1] = geometry::RealPoint2D(0, 0); + aPolygons[0][2] = geometry::RealPoint2D(nTextWidth, 0); + aPolygons[0][3] = geometry::RealPoint2D(nTextWidth, -nTextHeight); + Reference<rendering::XPolyPolygon2D> xPolygon ( + mxCanvas->getDevice()->createCompatibleLinePolyPolygon(aPolygons), UNO_QUERY); + if (xPolygon.is()) + xPolygon->setClosed(0, sal_True); + mxCanvas->fillPolyPolygon( + xPolygon, + maViewState, + aRenderState); + } + else + { + PresenterCanvasHelper::SetDeviceColor( + aRenderState, + rpStyle->mpFont->mnColor); + + mxCanvas->drawText( + aContext, + xFont, + maViewState, + aRenderState, + rendering::TextDirection::WEAK_LEFT_TO_RIGHT); + } +} + + + +::boost::shared_ptr<RendererPaneStyle> + PresenterPaneBorderPainter::Renderer::GetRendererPaneStyle (const OUString& rsResourceURL) +{ + OSL_ASSERT(mpTheme.get()!=NULL); + + RendererPaneStyleContainer::const_iterator iStyle (maRendererPaneStyles.find(rsResourceURL)); + if (iStyle == maRendererPaneStyles.end()) + { + OUString sPaneStyleName (RTL_CONSTASCII_USTRINGPARAM("DefaultRendererPaneStyle")); + + // Get pane layout name for resource URL. + const OUString sStyleName (mpTheme->GetStyleName(rsResourceURL)); + if (sStyleName.getLength() > 0) + sPaneStyleName = sStyleName; + + // Create a new pane style object and initialize it with bitmaps. + ::boost::shared_ptr<RendererPaneStyle> pStyle ( + new RendererPaneStyle(mpTheme,sPaneStyleName)); + iStyle = maRendererPaneStyles.insert( + RendererPaneStyleContainer::value_type(rsResourceURL, pStyle)).first; + } + if (iStyle != maRendererPaneStyles.end()) + return iStyle->second; + else + return ::boost::shared_ptr<RendererPaneStyle>(); +} + + + + +void PresenterPaneBorderPainter::Renderer::SetCalloutAnchor ( + const awt::Point& rCalloutAnchor) +{ + mbHasCallout = true; + maCalloutAnchor = rCalloutAnchor; +} + + + + +void PresenterPaneBorderPainter::Renderer::PaintBitmap( + const awt::Rectangle& rBox, + const awt::Rectangle& rUpdateBox, + const sal_Int32 nXPosition, + const sal_Int32 nYPosition, + const sal_Int32 nStartOffset, + const sal_Int32 nEndOffset, + const bool bExpand, + const SharedBitmapDescriptor& rpBitmap, + const SharedBitmapDescriptor& rpBackgroundBitmap) +{ + (void)rpBackgroundBitmap; + + bool bUseCanvas (mxCanvas.is()); + if ( ! bUseCanvas) + return; + + if (rpBitmap->mnWidth<=0 || rpBitmap->mnHeight<=0) + return; + + Reference<rendering::XBitmap> xBitmap (rpBitmap->GetNormalBitmap(), UNO_QUERY); + if ( ! xBitmap.is()) + return; + + // Calculate position, and for side bitmaps, the size. + sal_Int32 nX = 0; + sal_Int32 nY = 0; + sal_Int32 nW = rpBitmap->mnWidth; + sal_Int32 nH = rpBitmap->mnHeight; + if (nXPosition < 0) + { + nX = rBox.X - rpBitmap->mnWidth + rpBitmap->mnXOffset; + } + else if (nXPosition > 0) + { + nX = rBox.X + rBox.Width + rpBitmap->mnXOffset; + } + else + { + nX = rBox.X + nStartOffset; + if (bExpand) + nW = rBox.Width - nStartOffset + nEndOffset; + } + + if (nYPosition < 0) + { + nY = rBox.Y - rpBitmap->mnHeight + rpBitmap->mnYOffset; + } + else if (nYPosition > 0) + { + nY = rBox.Y + rBox.Height + rpBitmap->mnYOffset; + } + else + { + nY = rBox.Y + nStartOffset; + if (bExpand) + nH = rBox.Height - nStartOffset + nEndOffset; + } + + // Do not paint when bitmap area does not intersect with update box. + if (nX >= rUpdateBox.X + rUpdateBox.Width + || nX+nW <= rUpdateBox.X + || nY >= rUpdateBox.Y + rUpdateBox.Height + || nY+nH <= rUpdateBox.Y) + { + return; + } + + /* + Reference<rendering::XBitmap> xMaskedBitmap ( + PresenterBitmapHelper::FillMaskedWithColor ( + mxCanvas, + Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY), + rBitmap.mxMaskBitmap, + 0x00ff0000, + rBackgroundBitmap.maReplacementColor)); + if (xMaskedBitmap.is()) + xBitmap = xMaskedBitmap; + else if (rBitmap.mxMaskBitmap.is() && mxPresenterHelper.is()) + { + const static sal_Int32 nOutsideMaskColor (0x00ff0000); + Reference<rendering::XIntegerBitmap> xMask ( + mxPresenterHelper->createMask( + mxCanvas, + rBitmap.mxMaskBitmap, + nOutsideMaskColor, + false)); + xBitmap = mxPresenterHelper->applyBitmapMaskWithColor( + mxCanvas, + Reference<rendering::XIntegerBitmap>(xBitmap, UNO_QUERY), + xMask, + rBackgroundBitmap.maReplacementColor); + } + */ + rendering::RenderState aRenderState ( + geometry::AffineMatrix2D( + double(nW)/rpBitmap->mnWidth, 0, nX, + 0, double(nH)/rpBitmap->mnHeight, nY), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::OVER); + + if (xBitmap.is()) + mxCanvas->drawBitmap( + xBitmap, + maViewState, + aRenderState); +} + + + + +void PresenterPaneBorderPainter::Renderer::SetupClipping ( + const awt::Rectangle& rUpdateBox, + const awt::Rectangle& rOuterBox, + const OUString& rsPaneStyleName) +{ + mxViewStateClip = NULL; + maViewState.Clip = NULL; + + if ( ! mxCanvas.is()) + return; + + ::boost::shared_ptr<RendererPaneStyle> pStyle (GetRendererPaneStyle(rsPaneStyleName)); + if (pStyle.get() == NULL) + { + mxViewStateClip = PresenterGeometryHelper::CreatePolygon( + rUpdateBox, + mxCanvas->getDevice()); + } + else + { + awt::Rectangle aInnerBox ( + pStyle->RemoveBorder(rOuterBox, drawing::framework::BorderType_TOTAL_BORDER)); + ::std::vector<awt::Rectangle> aRectangles; + aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, rOuterBox)); + aRectangles.push_back(PresenterGeometryHelper::Intersection(rUpdateBox, aInnerBox)); + mxViewStateClip = PresenterGeometryHelper::CreatePolygon( + aRectangles, + mxCanvas->getDevice()); + if (mxViewStateClip.is()) + mxViewStateClip->setFillRule(rendering::FillRule_EVEN_ODD); + } + maViewState.Clip = mxViewStateClip; +} + + + +namespace { + +//===== BorderSize ============================================================ + +BorderSize::BorderSize (void) + : mnLeft(0), + mnTop(0), + mnRight(0), + mnBottom(0) +{ +} + + + + +BorderSize::BorderSize (const BorderSize& rBorderSize) + : mnLeft(rBorderSize.mnLeft), + mnTop(rBorderSize.mnTop), + mnRight(rBorderSize.mnRight), + mnBottom(rBorderSize.mnBottom) +{ +} + + + + +BorderSize& BorderSize::operator= (const BorderSize& rBorderSize) +{ + if (&rBorderSize != this) + { + mnLeft = rBorderSize.mnLeft; + mnTop = rBorderSize.mnTop; + mnRight = rBorderSize.mnRight; + mnBottom = rBorderSize.mnBottom; + } + return *this; +} + + + + +//===== RendererPaneStyle ============================================================ + +RendererPaneStyle::RendererPaneStyle ( + const ::boost::shared_ptr<PresenterTheme>& rpTheme, + const OUString& rsStyleName) + : mpTopLeft(), + mpTop(), + mpTopRight(), + mpLeft(), + mpRight(), + mpBottomLeft(), + mpBottom(), + mpBottomRight(), + mpBottomCallout(), + mpBackground(), + mpEmpty(new PresenterBitmapDescriptor()), + mpFont(), + mnFontXOffset(0), + mnFontYOffset(0), + meFontAnchor(AnchorCenter), + maInnerBorderSize(), + maOuterBorderSize(), + maTotalBorderSize() +{ + if (rpTheme.get() != NULL) + { + mpTopLeft = GetBitmap(rpTheme, rsStyleName, A2S("TopLeft")); + mpTop = GetBitmap(rpTheme, rsStyleName, A2S("Top")); + mpTopRight = GetBitmap(rpTheme, rsStyleName, A2S("TopRight")); + mpLeft = GetBitmap(rpTheme, rsStyleName, A2S("Left")); + mpRight = GetBitmap(rpTheme, rsStyleName, A2S("Right")); + mpBottomLeft = GetBitmap(rpTheme, rsStyleName, A2S("BottomLeft")); + mpBottom = GetBitmap(rpTheme, rsStyleName, A2S("Bottom")); + mpBottomRight = GetBitmap(rpTheme, rsStyleName, A2S("BottomRight")); + mpBottomCallout = GetBitmap(rpTheme, rsStyleName, A2S("BottomCallout")); + mpBackground = GetBitmap(rpTheme, OUString(), A2S("Background")); + + // Get font description. + mpFont = rpTheme->GetFont(rsStyleName); + + OUString sAnchor (RTL_CONSTASCII_USTRINGPARAM("Left")); + if (mpFont.get() != NULL) + { + sAnchor = mpFont->msAnchor; + mnFontXOffset = mpFont->mnXOffset; + mnFontYOffset = mpFont->mnYOffset; + } + + if (sAnchor == OUString(RTL_CONSTASCII_USTRINGPARAM("Left"))) + meFontAnchor = AnchorLeft; + else if (sAnchor == OUString(RTL_CONSTASCII_USTRINGPARAM("Right"))) + meFontAnchor = AnchorRight; + else if (sAnchor == OUString(RTL_CONSTASCII_USTRINGPARAM("Center"))) + meFontAnchor = AnchorCenter; + else + meFontAnchor = AnchorCenter; + + // Get border sizes. + try + { + ::std::vector<sal_Int32> aInnerBorder (rpTheme->GetBorderSize(rsStyleName, false)); + OSL_ASSERT(aInnerBorder.size()==4); + maInnerBorderSize.mnLeft = aInnerBorder[0]; + maInnerBorderSize.mnTop = aInnerBorder[1]; + maInnerBorderSize.mnRight = aInnerBorder[2]; + maInnerBorderSize.mnBottom = aInnerBorder[3]; + + ::std::vector<sal_Int32> aOuterBorder (rpTheme->GetBorderSize(rsStyleName, true)); + OSL_ASSERT(aOuterBorder.size()==4); + maOuterBorderSize.mnLeft = aOuterBorder[0]; + maOuterBorderSize.mnTop = aOuterBorder[1]; + maOuterBorderSize.mnRight = aOuterBorder[2]; + maOuterBorderSize.mnBottom = aOuterBorder[3]; + } + catch(beans::UnknownPropertyException&) + { + OSL_ASSERT(false); + } + + UpdateBorderSizes(); + } +} + + + + + +awt::Rectangle RendererPaneStyle::AddBorder ( + const awt::Rectangle& rBox, + const drawing::framework::BorderType eBorderType) const +{ + const BorderSize* pBorderSize = NULL; + switch (eBorderType) + { + case drawing::framework::BorderType_INNER_BORDER: + pBorderSize = &maInnerBorderSize; + break; + case drawing::framework::BorderType_OUTER_BORDER: + pBorderSize = &maOuterBorderSize; + break; + case drawing::framework::BorderType_TOTAL_BORDER: + pBorderSize = &maTotalBorderSize; + break; + default: + return rBox; + } + return awt::Rectangle ( + rBox.X - pBorderSize->mnLeft, + rBox.Y - pBorderSize->mnTop, + rBox.Width + pBorderSize->mnLeft + pBorderSize->mnRight, + rBox.Height + pBorderSize->mnTop + pBorderSize->mnBottom); +} + + + + +awt::Rectangle RendererPaneStyle::RemoveBorder ( + const awt::Rectangle& rBox, + const css::drawing::framework::BorderType eBorderType) const +{ + const BorderSize* pBorderSize = NULL; + switch (eBorderType) + { + case drawing::framework::BorderType_INNER_BORDER: + pBorderSize = &maInnerBorderSize; + break; + case drawing::framework::BorderType_OUTER_BORDER: + pBorderSize = &maOuterBorderSize; + break; + case drawing::framework::BorderType_TOTAL_BORDER: + pBorderSize = &maTotalBorderSize; + break; + default: + return rBox; + } + return awt::Rectangle ( + rBox.X + pBorderSize->mnLeft, + rBox.Y + pBorderSize->mnTop, + rBox.Width - pBorderSize->mnLeft - pBorderSize->mnRight, + rBox.Height - pBorderSize->mnTop - pBorderSize->mnBottom); +} + + + + +const Reference<rendering::XCanvasFont> RendererPaneStyle::GetFont ( + const Reference<rendering::XCanvas>& rxCanvas) const +{ + if (mpFont.get() != NULL) + mpFont->PrepareFont(rxCanvas); + return mpFont->mxFont; +} + + + + +void RendererPaneStyle::UpdateBorderSizes (void) +{ + maTotalBorderSize.mnLeft = maInnerBorderSize.mnLeft + maOuterBorderSize.mnLeft; + maTotalBorderSize.mnTop = maInnerBorderSize.mnTop + maOuterBorderSize.mnTop; + maTotalBorderSize.mnRight = maInnerBorderSize.mnRight + maOuterBorderSize.mnRight; + maTotalBorderSize.mnBottom = maInnerBorderSize.mnBottom + maOuterBorderSize.mnBottom; +} + + + + +SharedBitmapDescriptor RendererPaneStyle::GetBitmap( + const ::boost::shared_ptr<PresenterTheme>& rpTheme, + const OUString& rsStyleName, + const OUString& rsBitmapName) +{ + SharedBitmapDescriptor pDescriptor (rpTheme->GetBitmap(rsStyleName, rsBitmapName)); + if (pDescriptor.get() != NULL) + return pDescriptor; + else + return mpEmpty; +} + + + +} // end of anonymous namespace + + +} } // end of namespace ::sd::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPaneBorderPainter.hxx b/sdext/source/presenter/PresenterPaneBorderPainter.hxx new file mode 100644 index 000000000000..0084d567e478 --- /dev/null +++ b/sdext/source/presenter/PresenterPaneBorderPainter.hxx @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_PANE_BORDER_PAINTER_HXX +#define SDEXT_PRESENTER_PRESENTER_PANE_BORDER_PAINTER_HXX + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/drawing/framework/XPaneBorderPainter.hpp> +#include <com/sun/star/graphic/XGraphicProvider.hpp> +#include <com/sun/star/rendering/XCanvas.hpp> +#include <com/sun/star/util/XMacroExpander.hpp> +#include <com/sun/star/awt/XGraphics.hpp> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase1.hxx> +#include <boost/noncopyable.hpp> +#include <boost/scoped_ptr.hpp> +#include <boost/shared_ptr.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace tools { + class ConfigurationAccess; +} } + +namespace sdext { namespace presenter { + +class PresenterPane; +class PresenterTheme; + +namespace { + typedef ::cppu::WeakComponentImplHelper1< + css::drawing::framework::XPaneBorderPainter + > PresenterPaneBorderPainterInterfaceBase; +} + +/** This class is responsible for painting window borders of PresenterPane + objects. +*/ +class PresenterPaneBorderPainter + : private ::boost::noncopyable, + protected ::cppu::BaseMutex, + public PresenterPaneBorderPainterInterfaceBase +{ +public: + PresenterPaneBorderPainter ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext); + virtual ~PresenterPaneBorderPainter (void); + + /** Transform the bounding box of the window content to the outer + bounding box of the border that is painted around it. + @param rsPaneURL + Specifies the pane style that is used to determine the border sizes. + @param rInnerBox + The rectangle of the inner window content. + */ + css::awt::Rectangle AddBorder ( + const ::rtl::OUString& rsPaneURL, + const css::awt::Rectangle& rInnerBox, + const css::drawing::framework::BorderType eBorderType) const; + + /** Transorm the outer bounding box of a window to the bounding box of + the inner content area. + @param rsPaneURL + Specifies the pane style that is used to determine the border sizes. + @param rOuterBox + The bounding box of the rectangle around the window. + @param bIsTitleVisible + This flag controls whether the upper part of the frame is + supposed to contain the window title. + */ + css::awt::Rectangle RemoveBorder ( + const ::rtl::OUString& rsPaneURL, + const css::awt::Rectangle& rOuterBox, + const css::drawing::framework::BorderType eBorderType) const; + + bool HasTheme (void) const; + + void SetTheme (const ::boost::shared_ptr<PresenterTheme>& rpTheme); + + class Renderer; + + // XPaneBorderPainter + + virtual css::awt::Rectangle SAL_CALL addBorder ( + const rtl::OUString& rsPaneBorderStyleName, + const css::awt::Rectangle& rRectangle, + css::drawing::framework::BorderType eBorderType) + throw(css::uno::RuntimeException); + + virtual css::awt::Rectangle SAL_CALL removeBorder ( + const rtl::OUString& rsPaneBorderStyleName, + const css::awt::Rectangle& rRectangle, + css::drawing::framework::BorderType eBorderType) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL paintBorder ( + const rtl::OUString& rsPaneBorderStyleName, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rOuterBorderRectangle, + const css::awt::Rectangle& rRepaintArea, + const rtl::OUString& rsTitle) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL paintBorderWithCallout ( + const rtl::OUString& rsPaneBorderStyleName, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rOuterBorderRectangle, + const css::awt::Rectangle& rRepaintArea, + const rtl::OUString& rsTitle, + const css::awt::Point& rCalloutAnchor) + throw(css::uno::RuntimeException); + + virtual css::awt::Point SAL_CALL getCalloutOffset ( + const rtl::OUString& rsPaneBorderStyleName) + throw(css::uno::RuntimeException); + +private: + css::uno::Reference<css::uno::XComponentContext> mxContext; + ::boost::shared_ptr<PresenterTheme> mpTheme; + ::boost::scoped_ptr<Renderer> mpRenderer; + + /** When the theme for the border has not yet been loaded then try again + when this method is called. + @return + Returns <TRUE/> only one time when the theme is loaded and/or the + renderer is initialized. + */ + bool ProvideTheme ( + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas); + bool ProvideTheme (void); + + void ThrowIfDisposed (void) const + throw (::com::sun::star::lang::DisposedException); +}; + +} } // end of namespace ::sd::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPaneContainer.cxx b/sdext/source/presenter/PresenterPaneContainer.cxx new file mode 100644 index 000000000000..feb7ecb6bd02 --- /dev/null +++ b/sdext/source/presenter/PresenterPaneContainer.cxx @@ -0,0 +1,450 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterPaneContainer.hxx" +#include "PresenterPaneBase.hxx" +#include <com/sun/star/awt/XGraphics.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/drawing/framework/ResourceId.hpp> +#include <vector> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +namespace sdext { namespace presenter { + +PresenterPaneContainer::PresenterPaneContainer ( + const Reference<XComponentContext>& rxContext) + : PresenterPaneContainerInterfaceBase(m_aMutex), + maPanes(), + mxPresenterHelper() +{ + Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager()); + if (xFactory.is()) + { + mxPresenterHelper = Reference<drawing::XPresenterHelper>( + xFactory->createInstanceWithContext( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.PresenterHelper")), + rxContext), + UNO_QUERY_THROW); + } +} + + + + +PresenterPaneContainer::~PresenterPaneContainer (void) +{ +} + + + + +void PresenterPaneContainer::PreparePane ( + const Reference<XResourceId>& rxPaneId, + const OUString& rsViewURL, + const OUString& rsTitle, + const OUString& rsAccessibleTitle, + const bool bIsOpaque, + const ViewInitializationFunction& rViewInitialization, + const double nLeft, + const double nTop, + const double nRight, + const double nBottom) +{ + if ( ! rxPaneId.is()) + return; + + SharedPaneDescriptor pPane (FindPaneURL(rxPaneId->getResourceURL())); + if (pPane.get() == NULL) + { + // No entry found for the given pane id. Create a new one. + SharedPaneDescriptor pDescriptor (new PaneDescriptor()); + pDescriptor->mxPaneId = rxPaneId; + pDescriptor->msViewURL = rsViewURL; + pDescriptor->mxPane = NULL; + if (rsTitle.indexOf('%') < 0) + { + pDescriptor->msTitle = rsTitle; + pDescriptor->msTitleTemplate = OUString(); + } + else + { + pDescriptor->msTitleTemplate = rsTitle; + pDescriptor->msTitle = OUString(); + } + pDescriptor->msAccessibleTitleTemplate = rsAccessibleTitle; + pDescriptor->maViewInitialization = rViewInitialization; + pDescriptor->mnLeft = nLeft; + pDescriptor->mnTop = nTop; + pDescriptor->mnRight = nRight; + pDescriptor->mnBottom = nBottom; + pDescriptor->mbIsActive = true; + pDescriptor->mbIsOpaque = bIsOpaque; + pDescriptor->maSpriteProvider = PaneDescriptor::SpriteProvider(); + pDescriptor->mbIsSprite = false; + pDescriptor->maCalloutAnchorLocation = awt::Point(-1,-1); + pDescriptor->mbHasCalloutAnchor = false; + + maPanes.push_back(pDescriptor); + } +} + + + + +void SAL_CALL PresenterPaneContainer::disposing (void) +{ + PaneList::iterator iPane (maPanes.begin()); + PaneList::const_iterator iEnd (maPanes.end()); + for ( ; iPane!=iEnd; ++iPane) + if ((*iPane)->mxPaneId.is()) + RemovePane((*iPane)->mxPaneId); +} + + + + +PresenterPaneContainer::SharedPaneDescriptor + PresenterPaneContainer::StorePane (const rtl::Reference<PresenterPaneBase>& rxPane) +{ + SharedPaneDescriptor pDescriptor; + + if (rxPane.is()) + { + OUString sPaneURL; + Reference<XResourceId> xPaneId (rxPane->getResourceId()); + if (xPaneId.is()) + sPaneURL = xPaneId->getResourceURL(); + + pDescriptor = FindPaneURL(sPaneURL); + if (pDescriptor.get() == NULL) + PreparePane(xPaneId, OUString(), OUString(), OUString(), + false, ViewInitializationFunction(), 0,0,0,0); + pDescriptor = FindPaneURL(sPaneURL); + if (pDescriptor.get() != NULL) + { + Reference<awt::XWindow> xWindow (rxPane->getWindow()); + pDescriptor->mxContentWindow = xWindow; + pDescriptor->mxPaneId = xPaneId; + pDescriptor->mxPane = rxPane; + pDescriptor->mxPane->SetTitle(pDescriptor->msTitle); + + // When there is a call out anchor location set then tell the + // window about it. + if (pDescriptor->mbHasCalloutAnchor) + pDescriptor->mxPane->SetCalloutAnchor(pDescriptor->maCalloutAnchorLocation); + + if (xWindow.is()) + xWindow->addEventListener(this); + } + } + + return pDescriptor; +} + + + + +PresenterPaneContainer::SharedPaneDescriptor + PresenterPaneContainer::StoreBorderWindow( + const Reference<XResourceId>& rxPaneId, + const Reference<awt::XWindow>& rxBorderWindow) +{ + // The content window may not be present. Use the resource URL of the + // pane id as key. + OUString sPaneURL; + if (rxPaneId.is()) + sPaneURL = rxPaneId->getResourceURL(); + + SharedPaneDescriptor pDescriptor (FindPaneURL(sPaneURL)); + if (pDescriptor.get() != NULL) + { + pDescriptor->mxBorderWindow = rxBorderWindow; + return pDescriptor; + } + else + return SharedPaneDescriptor(); +} + + + + +PresenterPaneContainer::SharedPaneDescriptor + PresenterPaneContainer::StoreView ( + const Reference<XView>& rxView, + const SharedBitmapDescriptor& rpViewBackground) +{ + SharedPaneDescriptor pDescriptor; + + if (rxView.is()) + { + OUString sPaneURL; + Reference<XResourceId> xViewId (rxView->getResourceId()); + if (xViewId.is()) + { + Reference<XResourceId> xPaneId (xViewId->getAnchor()); + if (xPaneId.is()) + sPaneURL = xPaneId->getResourceURL(); + } + + pDescriptor = FindPaneURL(sPaneURL); + if (pDescriptor.get() != NULL) + { + pDescriptor->mxView = rxView; + pDescriptor->mpViewBackground = rpViewBackground; + pDescriptor->mxPane->SetBackground(rpViewBackground); + try + { + if ( ! pDescriptor->maViewInitialization.empty()) + pDescriptor->maViewInitialization(rxView); + + // Activate or deactivate the pane/view. + if ( ! pDescriptor->maActivator.empty()) + pDescriptor->maActivator(pDescriptor->mbIsActive); + } + catch (RuntimeException&) + { + OSL_ASSERT(false); + } + } + } + + return pDescriptor; +} + + + + +PresenterPaneContainer::SharedPaneDescriptor + PresenterPaneContainer::RemovePane (const Reference<XResourceId>& rxPaneId) +{ + SharedPaneDescriptor pDescriptor (FindPaneId(rxPaneId)); + if (pDescriptor.get() != NULL) + { + if (pDescriptor->mxContentWindow.is()) + pDescriptor->mxContentWindow->removeEventListener(this); + pDescriptor->mxContentWindow = NULL; + pDescriptor->mxBorderWindow = NULL; + pDescriptor->mxPane = NULL; + pDescriptor->mxView = NULL; + pDescriptor->mbIsActive = false; + } + return pDescriptor; +} + + + + + +PresenterPaneContainer::SharedPaneDescriptor + PresenterPaneContainer::RemoveView (const Reference<XView>& rxView) +{ + SharedPaneDescriptor pDescriptor; + + if (rxView.is()) + { + OUString sPaneURL; + Reference<XResourceId> xViewId (rxView->getResourceId()); + if (xViewId.is()) + { + Reference<XResourceId> xPaneId (xViewId->getAnchor()); + if (xPaneId.is()) + sPaneURL = xPaneId->getResourceURL(); + } + + pDescriptor = FindPaneURL(sPaneURL); + if (pDescriptor.get() != NULL) + { + pDescriptor->mxView = NULL; + pDescriptor->mpViewBackground = SharedBitmapDescriptor(); + } + } + + return pDescriptor; +} + + + + +PresenterPaneContainer::SharedPaneDescriptor PresenterPaneContainer::FindBorderWindow ( + const Reference<awt::XWindow>& rxBorderWindow) +{ + PaneList::const_iterator iPane; + PaneList::iterator iEnd (maPanes.end()); + for (iPane=maPanes.begin(); iPane!=iEnd; ++iPane) + { + if ((*iPane)->mxBorderWindow == rxBorderWindow) + return *iPane; + } + return SharedPaneDescriptor(); +} + + + + +PresenterPaneContainer::SharedPaneDescriptor PresenterPaneContainer::FindContentWindow ( + const Reference<awt::XWindow>& rxContentWindow) +{ + PaneList::const_iterator iPane; + PaneList::iterator iEnd (maPanes.end()); + for (iPane=maPanes.begin(); iPane!=iEnd; ++iPane) + { + if ((*iPane)->mxContentWindow == rxContentWindow) + return *iPane; + } + return SharedPaneDescriptor(); +} + + + + +PresenterPaneContainer::SharedPaneDescriptor PresenterPaneContainer::FindPaneURL ( + const OUString& rsPaneURL) +{ + PaneList::const_iterator iPane; + PaneList::const_iterator iEnd (maPanes.end()); + for (iPane=maPanes.begin(); iPane!=iEnd; ++iPane) + { + if ((*iPane)->mxPaneId->getResourceURL() == rsPaneURL) + return *iPane; + } + return SharedPaneDescriptor(); +} + + + + +PresenterPaneContainer::SharedPaneDescriptor PresenterPaneContainer::FindPaneId ( + const Reference<XResourceId>& rxPaneId) +{ + PaneList::iterator iEnd (maPanes.end()); + + if ( ! rxPaneId.is()) + return SharedPaneDescriptor(); + + PaneList::iterator iPane; + for (iPane=maPanes.begin(); iPane!=iEnd; ++iPane) + { + if (rxPaneId->compareTo((*iPane)->mxPaneId) == 0) + return *iPane; + } + return SharedPaneDescriptor(); +} + + + + +PresenterPaneContainer::SharedPaneDescriptor PresenterPaneContainer::FindViewURL ( + const OUString& rsViewURL) +{ + PaneList::iterator iEnd (maPanes.end()); + PaneList::iterator iPane; + for (iPane=maPanes.begin(); iPane!=iEnd; ++iPane) + { + if (rsViewURL == (*iPane)->msViewURL) + return *iPane; + } + return SharedPaneDescriptor(); +} + + + + +::rtl::OUString PresenterPaneContainer::GetPaneURLForViewURL (const ::rtl::OUString& rsViewURL) +{ + SharedPaneDescriptor pDescriptor (FindViewURL(rsViewURL)); + if (pDescriptor.get() != NULL) + if (pDescriptor->mxPaneId.is()) + return pDescriptor->mxPaneId->getResourceURL(); + return OUString(); +} + + + + +void PresenterPaneContainer::ToTop (const SharedPaneDescriptor& rpDescriptor) +{ + if (rpDescriptor.get() != NULL) + { + // Find iterator for pDescriptor. + PaneList::iterator iPane; + PaneList::iterator iEnd (maPanes.end()); + for (iPane=maPanes.begin(); iPane!=iEnd; ++iPane) + if (iPane->get() == rpDescriptor.get()) + break; + OSL_ASSERT(iPane!=iEnd); + if (iPane == iEnd) + return; + + if (mxPresenterHelper.is()) + mxPresenterHelper->toTop(rpDescriptor->mxBorderWindow); + + maPanes.erase(iPane); + maPanes.push_back(rpDescriptor); + } +} + + + + +//----- XEventListener -------------------------------------------------------- + +void SAL_CALL PresenterPaneContainer::disposing ( + const com::sun::star::lang::EventObject& rEvent) + throw (com::sun::star::uno::RuntimeException) +{ + SharedPaneDescriptor pDescriptor ( + FindContentWindow(Reference<awt::XWindow>(rEvent.Source, UNO_QUERY))); + if (pDescriptor.get() != NULL) + { + RemovePane(pDescriptor->mxPaneId); + } +} + + + + +//===== PresenterPaneContainer::PaneDescriptor ================================ + +void PresenterPaneContainer::PaneDescriptor::SetActivationState (const bool bIsActive) +{ + mbIsActive = bIsActive; + if ( ! maActivator.empty()) + maActivator(mbIsActive); +} + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPaneContainer.hxx b/sdext/source/presenter/PresenterPaneContainer.hxx new file mode 100644 index 000000000000..3c837ffc8a9b --- /dev/null +++ b/sdext/source/presenter/PresenterPaneContainer.hxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PANE_CONTAINER_HXX +#define SDEXT_PRESENTER_PANE_CONTAINER_HXX + +#include "PresenterTheme.hxx" +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/drawing/framework/XResourceId.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/drawing/framework/XView.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/util/Color.hpp> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase1.hxx> +#include <rtl/ref.hxx> +#include <vector> +#include <boost/function.hpp> +#include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +class PresenterPaneBase; +class PresenterSprite; + +namespace { + typedef ::cppu::WeakComponentImplHelper1 < + css::lang::XEventListener + > PresenterPaneContainerInterfaceBase; +} + +/** This class could also be called PresenterPaneAndViewContainer because it + stores not only references to all panes that belong to the presenter + screen but stores the views displayed in these panes as well. +*/ +class PresenterPaneContainer + : private ::boost::noncopyable, + private ::cppu::BaseMutex, + public PresenterPaneContainerInterfaceBase +{ +public: + PresenterPaneContainer ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext); + virtual ~PresenterPaneContainer (void); + + virtual void SAL_CALL disposing (void); + + typedef ::boost::function1<void, const css::uno::Reference<css::drawing::framework::XView>&> + ViewInitializationFunction; + + /** Each pane descriptor holds references to one pane and the view + displayed in this pane as well as the other information that is used + to manage the pane window like an XWindow reference, the title, and + the coordinates. + + A initialization function for the view is stored as well. This + function is executed as soon as a view is created. + */ + class PaneDescriptor + { + public: + typedef ::boost::function<void(bool)> Activator; + typedef ::boost::function<boost::shared_ptr<PresenterSprite>()> SpriteProvider; + css::uno::Reference<css::drawing::framework::XResourceId> mxPaneId; + ::rtl::OUString msViewURL; + ::rtl::Reference<PresenterPaneBase> mxPane; + css::uno::Reference<css::drawing::framework::XView> mxView; + css::uno::Reference<css::awt::XWindow> mxContentWindow; + css::uno::Reference<css::awt::XWindow> mxBorderWindow; + ::rtl::OUString msTitleTemplate; + ::rtl::OUString msAccessibleTitleTemplate; + ::rtl::OUString msTitle; + ViewInitializationFunction maViewInitialization; + double mnLeft; + double mnTop; + double mnRight; + double mnBottom; + SharedBitmapDescriptor mpViewBackground; + bool mbIsActive; + bool mbNeedsClipping; + bool mbIsOpaque; + SpriteProvider maSpriteProvider; + bool mbIsSprite; + Activator maActivator; + css::awt::Point maCalloutAnchorLocation; + bool mbHasCalloutAnchor; + + void SetActivationState (const bool bIsActive); + }; + typedef ::boost::shared_ptr<PaneDescriptor> SharedPaneDescriptor; + typedef ::std::vector<SharedPaneDescriptor> PaneList; + PaneList maPanes; + + void PreparePane ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::OUString& rsViewURL, + const ::rtl::OUString& rsTitle, + const ::rtl::OUString& rsAccessibleTitle, + const bool bIsOpaque, + const ViewInitializationFunction& rViewIntialization, + const double nLeft, + const double nTop, + const double nRight, + const double nBottom); + + SharedPaneDescriptor StorePane ( + const rtl::Reference<PresenterPaneBase>& rxPane); + + SharedPaneDescriptor StoreBorderWindow( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const css::uno::Reference<css::awt::XWindow>& rxBorderWindow); + + SharedPaneDescriptor StoreView ( + const css::uno::Reference<css::drawing::framework::XView>& rxView, + const SharedBitmapDescriptor& rpViewBackground); + + SharedPaneDescriptor RemovePane ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId); + + SharedPaneDescriptor RemoveView ( + const css::uno::Reference<css::drawing::framework::XView>& rxView); + + void CreateBorderWindow (PaneDescriptor& rDescriptor); + + /** Find the pane whose border window is identical to the given border + window. + */ + SharedPaneDescriptor FindBorderWindow ( + const css::uno::Reference<css::awt::XWindow>& rxBorderWindow); + + /** Find the pane whose border window is identical to the given content + window. + */ + SharedPaneDescriptor FindContentWindow ( + const css::uno::Reference<css::awt::XWindow>& rxBorderWindow); + + /** Find the pane whose pane URL is identical to the given URL string. + */ + SharedPaneDescriptor FindPaneURL (const ::rtl::OUString& rsPaneURL); + + /** Find the pane whose resource id is identical to the given one. + */ + SharedPaneDescriptor FindPaneId (const css::uno::Reference< + css::drawing::framework::XResourceId>& rxPaneId); + + SharedPaneDescriptor FindViewURL (const ::rtl::OUString& rsViewURL); + + ::rtl::OUString GetPaneURLForViewURL (const ::rtl::OUString& rsViewURL); + + void ToTop (const SharedPaneDescriptor& rpDescriptor); + + + // XEventListener + + virtual void SAL_CALL disposing ( + const com::sun::star::lang::EventObject& rEvent) + throw (com::sun::star::uno::RuntimeException); + +private: + css::uno::Reference<css::drawing::XPresenterHelper> mxPresenterHelper; + + PaneList::const_iterator FindIteratorForPaneURL (const ::rtl::OUString& rsPaneURL); +}; + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPaneFactory.cxx b/sdext/source/presenter/PresenterPaneFactory.cxx new file mode 100644 index 000000000000..5d8b307398ef --- /dev/null +++ b/sdext/source/presenter/PresenterPaneFactory.cxx @@ -0,0 +1,381 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterPaneFactory.hxx" +#include "PresenterController.hxx" +#include "PresenterPane.hxx" +#include "PresenterPaneBorderPainter.hxx" +#include "PresenterPaneContainer.hxx" +#include "PresenterSpritePane.hxx" +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/drawing/framework/ResourceId.hpp> +#include <com/sun/star/drawing/framework/XControllerManager.hpp> +#include <com/sun/star/drawing/framework/XConfigurationController.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <boost/bind.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +namespace sdext { namespace presenter { + +const ::rtl::OUString PresenterPaneFactory::msCurrentSlidePreviewPaneURL( + RTL_CONSTASCII_USTRINGPARAM("private:resource/pane/Presenter/Pane1")); +const ::rtl::OUString PresenterPaneFactory::msNextSlidePreviewPaneURL( + RTL_CONSTASCII_USTRINGPARAM("private:resource/pane/Presenter/Pane2")); +const ::rtl::OUString PresenterPaneFactory::msNotesPaneURL( + RTL_CONSTASCII_USTRINGPARAM("private:resource/pane/Presenter/Pane3")); +const ::rtl::OUString PresenterPaneFactory::msToolBarPaneURL( + RTL_CONSTASCII_USTRINGPARAM("private:resource/pane/Presenter/Pane4")); +const ::rtl::OUString PresenterPaneFactory::msSlideSorterPaneURL( + RTL_CONSTASCII_USTRINGPARAM("private:resource/pane/Presenter/Pane5")); +const ::rtl::OUString PresenterPaneFactory::msHelpPaneURL( + RTL_CONSTASCII_USTRINGPARAM("private:resource/pane/Presenter/Pane6")); + +const ::rtl::OUString PresenterPaneFactory::msOverlayPaneURL( + RTL_CONSTASCII_USTRINGPARAM("private:resource/pane/Presenter/Overlay")); + + + +//===== PresenterPaneFactory ================================================== + +Reference<drawing::framework::XResourceFactory> PresenterPaneFactory::Create ( + const Reference<uno::XComponentContext>& rxContext, + const Reference<frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController) +{ + rtl::Reference<PresenterPaneFactory> pFactory ( + new PresenterPaneFactory(rxContext,rpPresenterController)); + pFactory->Register(rxController); + return Reference<drawing::framework::XResourceFactory>( + static_cast<XWeak*>(pFactory.get()), UNO_QUERY); +} + + + + +PresenterPaneFactory::PresenterPaneFactory ( + const Reference<uno::XComponentContext>& rxContext, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterPaneFactoryInterfaceBase(m_aMutex), + mxComponentContextWeak(rxContext), + mxConfigurationControllerWeak(), + mpPresenterController(rpPresenterController), + mpResourceCache() +{ +} + + + + +void PresenterPaneFactory::Register (const Reference<frame::XController>& rxController) +{ + Reference<XConfigurationController> xCC; + try + { + // Get the configuration controller. + Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW); + xCC = Reference<XConfigurationController>(xCM->getConfigurationController()); + mxConfigurationControllerWeak = xCC; + if ( ! xCC.is()) + { + throw RuntimeException(); + } + else + { + xCC->addResourceFactory( + OUString(RTL_CONSTASCII_USTRINGPARAM("private:resource/pane/Presenter/*")), + this); + } + } + catch (RuntimeException&) + { + OSL_ASSERT(false); + if (xCC.is()) + xCC->removeResourceFactoryForReference(this); + mxConfigurationControllerWeak = WeakReference<XConfigurationController>(); + + throw; + } +} + + + + +PresenterPaneFactory::~PresenterPaneFactory (void) +{ +} + + + + +void SAL_CALL PresenterPaneFactory::disposing (void) + throw (RuntimeException) +{ + Reference<XConfigurationController> xCC (mxConfigurationControllerWeak); + if (xCC.is()) + xCC->removeResourceFactoryForReference(this); + mxConfigurationControllerWeak = WeakReference<XConfigurationController>(); + + // Dispose the panes in the cache. + if (mpResourceCache.get() != NULL) + { + ResourceContainer::const_iterator iPane (mpResourceCache->begin()); + ResourceContainer::const_iterator iEnd (mpResourceCache->end()); + for ( ; iPane!=iEnd; ++iPane) + { + Reference<lang::XComponent> xPaneComponent (iPane->second, UNO_QUERY); + if (xPaneComponent.is()) + xPaneComponent->dispose(); + } + mpResourceCache.reset(); + } +} + + + + +//----- XPaneFactory ---------------------------------------------------------- + +Reference<XResource> SAL_CALL PresenterPaneFactory::createResource ( + const Reference<XResourceId>& rxPaneId) + throw (RuntimeException, IllegalArgumentException, WrappedTargetException) +{ + ThrowIfDisposed(); + + if ( ! rxPaneId.is()) + return NULL; + + const OUString sPaneURL (rxPaneId->getResourceURL()); + if (sPaneURL.getLength() == 0) + return NULL; + + if (mpResourceCache.get() != NULL) + { + // Has the requested resource already been created? + ResourceContainer::const_iterator iResource (mpResourceCache->find(sPaneURL)); + if (iResource != mpResourceCache->end()) + { + // Yes. Mark it as active. + rtl::Reference<PresenterPaneContainer> pPaneContainer( + mpPresenterController->GetPaneContainer()); + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + pPaneContainer->FindPaneURL(sPaneURL)); + if (pDescriptor.get() != NULL) + { + pDescriptor->SetActivationState(true); + if (pDescriptor->mxBorderWindow.is()) + pDescriptor->mxBorderWindow->setVisible(sal_True); + pPaneContainer->StorePane(pDescriptor->mxPane); + } + + return iResource->second; + } + } + + // No. Create a new one. + Reference<XResource> xResource = CreatePane(rxPaneId, OUString()); + return xResource; +} + + + + +void SAL_CALL PresenterPaneFactory::releaseResource (const Reference<XResource>& rxResource) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + if ( ! rxResource.is()) + throw lang::IllegalArgumentException(); + + // Mark the pane as inactive. + rtl::Reference<PresenterPaneContainer> pPaneContainer( + mpPresenterController->GetPaneContainer()); + const OUString sPaneURL (rxResource->getResourceId()->getResourceURL()); + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + pPaneContainer->FindPaneURL(sPaneURL)); + if (pDescriptor.get() != NULL) + { + pDescriptor->SetActivationState(false); + if (pDescriptor->mxBorderWindow.is()) + pDescriptor->mxBorderWindow->setVisible(sal_False); + + if (mpResourceCache.get() != NULL) + { + // Store the pane in the cache. + (*mpResourceCache)[sPaneURL] = rxResource; + } + else + { + // Dispose the pane. + Reference<lang::XComponent> xPaneComponent (rxResource, UNO_QUERY); + if (xPaneComponent.is()) + xPaneComponent->dispose(); + } + } +} + + + + +//----------------------------------------------------------------------------- + +Reference<XResource> PresenterPaneFactory::CreatePane ( + const Reference<XResourceId>& rxPaneId, + const OUString& rsTitle) +{ + if ( ! rxPaneId.is()) + return NULL; + + Reference<XConfigurationController> xCC (mxConfigurationControllerWeak); + if ( ! xCC.is()) + return NULL; + + Reference<XComponentContext> xContext (mxComponentContextWeak); + if ( ! xContext.is()) + return NULL; + + Reference<XPane> xParentPane (xCC->getResource(rxPaneId->getAnchor()), UNO_QUERY); + if ( ! xParentPane.is()) + return NULL; + + try + { + return CreatePane( + rxPaneId, + rsTitle, + xParentPane, + rxPaneId->getFullResourceURL().Arguments.compareToAscii("Sprite=1") == 0); + } + catch (Exception&) + { + OSL_ASSERT(false); + } + + return NULL; +} + + + + +Reference<XResource> PresenterPaneFactory::CreatePane ( + const Reference<XResourceId>& rxPaneId, + const OUString& rsTitle, + const Reference<drawing::framework::XPane>& rxParentPane, + const bool bIsSpritePane) +{ + Reference<XComponentContext> xContext (mxComponentContextWeak); + Reference<lang::XMultiComponentFactory> xFactory ( + xContext->getServiceManager(), UNO_QUERY_THROW); + + // Create a border window and canvas and store it in the pane + // container. + + // Create the pane. + ::rtl::Reference<PresenterPaneBase> xPane; + if (bIsSpritePane) + { + xPane = ::rtl::Reference<PresenterPaneBase>( + new PresenterSpritePane(xContext, mpPresenterController)); + } + else + { + xPane = ::rtl::Reference<PresenterPaneBase>( + new PresenterPane(xContext, mpPresenterController)); + } + + // Supply arguments. + Sequence<Any> aArguments (6); + aArguments[0] <<= rxPaneId; + aArguments[1] <<= rxParentPane->getWindow(); + aArguments[2] <<= rxParentPane->getCanvas(); + aArguments[3] <<= rsTitle; + aArguments[4] <<= Reference<drawing::framework::XPaneBorderPainter>( + static_cast<XWeak*>(mpPresenterController->GetPaneBorderPainter().get()), + UNO_QUERY); + aArguments[5] <<= bIsSpritePane ? false : true; + xPane->initialize(aArguments); + + // Store pane and canvases and windows in container. + ::rtl::Reference<PresenterPaneContainer> pContainer ( + mpPresenterController->GetPaneContainer()); + PresenterPaneContainer::SharedPaneDescriptor pDescriptor( + pContainer->StoreBorderWindow(rxPaneId, xPane->GetBorderWindow())); + pContainer->StorePane(xPane); + if (pDescriptor.get() != NULL) + { + if (bIsSpritePane) + { + pDescriptor->maSpriteProvider = ::boost::bind( + &PresenterSpritePane::GetSprite, + dynamic_cast<PresenterSpritePane*>(xPane.get())); + pDescriptor->mbIsSprite = true; + pDescriptor->mbNeedsClipping = false; + } + else + { + pDescriptor->mbIsSprite = false; + pDescriptor->mbNeedsClipping = true; + } + + // Get the window of the frame and make that visible. + Reference<awt::XWindow> xWindow (pDescriptor->mxBorderWindow, UNO_QUERY_THROW); + xWindow->setVisible(sal_True); + } + + return Reference<XResource>(static_cast<XWeak*>(xPane.get()), UNO_QUERY_THROW); +} + + + + +void PresenterPaneFactory::ThrowIfDisposed (void) const + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterPaneFactory object has already been disposed")), + const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + } +} + + +} } // end of namespace sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterPaneFactory.hxx b/sdext/source/presenter/PresenterPaneFactory.hxx new file mode 100644 index 000000000000..136d47ec645b --- /dev/null +++ b/sdext/source/presenter/PresenterPaneFactory.hxx @@ -0,0 +1,142 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PANE_FACTORY_HXX +#define SDEXT_PRESENTER_PANE_FACTORY_HXX + +#include <cppuhelper/compbase1.hxx> +#include <cppuhelper/basemutex.hxx> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/drawing/framework/XConfigurationController.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/drawing/framework/XResourceFactory.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <rtl/ref.hxx> +#include <boost/scoped_ptr.hpp> +#include <map> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +class PresenterController; + +namespace { + typedef ::cppu::WeakComponentImplHelper1 < + css::drawing::framework::XResourceFactory + > PresenterPaneFactoryInterfaceBase; +} + + +/** The PresenerPaneFactory provides a fixed set of panes. + + In order to make the presener screen more easily extendable in the + future the set of supported panes could be made extendable on demand. +*/ +class PresenterPaneFactory + : public ::cppu::BaseMutex, + public PresenterPaneFactoryInterfaceBase +{ +public: + static const ::rtl::OUString msCurrentSlidePreviewPaneURL; + static const ::rtl::OUString msNextSlidePreviewPaneURL; + static const ::rtl::OUString msNotesPaneURL; + static const ::rtl::OUString msToolBarPaneURL; + static const ::rtl::OUString msSlideSorterPaneURL; + static const ::rtl::OUString msHelpPaneURL; + static const ::rtl::OUString msOverlayPaneURL; + + /** Create a new instance of this class and register it as resource + factory in the drawing framework of the given controller. + This registration keeps it alive. When the drawing framework is + shut down and releases its reference to the factory then the factory + is destroyed. + */ + static css::uno::Reference<css::drawing::framework::XResourceFactory> Create ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~PresenterPaneFactory (void); + + static ::rtl::OUString getImplementationName_static (void); + static css::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static (void); + static css::uno::Reference<css::uno::XInterface> Create( + const css::uno::Reference<css::uno::XComponentContext>& rxContext) + SAL_THROW((css::uno::Exception)); + + virtual void SAL_CALL disposing (void) + throw (css::uno::RuntimeException); + + // XResourceFactory + + virtual css::uno::Reference<css::drawing::framework::XResource> + SAL_CALL createResource ( + const ::com::sun::star::uno::Reference< + com::sun::star::drawing::framework::XResourceId>& rxPaneId) + throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException); + + virtual void SAL_CALL + releaseResource ( + const ::com::sun::star::uno::Reference<com::sun::star::drawing::framework::XResource>& + rxPane) + throw (::com::sun::star::uno::RuntimeException); + +private: + css::uno::WeakReference<css::uno::XComponentContext> mxComponentContextWeak; + css::uno::WeakReference<css::drawing::framework::XConfigurationController> + mxConfigurationControllerWeak; + ::rtl::Reference<PresenterController> mpPresenterController; + typedef ::std::map<rtl::OUString, css::uno::Reference<css::drawing::framework::XResource> > + ResourceContainer; + ::boost::scoped_ptr<ResourceContainer> mpResourceCache; + + PresenterPaneFactory ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const ::rtl::Reference<PresenterController>& rpPresenterController); + + void Register (const css::uno::Reference<css::frame::XController>& rxController); + + css::uno::Reference<css::drawing::framework::XResource> CreatePane ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::OUString& rsTitle); + css::uno::Reference<css::drawing::framework::XResource> CreatePane ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const ::rtl::OUString& rsTitle, + const css::uno::Reference<css::drawing::framework::XPane>& rxParentPane, + const bool bIsSpritePane); + + void ThrowIfDisposed (void) const throw (::com::sun::star::lang::DisposedException); +}; + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterProtocolHandler.cxx b/sdext/source/presenter/PresenterProtocolHandler.cxx new file mode 100644 index 000000000000..7c4829ac81fd --- /dev/null +++ b/sdext/source/presenter/PresenterProtocolHandler.cxx @@ -0,0 +1,1004 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterProtocolHandler.hxx" +#include "PresenterConfigurationAccess.hxx" +#include "PresenterController.hxx" +#include "PresenterHelper.hxx" +#include "PresenterNotesView.hxx" +#include "PresenterPaneContainer.hxx" +#include "PresenterPaneFactory.hxx" +#include "PresenterViewFactory.hxx" +#include "PresenterWindowManager.hxx" +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/drawing/SlideSorter.hpp> +#include <com/sun/star/drawing/framework/Configuration.hpp> +#include <com/sun/star/drawing/framework/XControllerManager.hpp> +#include <com/sun/star/drawing/framework/ResourceId.hpp> +#include <com/sun/star/drawing/framework/ResourceActivationMode.hpp> +#include <com/sun/star/presentation/XSlideShow.hpp> +#include <com/sun/star/presentation/XSlideShowView.hpp> +#include <com/sun/star/presentation/XPresentationSupplier.hpp> +#include <cppuhelper/compbase2.hxx> +#include <boost/bind.hpp> +#include <tools/debug.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) + +namespace sdext { namespace presenter { + +namespace { + const static OUString gsProtocol (A2S("vnd.com.sun.star.comp.PresenterScreen:")); + + class Command + { + public: + virtual void Execute (void) = 0; + virtual bool IsEnabled (void) const = 0; + virtual Any GetState (void) const = 0; + }; + + class GotoPreviousSlideCommand : public Command + { + public: + GotoPreviousSlideCommand ( + const rtl::Reference<PresenterController>& rpPresenterController); + virtual ~GotoPreviousSlideCommand (void) {} + virtual void Execute (void); + virtual bool IsEnabled (void) const; + virtual Any GetState (void) const; + private: + rtl::Reference<PresenterController> mpPresenterController; + }; + + class GotoNextSlideCommand : public Command + { + public: + GotoNextSlideCommand ( + const rtl::Reference<PresenterController>& rpPresenterController); + virtual ~GotoNextSlideCommand (void) {} + virtual void Execute (void); + virtual bool IsEnabled (void) const; + virtual Any GetState (void) const; + private: + rtl::Reference<PresenterController> mpPresenterController; + }; + + class GotoNextEffectCommand : public Command + { + public: + GotoNextEffectCommand ( + const rtl::Reference<PresenterController>& rpPresenterController); + virtual ~GotoNextEffectCommand (void) {} + virtual void Execute (void); + virtual bool IsEnabled (void) const; + virtual Any GetState (void) const; + private: + rtl::Reference<PresenterController> mpPresenterController; + }; + + class SetNotesViewCommand : public Command + { + public: + SetNotesViewCommand ( + const bool bOn, + const rtl::Reference<PresenterController>& rpPresenterController); + virtual ~SetNotesViewCommand (void) {} + virtual void Execute (void); + virtual bool IsEnabled (void) const; + virtual Any GetState (void) const; + private: + bool mbOn; + rtl::Reference<PresenterController> mpPresenterController; + bool IsActive (const ::rtl::Reference<PresenterWindowManager>& rpWindowManager) const; + }; + + class SetSlideSorterCommand : public Command + { + public: + SetSlideSorterCommand ( + const bool bOn, + const rtl::Reference<PresenterController>& rpPresenterController); + virtual ~SetSlideSorterCommand (void) {} + virtual void Execute (void); + virtual bool IsEnabled (void) const; + virtual Any GetState (void) const; + private: + bool mbOn; + rtl::Reference<PresenterController> mpPresenterController; + }; + + class SetHelpViewCommand : public Command + { + public: + SetHelpViewCommand ( + const bool bOn, + const rtl::Reference<PresenterController>& rpPresenterController); + virtual ~SetHelpViewCommand (void) {} + virtual void Execute (void); + virtual bool IsEnabled (void) const; + virtual Any GetState (void) const; + private: + bool mbOn; + rtl::Reference<PresenterController> mpPresenterController; + }; + + class NotesFontSizeCommand : public Command + { + public: + NotesFontSizeCommand( + const rtl::Reference<PresenterController>& rpPresenterController, + const sal_Int32 nSizeChange); + virtual ~NotesFontSizeCommand (void) {} + virtual void Execute (void); + virtual bool IsEnabled (void) const; + virtual Any GetState (void) const; + protected: + ::rtl::Reference<PresenterNotesView> GetNotesView (void) const; + private: + rtl::Reference<PresenterController> mpPresenterController; + const sal_Int32 mnSizeChange; + }; + +} // end of anonymous namespace + + +namespace { + typedef ::cppu::WeakComponentImplHelper2 < + css::frame::XDispatch, + css::document::XEventListener + > PresenterDispatchInterfaceBase; +} + +class PresenterProtocolHandler::Dispatch + : protected ::cppu::BaseMutex, + public PresenterDispatchInterfaceBase +{ +public: + typedef void (PresenterProtocolHandler::Dispatch::* Action)(void); + + /** Create a new Dispatch object. When the given command name + (rsURLPath) is not known then an empty reference is returned. + */ + static Reference<frame::XDispatch> Create ( + const OUString& rsURLPath, + const ::rtl::Reference<PresenterController>& rpPresenterController); + + void SAL_CALL disposing (void); + static Command* CreateCommand ( + const OUString& rsURLPath, + const ::rtl::Reference<PresenterController>& rpPresenterController); + + + // XDispatch + virtual void SAL_CALL dispatch( + const css::util::URL& aURL, + const css::uno::Sequence<css::beans::PropertyValue>& rArguments) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL addStatusListener( + const css::uno::Reference<css::frame::XStatusListener>& rxListener, + const css::util::URL& rURL) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL removeStatusListener ( + const css::uno::Reference<css::frame::XStatusListener>& rxListener, + const css::util::URL& rURL) + throw(css::uno::RuntimeException); + + + // document::XEventListener + + virtual void SAL_CALL notifyEvent (const css::document::EventObject& rEvent) + throw(css::uno::RuntimeException); + + + // lang::XEventListener + + virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) + throw(css::uno::RuntimeException); + +private: + OUString msURLPath; + ::boost::scoped_ptr<Command> mpCommand; + ::rtl::Reference<PresenterController> mpPresenterController; + typedef ::std::vector<Reference<frame::XStatusListener> > StatusListenerContainer; + StatusListenerContainer maStatusListenerContainer; + bool mbIsListeningToWindowManager; + + Dispatch ( + const OUString& rsURLPath, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~Dispatch (void); + + void ThrowIfDisposed (void) const throw (css::lang::DisposedException); +}; + + + + +//----- Service --------------------------------------------------------------- + +OUString PresenterProtocolHandler::getImplementationName_static (void) +{ + return A2S("vnd.sun.star.sdext.presenter.PresenterProtocolHandler"); +} + + + + +Sequence<OUString> PresenterProtocolHandler::getSupportedServiceNames_static (void) +{ + static const ::rtl::OUString sServiceName(A2S("com.sun.star.frame.ProtocolHandler")); + return Sequence<rtl::OUString>(&sServiceName, 1); +} + + + + +Reference<XInterface> PresenterProtocolHandler::Create ( + const Reference<uno::XComponentContext>& rxContext) + SAL_THROW((Exception)) +{ + return Reference<XInterface>(static_cast<XWeak*>(new PresenterProtocolHandler(rxContext))); +} + + + + +//===== PresenterProtocolHandler ========================================================= + + +PresenterProtocolHandler::PresenterProtocolHandler (const Reference<XComponentContext>& rxContext) + : PresenterProtocolHandlerInterfaceBase(m_aMutex) +{ + (void)rxContext; +} + + + + +PresenterProtocolHandler::~PresenterProtocolHandler (void) +{ +} + + + + +void SAL_CALL PresenterProtocolHandler::disposing (void) +{ +} + + + + +//----- XInitialize ----------------------------------------------------------- + +void SAL_CALL PresenterProtocolHandler::initialize (const Sequence<Any>& aArguments) + throw (Exception, RuntimeException) +{ + ThrowIfDisposed(); + if (aArguments.getLength() > 0) + { + try + { + Reference<frame::XFrame> xFrame; + if (aArguments[0] >>= xFrame) + { + mpPresenterController = PresenterController::Instance(xFrame); + } + } + catch (RuntimeException&) + { + OSL_ASSERT(false); + } + } +} + + + + +//----- XDispatchProvider ----------------------------------------------------- + +Reference<frame::XDispatch> SAL_CALL PresenterProtocolHandler::queryDispatch ( + const css::util::URL& rURL, + const rtl::OUString& rsTargetFrameName, + sal_Int32 nSearchFlags) + throw(RuntimeException) +{ + (void)rsTargetFrameName; + (void)nSearchFlags; + ThrowIfDisposed(); + + Reference<frame::XDispatch> xDispatch; + + if (rURL.Protocol == gsProtocol) + { + xDispatch.set(Dispatch::Create(rURL.Path, mpPresenterController)); + } + + return xDispatch; +} + + + + +Sequence<Reference<frame::XDispatch> > SAL_CALL PresenterProtocolHandler::queryDispatches( + const Sequence<frame::DispatchDescriptor>& rDescriptors) + throw(RuntimeException) +{ + (void)rDescriptors; + ThrowIfDisposed(); + return Sequence<Reference<frame::XDispatch> >(); +} + + + + +//----------------------------------------------------------------------------- + +void PresenterProtocolHandler::ThrowIfDisposed (void) const + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterProtocolHandler object has already been disposed")), + const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + } +} + + + + +//===== PresenterProtocolHandler::Dispatch ==================================== + +Reference<frame::XDispatch> PresenterProtocolHandler::Dispatch::Create ( + const OUString& rsURLPath, + const ::rtl::Reference<PresenterController>& rpPresenterController) +{ + ::rtl::Reference<Dispatch> pDispatch (new Dispatch (rsURLPath, rpPresenterController)); + if (pDispatch->mpCommand.get() != NULL) + return Reference<frame::XDispatch>(pDispatch.get()); + else + return NULL; +} + + + + +PresenterProtocolHandler::Dispatch::Dispatch ( + const OUString& rsURLPath, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterDispatchInterfaceBase(m_aMutex), + msURLPath(rsURLPath), + mpCommand(CreateCommand(rsURLPath, rpPresenterController)), + mpPresenterController(rpPresenterController), + maStatusListenerContainer(), + mbIsListeningToWindowManager(false) +{ + if (mpCommand.get() != NULL) + { + mpPresenterController->GetWindowManager()->AddLayoutListener(this); + mbIsListeningToWindowManager = true; + } +} + + + + +Command* PresenterProtocolHandler::Dispatch::CreateCommand ( + const OUString& rsURLPath, + const ::rtl::Reference<PresenterController>& rpPresenterController) +{ + if (rsURLPath.getLength() <= 5) + return NULL; + switch (rsURLPath[0]) + { + case sal_Char('C') : + switch (rsURLPath[5]) + { + case sal_Char('N'): + if (rsURLPath == A2S("CloseNotes")) + return new SetNotesViewCommand(false, rpPresenterController); + break; + case sal_Char('S'): + if (rsURLPath == A2S("CloseSlideSorter")) + return new SetSlideSorterCommand(false, rpPresenterController); + break; + case sal_Char('H'): + if (rsURLPath == A2S("CloseHelp")) + return new SetHelpViewCommand(false, rpPresenterController); + break; + } + break; + case sal_Char('G') : + if (rsURLPath == A2S("GrowNotesFont")) + return new NotesFontSizeCommand(rpPresenterController, +1); + break; + + case sal_Char('N') : + switch (rsURLPath[4]) + { + case sal_Char('E'): + if (rsURLPath == A2S("NextEffect")) + return new GotoNextEffectCommand(rpPresenterController); + case sal_Char('S'): + if (rsURLPath == A2S("NextSlide")) + return new GotoNextSlideCommand(rpPresenterController); + break; + } + break; + + case sal_Char('P') : + if (rsURLPath == A2S("PrevSlide")) + return new GotoPreviousSlideCommand(rpPresenterController); + break; + + case sal_Char('S') : + switch (rsURLPath[4]) + { + case sal_Char('N'): + if (rsURLPath == A2S("ShowNotes")) + return new SetNotesViewCommand(true, rpPresenterController); + break; + + case sal_Char('S'): + if (rsURLPath == A2S("ShowSlideSorter")) + return new SetSlideSorterCommand(true, rpPresenterController); + break; + + case sal_Char('H'): + if (rsURLPath == A2S("ShowHelp")) + return new SetHelpViewCommand(true, rpPresenterController); + break; + + case sal_Char('n'): + if (rsURLPath == A2S("ShrinkNotesFont")) + return new NotesFontSizeCommand(rpPresenterController, -1); + break; + } + break; + + default: + break; + } + + return NULL; +} + + + + +PresenterProtocolHandler::Dispatch::~Dispatch (void) +{ +} + + + + +void PresenterProtocolHandler::Dispatch::disposing (void) +{ + if (mbIsListeningToWindowManager) + { + if (mpPresenterController.get() != NULL) + mpPresenterController->GetWindowManager()->RemoveLayoutListener(this); + mbIsListeningToWindowManager = false; + } + + msURLPath = OUString(); + mpCommand.reset(); +} + + + + +//----- XDispatch ------------------------------------------------------------- + +void SAL_CALL PresenterProtocolHandler::Dispatch::dispatch( + const css::util::URL& rURL, + const css::uno::Sequence<css::beans::PropertyValue>& rArguments) + throw(css::uno::RuntimeException) +{ + (void)rArguments; + ThrowIfDisposed(); + + if (rURL.Protocol == gsProtocol + && rURL.Path == msURLPath) + { + if (mpCommand.get() != NULL) + mpCommand->Execute(); + } + else + { + // We can not throw an IllegalArgumentException + throw RuntimeException(); + } +} + + + + +void SAL_CALL PresenterProtocolHandler::Dispatch::addStatusListener( + const css::uno::Reference<css::frame::XStatusListener>& rxListener, + const css::util::URL& rURL) + throw(css::uno::RuntimeException) +{ + if (rURL.Path == msURLPath) + { + maStatusListenerContainer.push_back(rxListener); + + frame::FeatureStateEvent aEvent; + aEvent.FeatureURL = rURL; + aEvent.IsEnabled = mpCommand->IsEnabled(); + aEvent.Requery = sal_False; + aEvent.State = mpCommand->GetState(); + rxListener->statusChanged(aEvent); + } + else + throw RuntimeException(); +} + + + + +void SAL_CALL PresenterProtocolHandler::Dispatch::removeStatusListener ( + const css::uno::Reference<css::frame::XStatusListener>& rxListener, + const css::util::URL& rURL) + throw(css::uno::RuntimeException) +{ + if (rURL.Path == msURLPath) + { + StatusListenerContainer::iterator iListener ( + ::std::find( + maStatusListenerContainer.begin(), + maStatusListenerContainer.end(), + rxListener)); + if (iListener != maStatusListenerContainer.end()) + maStatusListenerContainer.erase(iListener); + } + else + throw RuntimeException(); +} + + + + +//----------------------------------------------------------------------------- + +void PresenterProtocolHandler::Dispatch::ThrowIfDisposed (void) const + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterProtocolHandler::Dispatch object has already been disposed")), + const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + } +} + + + + +//----- document::XEventListener ---------------------------------------------- + +void SAL_CALL PresenterProtocolHandler::Dispatch::notifyEvent ( + const css::document::EventObject& rEvent) + throw(css::uno::RuntimeException) +{ + (void)rEvent; + + mpCommand->GetState(); +} + + + + +//----- lang::XEventListener -------------------------------------------------- + +void SAL_CALL PresenterProtocolHandler::Dispatch::disposing (const css::lang::EventObject& rEvent) + throw(css::uno::RuntimeException) +{ + (void)rEvent; + mbIsListeningToWindowManager = false; +} + + + + + +//===== GotoPreviousSlideCommand ============================================== + +GotoPreviousSlideCommand::GotoPreviousSlideCommand ( + const rtl::Reference<PresenterController>& rpPresenterController) + : mpPresenterController(rpPresenterController) +{ +} + + + +void GotoPreviousSlideCommand::Execute (void) +{ + if ( ! mpPresenterController.is()) + return; + + if ( ! mpPresenterController->GetSlideShowController().is()) + return; + + mpPresenterController->GetSlideShowController()->gotoPreviousSlide(); +} + + + + +bool GotoPreviousSlideCommand::IsEnabled (void) const +{ + if ( ! mpPresenterController.is()) + return false; + + if ( ! mpPresenterController->GetSlideShowController().is()) + return false; + + return mpPresenterController->GetSlideShowController()->getCurrentSlideIndex()>0; +} + + + + +Any GotoPreviousSlideCommand::GetState (void) const +{ + return Any(sal_False); +} + + + + +//===== GotoNextEffect ======================================================== + +GotoNextEffectCommand::GotoNextEffectCommand ( + const rtl::Reference<PresenterController>& rpPresenterController) + : mpPresenterController(rpPresenterController) +{ +} + + + +void GotoNextEffectCommand::Execute (void) +{ + if ( ! mpPresenterController.is()) + return; + + if ( ! mpPresenterController->GetSlideShowController().is()) + return; + + mpPresenterController->GetSlideShowController()->gotoNextEffect(); +} + + + + +bool GotoNextEffectCommand::IsEnabled (void) const +{ + // The next slide command is always enabled, even when the current slide + // is the last slide: from the last slide it goes to the pause slide, + // and from there it ends the slide show. + return true; +} + + + + +Any GotoNextEffectCommand::GetState (void) const +{ + return Any(sal_False); +} + + + + +//===== GotoNextSlide ========================================================= + +GotoNextSlideCommand::GotoNextSlideCommand ( + const rtl::Reference<PresenterController>& rpPresenterController) + : mpPresenterController(rpPresenterController) +{ +} + + + +void GotoNextSlideCommand::Execute (void) +{ + if ( ! mpPresenterController.is()) + return; + + if ( ! mpPresenterController->GetSlideShowController().is()) + return; + + mpPresenterController->GetSlideShowController()->gotoNextSlide(); +} + + + + +bool GotoNextSlideCommand::IsEnabled (void) const +{ + // The next slide command is always enabled, even when the current slide + // is the last slide: from the last slide it goes to the pause slide, + // and from there it ends the slide show. + return true; +} + + + + +Any GotoNextSlideCommand::GetState (void) const +{ + return Any(sal_False); +} + + + + +//===== SetNotesViewCommand =================================================== + +SetNotesViewCommand::SetNotesViewCommand ( + const bool bOn, + const rtl::Reference<PresenterController>& rpPresenterController) + : mbOn(bOn), + mpPresenterController(rpPresenterController) +{ +} + + + + +void SetNotesViewCommand::Execute (void) +{ + if ( ! mpPresenterController.is()) + return; + + ::rtl::Reference<PresenterWindowManager> pWindowManager ( + mpPresenterController->GetWindowManager()); + if ( ! pWindowManager.is()) + return; + + if (mbOn) + pWindowManager->SetViewMode(PresenterWindowManager::VM_Notes); + else + pWindowManager->SetViewMode(PresenterWindowManager::VM_Standard); +} + + + + +bool SetNotesViewCommand::IsEnabled (void) const +{ + return true; +} + + + + +Any SetNotesViewCommand::GetState (void) const +{ + if ( ! mpPresenterController.is()) + return Any(false); + + ::rtl::Reference<PresenterWindowManager> pWindowManager ( + mpPresenterController->GetWindowManager()); + if ( ! pWindowManager.is()) + return Any(false); + + return Any(IsActive(pWindowManager)); +} + + + + +bool SetNotesViewCommand::IsActive ( + const ::rtl::Reference<PresenterWindowManager>& rpWindowManager) const +{ + return rpWindowManager->GetViewMode() == PresenterWindowManager::VM_Notes; +} + + + + +//===== SetSlideSorterCommand ================================================= + +SetSlideSorterCommand::SetSlideSorterCommand ( + const bool bOn, + const rtl::Reference<PresenterController>& rpPresenterController) + : mbOn(bOn), + mpPresenterController(rpPresenterController) +{ +} + + + + +void SetSlideSorterCommand::Execute (void) +{ + if ( ! mpPresenterController.is()) + return; + + ::rtl::Reference<PresenterWindowManager> pWindowManager ( + mpPresenterController->GetWindowManager()); + if ( ! pWindowManager.is()) + return; + + pWindowManager->SetSlideSorterState(mbOn); +} + + + + +bool SetSlideSorterCommand::IsEnabled (void) const +{ + return true; +} + + + + +Any SetSlideSorterCommand::GetState (void) const +{ + if ( ! mpPresenterController.is()) + return Any(false); + + ::rtl::Reference<PresenterWindowManager> pWindowManager ( + mpPresenterController->GetWindowManager()); + if ( ! pWindowManager.is()) + return Any(false); + + return Any(pWindowManager->GetViewMode()==PresenterWindowManager::VM_SlideOverview); +} + + + + +//===== SetHelpViewCommand =================================================== + +SetHelpViewCommand::SetHelpViewCommand ( + const bool bOn, + const rtl::Reference<PresenterController>& rpPresenterController) + : mbOn(bOn), + mpPresenterController(rpPresenterController) +{ +} + + + + +void SetHelpViewCommand::Execute (void) +{ + if ( ! mpPresenterController.is()) + return; + + ::rtl::Reference<PresenterWindowManager> pWindowManager ( + mpPresenterController->GetWindowManager()); + if ( ! pWindowManager.is()) + return; + + pWindowManager->SetHelpViewState(mbOn); +} + + + + +bool SetHelpViewCommand::IsEnabled (void) const +{ + return true; +} + + + + +Any SetHelpViewCommand::GetState (void) const +{ + if ( ! mpPresenterController.is()) + return Any(false); + + ::rtl::Reference<PresenterWindowManager> pWindowManager ( + mpPresenterController->GetWindowManager()); + if ( ! pWindowManager.is()) + return Any(false); + + return Any(pWindowManager->GetViewMode()==PresenterWindowManager::VM_Help); +} + + + + +//===== NotesFontSizeCommand ================================================== + +NotesFontSizeCommand::NotesFontSizeCommand( + const rtl::Reference<PresenterController>& rpPresenterController, + const sal_Int32 nSizeChange) + : mpPresenterController(rpPresenterController), + mnSizeChange(nSizeChange) +{ +} + + + + +::rtl::Reference<PresenterNotesView> NotesFontSizeCommand::GetNotesView (void) const +{ + if (mpPresenterController.get() == NULL) + return NULL; + + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPresenterController->GetPaneContainer()->FindViewURL( + PresenterViewFactory::msNotesViewURL)); + if (pDescriptor.get() == NULL) + return NULL; + + return dynamic_cast<PresenterNotesView*>(pDescriptor->mxView.get()); +} + + + + +void NotesFontSizeCommand::Execute (void) +{ + ::rtl::Reference<PresenterNotesView> pView (GetNotesView()); + if (pView.is()) + pView->ChangeFontSize(mnSizeChange); +} + + + + +bool NotesFontSizeCommand::IsEnabled (void) const +{ + return true; +} + + + + +Any NotesFontSizeCommand::GetState (void) const +{ + return Any(); +} + + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterProtocolHandler.hxx b/sdext/source/presenter/PresenterProtocolHandler.hxx new file mode 100644 index 000000000000..2c7918e735f8 --- /dev/null +++ b/sdext/source/presenter/PresenterProtocolHandler.hxx @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_PROTOCOL_HANDLER_HXX +#define SDEXT_PRESENTER_PRESENTER_PROTOCOL_HANDLER_HXX + +#include <cppuhelper/compbase2.hxx> +#include <cppuhelper/basemutex.hxx> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <boost/unordered_map.hpp> +#include <rtl/ref.hxx> +#include <boost/scoped_ptr.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + + +namespace { + typedef ::cppu::WeakComponentImplHelper2 < + css::lang::XInitialization, + css::frame::XDispatchProvider + > PresenterProtocolHandlerInterfaceBase; +} + +class PresenterController; + +class PresenterProtocolHandler + : protected ::cppu::BaseMutex, + public PresenterProtocolHandlerInterfaceBase +{ +public: + PresenterProtocolHandler (const css::uno::Reference<css::uno::XComponentContext>& rxContext); + virtual ~PresenterProtocolHandler (void); + + void SAL_CALL disposing (void); + + static ::rtl::OUString getImplementationName_static (void); + static css::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static (void); + static css::uno::Reference<css::uno::XInterface> Create( + const css::uno::Reference<css::uno::XComponentContext>& rxContext) + SAL_THROW((css::uno::Exception)); + + + // XInitialization + + virtual void SAL_CALL initialize( + const css::uno::Sequence<css::uno::Any>& aArguments) + throw (css::uno::Exception, css::uno::RuntimeException); + + + // XDispatchProvider + + virtual css::uno::Reference<css::frame::XDispatch > SAL_CALL + queryDispatch ( + const css::util::URL& aURL, + const rtl::OUString& aTargetFrameName, + sal_Int32 nSearchFlags ) + throw(css::uno::RuntimeException); + + virtual css::uno::Sequence<css::uno::Reference<css::frame::XDispatch> > SAL_CALL + queryDispatches( + const css::uno::Sequence< css::frame::DispatchDescriptor>& rDescriptors) + throw(css::uno::RuntimeException); + + +private: + class Dispatch; + ::rtl::Reference<PresenterController> mpPresenterController; + + void ThrowIfDisposed (void) const throw (css::lang::DisposedException); +}; + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterScreen.cxx b/sdext/source/presenter/PresenterScreen.cxx new file mode 100644 index 000000000000..e39e168876c6 --- /dev/null +++ b/sdext/source/presenter/PresenterScreen.cxx @@ -0,0 +1,930 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterScreen.hxx" +#include "PresenterConfigurationAccess.hxx" +#include "PresenterController.hxx" +#include "PresenterFrameworkObserver.hxx" +#include "PresenterHelper.hxx" +#include "PresenterPaneContainer.hxx" +#include "PresenterPaneFactory.hxx" +#include "PresenterViewFactory.hxx" +#include "PresenterWindowManager.hxx" +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/drawing/framework/Configuration.hpp> +#include <com/sun/star/drawing/framework/XControllerManager.hpp> +#include <com/sun/star/drawing/framework/ResourceId.hpp> +#include <com/sun/star/drawing/framework/ResourceActivationMode.hpp> +#include <com/sun/star/presentation/XSlideShow.hpp> +#include <com/sun/star/presentation/XPresentation2.hpp> +#include <com/sun/star/presentation/XPresentationSupplier.hpp> +#include <com/sun/star/document/XEventBroadcaster.hpp> +#include <boost/bind.hpp> +#include <tools/debug.hxx> + +#include <com/sun/star/view/XSelectionSupplier.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +#define A2S(s) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))) + +namespace sdext { namespace presenter { + +namespace { + typedef ::cppu::WeakComponentImplHelper1 < + css::document::XEventListener + > PresenterScreenListenerInterfaceBase; + + /** One instance of a PresenterScreenListener is registered per Impress + document and waits for the full screen slide show to start and to + end. + */ + class PresenterScreenListener + : private ::boost::noncopyable, + private ::cppu::BaseMutex, + public PresenterScreenListenerInterfaceBase + { + public: + PresenterScreenListener ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::frame::XModel2>& rxModel); + virtual ~PresenterScreenListener (void); + + void Initialize (void); + virtual void SAL_CALL disposing (void); + + // document::XEventListener + + virtual void SAL_CALL notifyEvent( const css::document::EventObject& Event ) throw (css::uno::RuntimeException); + + // XEventListener + + virtual void SAL_CALL disposing ( const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException); + + private: + css::uno::Reference<css::frame::XModel2 > mxModel; + css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + rtl::Reference<PresenterScreen> mpPresenterScreen; + + void ThrowIfDisposed (void) const throw (::com::sun::star::lang::DisposedException); + }; +} + + +//----- Service --------------------------------------------------------------- + +OUString PresenterScreenJob::getImplementationName_static (void) +{ + return A2S("com.sun.star.comp.Draw.framework.PresenterScreenJob"); +} + + + + +Sequence<OUString> PresenterScreenJob::getSupportedServiceNames_static (void) +{ + static const ::rtl::OUString sServiceName( + A2S("com.sun.star.drawing.framework.PresenterScreenJob")); + return Sequence<rtl::OUString>(&sServiceName, 1); +} + + + + +Reference<XInterface> PresenterScreenJob::Create (const Reference<uno::XComponentContext>& rxContext) + SAL_THROW((css::uno::Exception)) +{ + return Reference<XInterface>(static_cast<XWeak*>(new PresenterScreenJob(rxContext))); +} + + + + +//===== PresenterScreenJob ==================================================== + +PresenterScreenJob::PresenterScreenJob (const Reference<XComponentContext>& rxContext) + : PresenterScreenJobInterfaceBase(m_aMutex), + mxComponentContext(rxContext) +{ +} + + + + +PresenterScreenJob::~PresenterScreenJob (void) +{ +} + + + + +void SAL_CALL PresenterScreenJob::disposing (void) +{ + mxComponentContext = NULL; +} + + + + +//----- XJob ----------------------------------------------------------- + +Any SAL_CALL PresenterScreenJob::execute( + const Sequence< beans::NamedValue >& Arguments ) + throw (lang::IllegalArgumentException, Exception, RuntimeException) +{ + Sequence< beans::NamedValue > lEnv; + + sal_Int32 i = 0; + sal_Int32 c = Arguments.getLength(); + const beans::NamedValue* p = Arguments.getConstArray(); + for (i=0; i<c; ++i) + { + if (p[i].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Environment"))) + { + p[i].Value >>= lEnv; + break; + } + } + + Reference<frame::XModel2> xModel; + c = lEnv.getLength(); + p = lEnv.getConstArray(); + for (i=0; i<c; ++i) + { + if (p[i].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Model"))) + { + p[i].Value >>= xModel; + break; + } + } + + Reference< XServiceInfo > xInfo( xModel, UNO_QUERY ); + if( xInfo.is() && xInfo->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument" ) ) ) ) + { + // Create a new listener that waits for the full screen presentation + // to start and to end. It takes care of its own lifetime. + ::rtl::Reference<PresenterScreenListener> pListener ( + new PresenterScreenListener(mxComponentContext, xModel)); + pListener->Initialize(); + } + + return Any(); +} + + + + +//===== PresenterScreenListener =============================================== + +namespace { + +PresenterScreenListener::PresenterScreenListener ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::frame::XModel2>& rxModel) + : PresenterScreenListenerInterfaceBase(m_aMutex), + mxModel(rxModel), + mxComponentContext(rxContext), + mpPresenterScreen() +{ +} + + + + +void PresenterScreenListener::Initialize (void) +{ + Reference< document::XEventListener > xDocListener( + static_cast< document::XEventListener* >(this), UNO_QUERY); + Reference< document::XEventBroadcaster > xDocBroadcaster( mxModel, UNO_QUERY ); + if( xDocBroadcaster.is() ) + xDocBroadcaster->addEventListener(xDocListener); +} + + + + +PresenterScreenListener::~PresenterScreenListener (void) +{ +} + + + + +void SAL_CALL PresenterScreenListener::disposing (void) +{ + Reference< document::XEventBroadcaster > xDocBroadcaster( mxModel, UNO_QUERY ); + if( xDocBroadcaster.is() ) + xDocBroadcaster->removeEventListener( + Reference<document::XEventListener>( + static_cast<document::XEventListener*>(this), UNO_QUERY)); + + if (mpPresenterScreen.is()) + { + mpPresenterScreen->RequestShutdownPresenterScreen(); + mpPresenterScreen = NULL; + } +} + + + + +// document::XEventListener + +void SAL_CALL PresenterScreenListener::notifyEvent( const css::document::EventObject& Event ) throw (css::uno::RuntimeException) +{ + ThrowIfDisposed(); + + if( Event.EventName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OnStartPresentation" ) ) ) + { + mpPresenterScreen = new PresenterScreen(mxComponentContext, mxModel); + mpPresenterScreen->InitializePresenterScreen(); + } + else if( Event.EventName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OnEndPresentation" ) ) ) + { + if (mpPresenterScreen.is()) + { + mpPresenterScreen->RequestShutdownPresenterScreen(); + mpPresenterScreen = NULL; + } + } +} + + + + +// XEventListener + +void SAL_CALL PresenterScreenListener::disposing (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; + + if (mpPresenterScreen.is()) + { + mpPresenterScreen->RequestShutdownPresenterScreen(); + mpPresenterScreen = NULL; + } +} + + + + +void PresenterScreenListener::ThrowIfDisposed (void) const throw ( + ::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterScreenListener object has already been disposed")), + const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + } +} + +} // end of anonymous namespace + + + + +//===== PresenterScreen ======================================================= + +PresenterScreen::PresenterScreen ( + const Reference<XComponentContext>& rxContext, + const css::uno::Reference<css::frame::XModel2>& rxModel) + : PresenterScreenInterfaceBase(m_aMutex), + mxModel(rxModel), + mxController(), + mxConfigurationControllerWeak(), + mxContextWeak(rxContext), + mxSlideShowControllerWeak(), + mpPresenterController(), + mxSlideShowViewId(), + mxSavedConfiguration(), + mpPaneContainer(), + mnComponentIndex(0), + mxPaneFactory(), + mxViewFactory(), + maViewDescriptors() +{ +} + + + + +PresenterScreen::~PresenterScreen (void) +{ +} + + + + +void SAL_CALL PresenterScreen::disposing (void) +{ + Reference<XConfigurationController> xCC (mxConfigurationControllerWeak); + if (xCC.is() && mxSavedConfiguration.is()) + { + xCC->restoreConfiguration(mxSavedConfiguration); + } + mxConfigurationControllerWeak = Reference<XConfigurationController>(NULL); + + Reference<lang::XComponent> xViewFactoryComponent (mxViewFactory, UNO_QUERY); + if (xViewFactoryComponent.is()) + xViewFactoryComponent->dispose(); + Reference<lang::XComponent> xPaneFactoryComponent (mxPaneFactory, UNO_QUERY); + if (xPaneFactoryComponent.is()) + xPaneFactoryComponent->dispose(); + + mxModel = NULL; +} + + + + +//----- XEventListener -------------------------------------------------------- + +void SAL_CALL PresenterScreen::disposing (const lang::EventObject& /*rEvent*/) + throw (RuntimeException) +{ + mxSlideShowControllerWeak = WeakReference<presentation::XSlideShowController>(); + RequestShutdownPresenterScreen(); +} + + + + +//----------------------------------------------------------------------------- + +void PresenterScreen::InitializePresenterScreen (void) +{ + try + { + Reference<XComponentContext> xContext (mxContextWeak); + mpPaneContainer = + new PresenterPaneContainer(Reference<XComponentContext>(xContext)); + + Reference<XPresentationSupplier> xPS ( mxModel, UNO_QUERY_THROW); + Reference<XPresentation2> xPresentation(xPS->getPresentation(), UNO_QUERY_THROW); + Reference<presentation::XSlideShowController> xSlideShowController( xPresentation->getController() ); + mxSlideShowControllerWeak = xSlideShowController; + + if( !xSlideShowController.is() || !xSlideShowController->isFullScreen() ) + return; + + // find first controller that is not the current controller (the one with the slideshow + mxController = mxModel->getCurrentController(); + Reference< container::XEnumeration > xEnum( mxModel->getControllers() ); + if( xEnum.is() ) + { + while( xEnum->hasMoreElements() ) + { + Reference< frame::XController > xC( xEnum->nextElement(), UNO_QUERY ); + if( xC.is() && (xC != mxController) ) + { + mxController = xC; + break; + } + } + } + // Get the XController from the first argument. + Reference<XControllerManager> xCM(mxController, UNO_QUERY_THROW); + + Reference<XConfigurationController> xCC( xCM->getConfigurationController()); + mxConfigurationControllerWeak = xCC; + + Reference<drawing::framework::XResourceId> xMainPaneId( + GetMainPaneId(xPresentation)); + // An empty reference means that the presenter screen can + // not or must not be displayed. + if ( ! xMainPaneId.is()) + return; + + if (xCC.is() && xContext.is()) + { + // Store the current configuration so that we can restore it when + // the presenter view is deactivated. + mxSavedConfiguration = xCC->getRequestedConfiguration(); + xCC->lock(); + + try + { + // At the moment the presenter controller is displayed in its + // own full screen window that is controlled by the same + // configuration controller as the Impress document from + // which the presentation was started. Therefore the main + // pane is actived additionally to the already existing + // panes and does not replace them. + xCC->requestResourceActivation( + xMainPaneId, + ResourceActivationMode_ADD); + SetupConfiguration(xContext, xMainPaneId); + + mpPresenterController = new PresenterController( + xContext, + mxController, + xSlideShowController, + mpPaneContainer, + xMainPaneId); + + // Create pane and view factories and integrate them into the + // drawing framework. + SetupPaneFactory(xContext); + SetupViewFactory(xContext); + + mpPresenterController->GetWindowManager()->RestoreViewMode(); + } + catch (RuntimeException&) + { + xCC->restoreConfiguration(mxSavedConfiguration); + } + xCC->unlock(); + } + } + catch (Exception&) + { + } +} + + + + +sal_Int32 PresenterScreen::GetScreenNumber ( + const Reference<presentation::XPresentation2>& rxPresentation) const +{ + // Determine the screen on which the full screen presentation is being + // displayed. + sal_Int32 nScreenNumber (0); + sal_Int32 nScreenCount (1); + try + { + Reference<beans::XPropertySet> xProperties (rxPresentation, UNO_QUERY); + if ( ! xProperties.is()) + return -1; + + sal_Int32 nDisplayNumber (-1); + if ( ! (xProperties->getPropertyValue(A2S("Display")) >>= nDisplayNumber)) + return -1; + + Reference<XComponentContext> xContext (mxContextWeak); + if ( ! xContext.is()) + return -1; + Reference<lang::XMultiComponentFactory> xFactory ( + xContext->getServiceManager(), UNO_QUERY); + if ( ! xFactory.is()) + return -1; + Reference<beans::XPropertySet> xDisplayProperties ( + xFactory->createInstanceWithContext(A2S("com.sun.star.awt.DisplayAccess"),xContext), + UNO_QUERY); + if ( ! xDisplayProperties.is()) + return -1; + + if (nDisplayNumber > 0) + { + nScreenNumber = nDisplayNumber - 1; + } + else if (nDisplayNumber == 0) + { + // A display number value of 0 indicates the primary screen. + // Instantiate the DisplayAccess service to find out which + // screen number that is. + if (nDisplayNumber <= 0 && xDisplayProperties.is()) + xDisplayProperties->getPropertyValue(A2S("DefaultDisplay")) >>= nScreenNumber; + } + + // We still have to determine the number of screens to decide + // whether the presenter screen may be shown at all. + Reference<container::XIndexAccess> xIndexAccess (xDisplayProperties, UNO_QUERY); + if ( ! xIndexAccess.is()) + return -1; + nScreenCount = xIndexAccess->getCount(); + + if (nScreenCount < 2 || nDisplayNumber > nScreenCount) + { + // There is either only one screen or the full screen + // presentation spans all available screens. The presenter + // screen is shown only when a special flag in the configuration + // is set. + PresenterConfigurationAccess aConfiguration ( + xContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.extension.PresenterScreen/")), + PresenterConfigurationAccess::READ_ONLY); + bool bStartAlways (false); + if (aConfiguration.GetConfigurationNode( + OUString(RTL_CONSTASCII_USTRINGPARAM("Presenter/StartAlways"))) >>= bStartAlways) + { + if (bStartAlways) + return nScreenNumber; + } + return -1; + } + } + catch (beans::UnknownPropertyException&) + { + OSL_ASSERT(false); + // For some reason we can not access the screen number. Use + // the default instead. + } + + return nScreenNumber; +} + + + + +Reference<drawing::framework::XResourceId> PresenterScreen::GetMainPaneId ( + const Reference<presentation::XPresentation2>& rxPresentation) const +{ + // A negative value means that the presentation spans all available + // displays. That leaves no room for the presenter. + const sal_Int32 nScreenNumber(GetScreenNumber(rxPresentation)); + if (nScreenNumber < 0) + return NULL; + + // Setup the resource id of the full screen background pane so that + // it is displayed on another screen than the presentation. + sal_Int32 nPresenterScreenNumber (1); + switch (nScreenNumber) + { + case 0: + nPresenterScreenNumber = 1; + break; + + case 1: + nPresenterScreenNumber = 0; + break; + + default: + // When the full screen presentation is displayed on a screen + // other than 0 or 1 then place the presenter on the first + // available screen. + nPresenterScreenNumber = 0; + break; + } + + return ResourceId::create( + Reference<XComponentContext>(mxContextWeak), + PresenterHelper::msFullScreenPaneURL + +A2S("?FullScreen=true&ScreenNumber=") + + OUString::valueOf(nPresenterScreenNumber)); +} + + + + +void PresenterScreen::RequestShutdownPresenterScreen (void) +{ + // Restore the configuration that was active before the presenter screen + // has been activated. Now, that the presenter screen is displayed in + // its own top level window this probably not necessary, but one never knows. + Reference<XConfigurationController> xCC (mxConfigurationControllerWeak); + if (xCC.is() && mxSavedConfiguration.is()) + { + xCC->restoreConfiguration(mxSavedConfiguration); + mxSavedConfiguration = NULL; + } + + if (xCC.is()) + { + // The actual restoration of the configuration takes place + // asynchronously. The view and pane factories can only by disposed + // after that. Therefore, set up a listener and wait for the + // restoration. + rtl::Reference<PresenterScreen> pSelf (this); + PresenterFrameworkObserver::RunOnUpdateEnd( + xCC, + ::boost::bind(&PresenterScreen::ShutdownPresenterScreen, pSelf)); + xCC->update(); + } +} + + + + +void PresenterScreen::ShutdownPresenterScreen (void) +{ + Reference<lang::XComponent> xViewFactoryComponent (mxViewFactory, UNO_QUERY); + if (xViewFactoryComponent.is()) + xViewFactoryComponent->dispose(); + mxViewFactory = NULL; + + Reference<lang::XComponent> xPaneFactoryComponent (mxPaneFactory, UNO_QUERY); + if (xPaneFactoryComponent.is()) + xPaneFactoryComponent->dispose(); + mxPaneFactory = NULL; + + if (mpPresenterController.get() != NULL) + { + mpPresenterController->dispose(); + mpPresenterController = rtl::Reference<PresenterController>(); + } + mpPaneContainer = new PresenterPaneContainer(Reference<XComponentContext>(mxContextWeak)); +} + + + + +void PresenterScreen::SetupPaneFactory (const Reference<XComponentContext>& rxContext) +{ + try + { + if ( ! mxPaneFactory.is()) + mxPaneFactory = PresenterPaneFactory::Create( + rxContext, + mxController, + mpPresenterController); + } + catch (RuntimeException&) + { + OSL_ASSERT(false); + } +} + + + + +void PresenterScreen::SetupViewFactory (const Reference<XComponentContext>& rxContext) +{ + try + { + if ( ! mxViewFactory.is()) + mxViewFactory = PresenterViewFactory::Create( + rxContext, + mxController, + mpPresenterController); + } + catch (RuntimeException&) + { + OSL_ASSERT(false); + } +} + + + + +void PresenterScreen::SetupConfiguration ( + const Reference<XComponentContext>& rxContext, + const Reference<XResourceId>& rxAnchorId) +{ + try + { + PresenterConfigurationAccess aConfiguration ( + rxContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.extension.PresenterScreen")), + PresenterConfigurationAccess::READ_ONLY); + maViewDescriptors.clear(); + ProcessViewDescriptions(aConfiguration); + OUString sLayoutName (RTL_CONSTASCII_USTRINGPARAM("DefaultLayout")); + aConfiguration.GetConfigurationNode( + OUString(RTL_CONSTASCII_USTRINGPARAM("Presenter/CurrentLayout"))) >>= sLayoutName; + ProcessLayout(aConfiguration, sLayoutName, rxContext, rxAnchorId); + } + catch (RuntimeException&) + { + } +} + + + + +void PresenterScreen::ProcessLayout ( + PresenterConfigurationAccess& rConfiguration, + const OUString& rsLayoutName, + const Reference<XComponentContext>& rxContext, + const Reference<XResourceId>& rxAnchorId) +{ + try + { + Reference<container::XHierarchicalNameAccess> xLayoutNode ( + rConfiguration.GetConfigurationNode( + OUString(RTL_CONSTASCII_USTRINGPARAM("Presenter/Layouts/"))+rsLayoutName), + UNO_QUERY_THROW); + + // Read the parent layout first, if one is referenced. + OUString sParentLayout; + rConfiguration.GetConfigurationNode( + xLayoutNode, + OUString(RTL_CONSTASCII_USTRINGPARAM("ParentLayout"))) >>= sParentLayout; + if (sParentLayout.getLength() > 0) + { + // Prevent infinite recursion. + if (rsLayoutName != sParentLayout) + ProcessLayout(rConfiguration, sParentLayout, rxContext, rxAnchorId); + } + + // Process the actual layout list. + Reference<container::XNameAccess> xList ( + rConfiguration.GetConfigurationNode( + xLayoutNode, + OUString(RTL_CONSTASCII_USTRINGPARAM("Layout"))), + UNO_QUERY_THROW); + + ::std::vector<rtl::OUString> aProperties (6); + aProperties[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("PaneURL")); + aProperties[1] = OUString(RTL_CONSTASCII_USTRINGPARAM("ViewURL")); + aProperties[2] = OUString(RTL_CONSTASCII_USTRINGPARAM("RelativeX")); + aProperties[3] = OUString(RTL_CONSTASCII_USTRINGPARAM("RelativeY")); + aProperties[4] = OUString(RTL_CONSTASCII_USTRINGPARAM("RelativeWidth")); + aProperties[5] = OUString(RTL_CONSTASCII_USTRINGPARAM("RelativeHeight")); + mnComponentIndex = 1; + PresenterConfigurationAccess::ForAll( + xList, + aProperties, + ::boost::bind(&PresenterScreen::ProcessComponent, this, + _1, + _2, + rxContext, + rxAnchorId)); + } + catch (RuntimeException&) + { + } +} + + + + +void PresenterScreen::ProcessViewDescriptions ( + PresenterConfigurationAccess& rConfiguration) +{ + try + { + Reference<container::XNameAccess> xViewDescriptionsNode ( + rConfiguration.GetConfigurationNode(A2S("Presenter/Views")), + UNO_QUERY_THROW); + + ::std::vector<rtl::OUString> aProperties (4); + aProperties[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("ViewURL")); + aProperties[1] = OUString(RTL_CONSTASCII_USTRINGPARAM("Title")); + aProperties[2] = OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleTitle")); + aProperties[3] = OUString(RTL_CONSTASCII_USTRINGPARAM("IsOpaque")); + mnComponentIndex = 1; + PresenterConfigurationAccess::ForAll( + xViewDescriptionsNode, + aProperties, + ::boost::bind(&PresenterScreen::ProcessViewDescription, this, _1, _2)); + } + catch (RuntimeException&) + { + OSL_ASSERT(false); + } +} + + + + +void PresenterScreen::ProcessComponent ( + const OUString& rsKey, + const ::std::vector<Any>& rValues, + const Reference<XComponentContext>& rxContext, + const Reference<XResourceId>& rxAnchorId) +{ + (void)rsKey; + + if (rValues.size() != 6) + return; + + try + { + OUString sPaneURL; + OUString sViewURL; + double nX = 0; + double nY = 0; + double nWidth = 0; + double nHeight = 0; + rValues[0] >>= sPaneURL; + rValues[1] >>= sViewURL; + rValues[2] >>= nX; + rValues[3] >>= nY; + rValues[4] >>= nWidth; + rValues[5] >>= nHeight; + + if (nX>=0 && nY>=0 && nWidth>0 && nHeight>0) + { + SetupView( + rxContext, + rxAnchorId, + sPaneURL, + sViewURL, + PresenterPaneContainer::ViewInitializationFunction(), + nX, + nY, + nX+nWidth, + nY+nHeight); + } + } + catch (Exception& e) + { + (void)e; + OSL_ASSERT(false); + } +} + + + + +void PresenterScreen::ProcessViewDescription ( + const OUString& rsKey, + const ::std::vector<Any>& rValues) +{ + (void)rsKey; + + if (rValues.size() != 4) + return; + + try + { + ViewDescriptor aViewDescriptor; + OUString sViewURL; + rValues[0] >>= sViewURL; + rValues[1] >>= aViewDescriptor.msTitle; + rValues[2] >>= aViewDescriptor.msAccessibleTitle; + rValues[3] >>= aViewDescriptor.mbIsOpaque; + if (aViewDescriptor.msAccessibleTitle.getLength()==0) + aViewDescriptor.msAccessibleTitle = aViewDescriptor.msTitle; + maViewDescriptors[sViewURL] = aViewDescriptor; + } + catch (Exception&) + { + OSL_ASSERT(false); + } +} + + + + +void PresenterScreen::SetupView( + const Reference<XComponentContext>& rxContext, + const Reference<XResourceId>& rxAnchorId, + const OUString& rsPaneURL, + const OUString& rsViewURL, + const PresenterPaneContainer::ViewInitializationFunction& rViewInitialization, + const double nLeft, + const double nTop, + const double nRight, + const double nBottom) +{ + Reference<XConfigurationController> xCC (mxConfigurationControllerWeak); + if (xCC.is()) + { + Reference<XResourceId> xPaneId (ResourceId::createWithAnchor(rxContext,rsPaneURL,rxAnchorId)); + // Look up the view descriptor. + ViewDescriptor aViewDescriptor; + ViewDescriptorContainer::const_iterator iDescriptor (maViewDescriptors.find(rsViewURL)); + if (iDescriptor != maViewDescriptors.end()) + aViewDescriptor = iDescriptor->second; + + // Prepare the pane. + OSL_ASSERT(mpPaneContainer.get() != NULL); + mpPaneContainer->PreparePane( + xPaneId, + rsViewURL, + aViewDescriptor.msTitle, + aViewDescriptor.msAccessibleTitle, + aViewDescriptor.mbIsOpaque, + rViewInitialization, + nLeft, + nTop, + nRight, + nBottom); + } +} + + + + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterScreen.hxx b/sdext/source/presenter/PresenterScreen.hxx new file mode 100644 index 000000000000..7096c9f72fe6 --- /dev/null +++ b/sdext/source/presenter/PresenterScreen.hxx @@ -0,0 +1,250 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_SCREEN_HXX +#define SDEXT_PRESENTER_PRESENTER_SCREEN_HXX + +#include "PresenterConfigurationAccess.hxx" +#include "PresenterPaneContainer.hxx" +#include <cppuhelper/compbase1.hxx> +#include <cppuhelper/basemutex.hxx> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/frame/XModel2.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/document/XEventListener.hpp> +#include <com/sun/star/drawing/framework/XConfigurationController.hpp> +#include <com/sun/star/drawing/framework/XView.hpp> +#include <com/sun/star/presentation/XSlideShowController.hpp> +#include <com/sun/star/presentation/XPresentation2.hpp> +#include <rtl/ref.hxx> +#include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/scoped_ptr.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +class PresenterWindowManager; +class PresenterController; + +namespace { + typedef ::cppu::WeakComponentImplHelper1 < + css::task::XJob + > PresenterScreenJobInterfaceBase; + typedef ::cppu::WeakComponentImplHelper1 < + css::lang::XEventListener + > PresenterScreenInterfaceBase; +} + + + + +/** The PresenterScreenJob service is instantiated every time a document is + created or loaded. In its execute() method it then filters out all + non-Impress documents and creates and registers a new PresenterScreen + object. +*/ +class PresenterScreenJob + : private ::boost::noncopyable, + private ::cppu::BaseMutex, + public PresenterScreenJobInterfaceBase +{ +public: + static ::rtl::OUString getImplementationName_static (void); + static css::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static (void); + static css::uno::Reference<css::uno::XInterface> Create( + const css::uno::Reference<css::uno::XComponentContext>& rxContext) + SAL_THROW((css::uno::Exception)); + + virtual void SAL_CALL disposing (void); + + // XJob + + virtual css::uno::Any SAL_CALL execute( + const css::uno::Sequence<css::beans::NamedValue >& Arguments) + throw (css::lang::IllegalArgumentException, + css::uno::Exception, + css::uno::RuntimeException); + +private: + PresenterScreenJob (const css::uno::Reference<css::uno::XComponentContext>& rxContext); + virtual ~PresenterScreenJob (void); + + css::uno::Reference<css::uno::XComponentContext> mxComponentContext; +}; + + + + +/** This is the bootstrap class of the presenter screen. It is registered + as drawing framework startup service. That means that every drawing + framework instance creates an instance of this class. + + <p>A PresenterScreen object registers itself as listener for drawing + framework configuration changes. It waits for the full screen marker (a + top level resource) to appear in the current configuration. When that + happens the actual presenter screen is initialized. A new + PresenterController is created and takes over the task of controlling + the presenter screen.</p> +*/ +class PresenterScreen + : private ::boost::noncopyable, + private ::cppu::BaseMutex, + public PresenterScreenInterfaceBase +{ +public: + PresenterScreen ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::frame::XModel2>& rxModel); + virtual ~PresenterScreen (void); + + virtual void SAL_CALL disposing (void); + + /** Make the presenter screen visible. + */ + void InitializePresenterScreen (void); + + /** Do not call ShutdownPresenterScreen() directly. Call + RequestShutdownPresenterScreen() instead. It will issue an + asynchronous call to ShutdownPresenterScreen() when that is safe. + */ + void RequestShutdownPresenterScreen (void); + + + // XEventListener + + virtual void SAL_CALL disposing ( const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException); + +private: + css::uno::Reference<css::frame::XModel2 > mxModel; + css::uno::Reference<css::frame::XController> mxController; + css::uno::WeakReference<css::drawing::framework::XConfigurationController> + mxConfigurationControllerWeak; + css::uno::WeakReference<css::uno::XComponentContext> mxContextWeak; + css::uno::WeakReference<css::presentation::XSlideShowController> mxSlideShowControllerWeak; + ::rtl::Reference<PresenterController> mpPresenterController; + css::uno::Reference<css::drawing::framework::XResourceId> mxSlideShowViewId; + css::uno::Reference<css::drawing::framework::XConfiguration> mxSavedConfiguration; + ::rtl::Reference<PresenterPaneContainer> mpPaneContainer; + sal_Int32 mnComponentIndex; + css::uno::Reference<css::drawing::framework::XResourceFactory> mxPaneFactory; + css::uno::Reference<css::drawing::framework::XResourceFactory> mxViewFactory; + + class ViewDescriptor + { + public: + ::rtl::OUString msTitle; + ::rtl::OUString msAccessibleTitle; + bool mbIsOpaque; + }; + typedef ::std::map<rtl::OUString,ViewDescriptor> ViewDescriptorContainer; + ViewDescriptorContainer maViewDescriptors; + + + void ShutdownPresenterScreen (void); + + /** Create and initialize the factory for presenter view specific panes. + */ + void SetupPaneFactory ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext); + + /** Create and initialize the factory for presenter view specific views. + */ + void SetupViewFactory ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext); + + /** Read the current layout from the configuration and call + ProcessLayout to bring it on to the screen. + */ + void SetupConfiguration ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxAnchorId); + + /** Read one layout from the configuration and make resource activation + requests to bring it on to the screen. When one layout references a + parent layout then this method calls itself recursively. + */ + void ProcessLayout ( + PresenterConfigurationAccess& rConfiguration, + const ::rtl::OUString& rsLayoutName, + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxAnchorId); + + /** Called by ProcessLayout for a single entry of a Layouts + configuration list. + */ + void ProcessComponent ( + const ::rtl::OUString& rsKey, + const ::std::vector<css::uno::Any>& rValues, + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxAnchorId); + + /** Read the view descriptions from the configuration. + */ + void ProcessViewDescriptions ( + PresenterConfigurationAccess& rConfiguration); + + /** Called by ProcessViewDescriptions for a single entry. + */ + void ProcessViewDescription ( + const ::rtl::OUString& rsKey, + const ::std::vector<css::uno::Any>& rValues); + + void SetupView ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxAnchorId, + const ::rtl::OUString& rsPaneURL, + const ::rtl::OUString& rsViewURL, + const PresenterPaneContainer::ViewInitializationFunction& rViewInitialization, + const double nLeft, + const double nTop, + const double nRight, + const double nBottom); + + /** Return the screen number on which to display the presenter screen. + @return + Returns -1 when the presenter screen can or shall not be + displayed. + */ + sal_Int32 GetScreenNumber ( + const css::uno::Reference<css::presentation::XPresentation2>& rxPresentation) const; + + /** Create a resource id for the full screen background pane so that it + is displayed on another screen than the full screen presentation. + */ + css::uno::Reference<css::drawing::framework::XResourceId> GetMainPaneId ( + const css::uno::Reference<css::presentation::XPresentation2>& rxPresentation) const; +}; + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterScrollBar.cxx b/sdext/source/presenter/PresenterScrollBar.cxx new file mode 100644 index 000000000000..7b78acaed7aa --- /dev/null +++ b/sdext/source/presenter/PresenterScrollBar.cxx @@ -0,0 +1,1348 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterScrollBar.hxx" +#include "PresenterBitmapContainer.hxx" +#include "PresenterCanvasHelper.hxx" +#include "PresenterComponent.hxx" +#include "PresenterGeometryHelper.hxx" +#include "PresenterPaintManager.hxx" +#include "PresenterTimer.hxx" +#include "PresenterUIPainter.hxx" +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/awt/WindowAttribute.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/awt/XToolkit.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/TexturingMode.hpp> +#include <com/sun/star/rendering/XPolyPolygon2D.hpp> +#include <boost/bind.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <boost/weak_ptr.hpp> +#include <math.h> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) + +const static double gnScrollBarGap (10); + +namespace sdext { namespace presenter { + +//===== PresenterScrollBar::MousePressRepeater ================================ + +class PresenterScrollBar::MousePressRepeater + : public ::boost::enable_shared_from_this<MousePressRepeater> +{ +public: + MousePressRepeater (const ::rtl::Reference<PresenterScrollBar>& rpScrollBar); + void Dispose (void); + void Start (const PresenterScrollBar::Area& reArea); + void Stop (void); + void SetMouseArea (const PresenterScrollBar::Area& reArea); + +private: + void Callback (const TimeValue& rCurrentTime); + void Execute (void); + + sal_Int32 mnMousePressRepeaterTaskId; + ::rtl::Reference<PresenterScrollBar> mpScrollBar; + PresenterScrollBar::Area meMouseArea; +}; + + + + +//===== PresenterScrollBar ==================================================== + +boost::weak_ptr<PresenterBitmapContainer> PresenterScrollBar::mpSharedBitmaps; + +PresenterScrollBar::PresenterScrollBar ( + const Reference<XComponentContext>& rxComponentContext, + const Reference<awt::XWindow>& rxParentWindow, + const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager, + const ::boost::function<void(double)>& rThumbMotionListener) + : PresenterScrollBarInterfaceBase(m_aMutex), + mxComponentContext(rxComponentContext), + mxParentWindow(rxParentWindow), + mxWindow(), + mxCanvas(), + mxPresenterHelper(), + mpPaintManager(rpPaintManager), + mnThumbPosition(0), + mnTotalSize(0), + mnThumbSize(0), + mnLineHeight(10), + maDragAnchor(-1,-1), + maThumbMotionListener(rThumbMotionListener), + meButtonDownArea(None), + meMouseMoveArea(None), + mbIsNotificationActive(false), + mpBitmaps(), + mpPrevButtonDescriptor(), + mpNextButtonDescriptor(), + mpPagerStartDescriptor(), + mpPagerCenterDescriptor(), + mpPagerEndDescriptor(), + mpThumbStartDescriptor(), + mpThumbCenterDescriptor(), + mpThumbEndDescriptor(), + mpMousePressRepeater(new MousePressRepeater(this)), + mpBackgroundBitmap(), + mpCanvasHelper(new PresenterCanvasHelper()) +{ + try + { + Reference<lang::XMultiComponentFactory> xFactory (rxComponentContext->getServiceManager()); + if ( ! xFactory.is()) + throw RuntimeException(); + + mxPresenterHelper = Reference<drawing::XPresenterHelper>( + xFactory->createInstanceWithContext( + OUString(RTL_CONSTASCII_USTRINGPARAM("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. The slide show paints its own background. + Reference<awt::XWindowPeer> 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&) + { + } +} + + + + +PresenterScrollBar::~PresenterScrollBar (void) +{ +} + + + + +void SAL_CALL PresenterScrollBar::disposing (void) +{ + mpMousePressRepeater->Dispose(); + + if (mxWindow.is()) + { + mxWindow->removeWindowListener(this); + mxWindow->removePaintListener(this); + mxWindow->removeMouseListener(this); + mxWindow->removeMouseMotionListener(this); + + Reference<lang::XComponent> xComponent (mxWindow, UNO_QUERY); + mxWindow = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + + mpBitmaps.reset(); +} + + + + +void PresenterScrollBar::SetVisible (const bool bIsVisible) +{ + if (mxWindow.is()) + mxWindow->setVisible(bIsVisible); +} + + + + +void PresenterScrollBar::SetPosSize (const css::geometry::RealRectangle2D& rBox) +{ + if (mxWindow.is()) + { + mxWindow->setPosSize( + sal_Int32(floor(rBox.X1)), + sal_Int32(ceil(rBox.Y1)), + sal_Int32(ceil(rBox.X2-rBox.X1)), + sal_Int32(floor(rBox.Y2-rBox.Y1)), + awt::PosSize::POSSIZE); + UpdateBorders(); + } +} + + + + +void PresenterScrollBar::SetThumbPosition ( + double nPosition, + const bool bAsynchronousUpdate) +{ + SetThumbPosition(nPosition, bAsynchronousUpdate, true, true); +} + + + + +void PresenterScrollBar::SetThumbPosition ( + double nPosition, + const bool bAsynchronousUpdate, + const bool bValidate, + const bool bNotify) +{ + if (bValidate) + nPosition = ValidateThumbPosition(nPosition); + + if (nPosition != mnThumbPosition && ! mbIsNotificationActive) + { + mnThumbPosition = nPosition; + + UpdateBorders(); + Repaint(GetRectangle(Total), bAsynchronousUpdate); + if (bNotify) + NotifyThumbPositionChange(); + } +} + + + + +double PresenterScrollBar::GetThumbPosition (void) const +{ + return mnThumbPosition; +} + + + + +void PresenterScrollBar::SetTotalSize (const double nTotalSize) +{ + if (mnTotalSize != nTotalSize) + { + mnTotalSize = nTotalSize + 1; + UpdateBorders(); + Repaint(GetRectangle(Total), false); + } +} + + + + +double PresenterScrollBar::GetTotalSize (void) const +{ + return mnTotalSize; +} + + + + +void PresenterScrollBar::SetThumbSize (const double nThumbSize) +{ + OSL_ASSERT(nThumbSize>=0); + if (mnThumbSize != nThumbSize) + { + mnThumbSize = nThumbSize; + UpdateBorders(); + Repaint(GetRectangle(Total), false); + } +} + + + + +double PresenterScrollBar::GetThumbSize (void) const +{ + return mnThumbSize; +} + + + + +void PresenterScrollBar::SetLineHeight (const double nLineHeight) +{ + mnLineHeight = nLineHeight; +} + + + + +double PresenterScrollBar::GetLineHeight (void) const +{ + return mnLineHeight; +} + + + + +void PresenterScrollBar::SetCanvas (const Reference<css::rendering::XCanvas>& rxCanvas) +{ + if (mxCanvas != rxCanvas) + { + mxCanvas = rxCanvas; + if (mxCanvas.is()) + { + if (mpBitmaps.get()==NULL) + { + if (mpSharedBitmaps.expired()) + { + try + { + mpBitmaps.reset(new PresenterBitmapContainer( + OUString(RTL_CONSTASCII_USTRINGPARAM("PresenterScreenSettings/ScrollBar/Bitmaps")), + ::boost::shared_ptr<PresenterBitmapContainer>(), + mxComponentContext, + mxCanvas, + PresenterComponent::GetBasePath(mxComponentContext))); + mpSharedBitmaps = mpBitmaps; + } + catch(Exception&) + { + OSL_ASSERT(false); + } + } + else + mpBitmaps = ::boost::shared_ptr<PresenterBitmapContainer>(mpSharedBitmaps); + UpdateBitmaps(); + UpdateBorders(); + } + + Repaint(GetRectangle(Total), false); + } + } +} + + + + +void PresenterScrollBar::SetBackground (const SharedBitmapDescriptor& rpBackgroundBitmap) +{ + mpBackgroundBitmap = rpBackgroundBitmap; +} + + + +void PresenterScrollBar::CheckValues (void) +{ + mnThumbPosition = ValidateThumbPosition(mnThumbPosition); +} + + + + +double PresenterScrollBar::ValidateThumbPosition (double nPosition) +{ + if (nPosition + mnThumbSize > mnTotalSize) + nPosition = mnTotalSize - mnThumbSize; + if (nPosition < 0) + nPosition = 0; + return nPosition; +} + + + + +void PresenterScrollBar::Paint ( + const awt::Rectangle& rUpdateBox, + const bool bNoClip) +{ + if ( ! mxCanvas.is() || ! mxWindow.is()) + { + OSL_ASSERT(mxCanvas.is()); + OSL_ASSERT(mxWindow.is()); + return; + } + + if ( ! bNoClip) + { + if (PresenterGeometryHelper::AreRectanglesDisjoint (rUpdateBox, mxWindow->getPosSize())) + return; + } + + PaintBackground(rUpdateBox); + PaintComposite(rUpdateBox, PagerUp, + mpPagerStartDescriptor, mpPagerCenterDescriptor, SharedBitmapDescriptor()); + PaintComposite(rUpdateBox, PagerDown, + SharedBitmapDescriptor(), mpPagerCenterDescriptor, mpPagerEndDescriptor); + PaintComposite(rUpdateBox, Thumb, + mpThumbStartDescriptor, mpThumbCenterDescriptor, mpThumbEndDescriptor); + PaintBitmap(rUpdateBox, PrevButton, mpPrevButtonDescriptor); + PaintBitmap(rUpdateBox, NextButton, mpNextButtonDescriptor); + + Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); + if (xSpriteCanvas.is()) + xSpriteCanvas->updateScreen(sal_False); +} + + + + + + +//----- XWindowListener ------------------------------------------------------- + +void SAL_CALL PresenterScrollBar::windowResized (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + + +void SAL_CALL PresenterScrollBar::windowMoved (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterScrollBar::windowShown (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterScrollBar::windowHidden (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +//----- XPaintListener -------------------------------------------------------- + +void SAL_CALL PresenterScrollBar::windowPaint (const css::awt::PaintEvent& rEvent) + throw (css::uno::RuntimeException) +{ + if (mxWindow.is()) + { + awt::Rectangle aRepaintBox (rEvent.UpdateRect); + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + aRepaintBox.X += aWindowBox.X; + aRepaintBox.Y += aWindowBox.Y; + Paint(aRepaintBox); + + Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); + if (xSpriteCanvas.is()) + xSpriteCanvas->updateScreen(sal_False); + } +} + + + + +//----- XMouseListener -------------------------------------------------------- + +void SAL_CALL PresenterScrollBar::mousePressed (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + maDragAnchor.X = rEvent.X; + maDragAnchor.Y = rEvent.Y; + meButtonDownArea = GetArea(rEvent.X, rEvent.Y); + + mpMousePressRepeater->Start(meButtonDownArea); +} + + + + +void SAL_CALL PresenterScrollBar::mouseReleased (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + (void)rEvent; + + mpMousePressRepeater->Stop(); + + if (mxPresenterHelper.is()) + mxPresenterHelper->releaseMouse(mxWindow); +} + + + + +void SAL_CALL PresenterScrollBar::mouseEntered (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterScrollBar::mouseExited (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + (void)rEvent; + if (meMouseMoveArea != None) + { + const Area eOldMouseMoveArea (meMouseMoveArea); + meMouseMoveArea = None; + Repaint(GetRectangle(eOldMouseMoveArea), true); + } + meButtonDownArea = None; + meMouseMoveArea = None; + + mpMousePressRepeater->Stop(); +} + + + + + +//----- XMouseMotionListener -------------------------------------------------- + +void SAL_CALL PresenterScrollBar::mouseMoved (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + const Area eArea (GetArea(rEvent.X, rEvent.Y)); + if (eArea != meMouseMoveArea) + { + const Area eOldMouseMoveArea (meMouseMoveArea); + meMouseMoveArea = eArea; + if (eOldMouseMoveArea != None) + Repaint(GetRectangle(eOldMouseMoveArea), meMouseMoveArea==None); + if (meMouseMoveArea != None) + Repaint(GetRectangle(meMouseMoveArea), true); + } + mpMousePressRepeater->SetMouseArea(eArea); +} + + + + +void SAL_CALL PresenterScrollBar::mouseDragged (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + if (meButtonDownArea != Thumb) + return; + + mpMousePressRepeater->Stop(); + + if (mxPresenterHelper.is()) + mxPresenterHelper->captureMouse(mxWindow); + + const double nDragDistance (GetDragDistance(rEvent.X,rEvent.Y)); + UpdateDragAnchor(nDragDistance); + if (nDragDistance != 0) + { + SetThumbPosition(mnThumbPosition + nDragDistance, false, true, true); + } +} + + + + +//----- lang::XEventListener -------------------------------------------------- + +void SAL_CALL PresenterScrollBar::disposing (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException) +{ + if (rEvent.Source == mxWindow) + mxWindow = NULL; +} + + + + +//----------------------------------------------------------------------------- + +geometry::RealRectangle2D PresenterScrollBar::GetRectangle (const Area eArea) const +{ + OSL_ASSERT(eArea>=0 && eArea<__AreaCount__); + + return maBox[eArea]; +} + + + + +void PresenterScrollBar::Repaint ( + const geometry::RealRectangle2D aBox, + const bool bAsynchronousUpdate) +{ + if (mpPaintManager.get() != NULL) + mpPaintManager->Invalidate( + mxWindow, + PresenterGeometryHelper::ConvertRectangle(aBox), + bAsynchronousUpdate); +} + + + + +void PresenterScrollBar::PaintBackground( + const css::awt::Rectangle& rUpdateBox) +{ + if (mpBackgroundBitmap.get() == NULL) + return; + + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + mpCanvasHelper->Paint( + mpBackgroundBitmap, + mxCanvas, + rUpdateBox, + aWindowBox, + awt::Rectangle()); +} + + + + +void PresenterScrollBar::PaintBitmap( + const css::awt::Rectangle& rUpdateBox, + const Area eArea, + const SharedBitmapDescriptor& rpBitmaps) +{ + const geometry::RealRectangle2D aLocalBox (GetRectangle(eArea)); + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + geometry::RealRectangle2D aBox (aLocalBox); + aBox.X1 += aWindowBox.X; + aBox.Y1 += aWindowBox.Y; + aBox.X2 += aWindowBox.X; + aBox.Y2 += aWindowBox.Y; + + Reference<rendering::XBitmap> xBitmap (GetBitmap(eArea,rpBitmaps)); + + if (xBitmap.is()) + { + Reference<rendering::XPolyPolygon2D> xClipPolygon ( + PresenterGeometryHelper::CreatePolygon( + PresenterGeometryHelper::Intersection(rUpdateBox, + PresenterGeometryHelper::ConvertRectangle(aBox)), + mxCanvas->getDevice())); + + const rendering::ViewState aViewState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + xClipPolygon); + + const geometry::IntegerSize2D aBitmapSize (xBitmap->getSize()); + rendering::RenderState aRenderState ( + geometry::AffineMatrix2D( + 1,0,aBox.X1 + (aBox.X2-aBox.X1 - aBitmapSize.Width)/2, + 0,1,aBox.Y1 + (aBox.Y2-aBox.Y1 - aBitmapSize.Height)/2), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + + mxCanvas->drawBitmap( + xBitmap, + aViewState, + aRenderState); + } +} + + + + +void PresenterScrollBar::NotifyThumbPositionChange (void) +{ + if ( ! mbIsNotificationActive) + { + mbIsNotificationActive = true; + + try + { + maThumbMotionListener(mnThumbPosition); + } + catch (Exception&) + { + } + + mbIsNotificationActive = false; + } +} + + + + +PresenterScrollBar::Area PresenterScrollBar::GetArea (const double nX, const double nY) const +{ + const geometry::RealPoint2D aPoint(nX, nY); + + if (PresenterGeometryHelper::IsInside(GetRectangle(Pager), aPoint)) + { + if (PresenterGeometryHelper::IsInside(GetRectangle(Thumb), aPoint)) + return Thumb; + else if (PresenterGeometryHelper::IsInside(GetRectangle(PagerUp), aPoint)) + return PagerUp; + else if (PresenterGeometryHelper::IsInside(GetRectangle(PagerDown), aPoint)) + return PagerDown; + } + else if (PresenterGeometryHelper::IsInside(GetRectangle(PrevButton), aPoint)) + return PrevButton; + else if (PresenterGeometryHelper::IsInside(GetRectangle(NextButton), aPoint)) + return NextButton; + + return None; +} + + + + +void PresenterScrollBar::UpdateWidthOrHeight ( + sal_Int32& rSize, + const SharedBitmapDescriptor& rpDescriptor) +{ + if (rpDescriptor.get() != NULL) + { + Reference<rendering::XBitmap> xBitmap (rpDescriptor->GetNormalBitmap()); + if (xBitmap.is()) + { + const geometry::IntegerSize2D aBitmapSize (xBitmap->getSize()); + const sal_Int32 nBitmapSize = (sal_Int32)GetMinor(aBitmapSize.Width, aBitmapSize.Height); + if (nBitmapSize > rSize) + rSize = nBitmapSize; + } + } +} + + + + +css::uno::Reference<css::rendering::XBitmap> PresenterScrollBar::GetBitmap ( + const Area eArea, + const SharedBitmapDescriptor& rpBitmaps) const +{ + if (rpBitmaps.get() == NULL) + return NULL; + else + return rpBitmaps->GetBitmap(GetBitmapMode(eArea)); +} + + + + +PresenterBitmapContainer::BitmapDescriptor::Mode PresenterScrollBar::GetBitmapMode ( + const Area eArea) const +{ + if (IsDisabled(eArea)) + return PresenterBitmapContainer::BitmapDescriptor::Disabled; + else if (eArea == meMouseMoveArea) + return PresenterBitmapContainer::BitmapDescriptor::MouseOver; + else + return PresenterBitmapContainer::BitmapDescriptor::Normal; +} + + + + +bool PresenterScrollBar::IsDisabled (const Area eArea) const +{ + OSL_ASSERT(eArea>=0 && eArea<__AreaCount__); + + return ! maEnabledState[eArea]; +} + + + + +//===== PresenterVerticalScrollBar ============================================ + +PresenterVerticalScrollBar::PresenterVerticalScrollBar ( + const Reference<XComponentContext>& rxComponentContext, + const Reference<awt::XWindow>& rxParentWindow, + const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager, + const ::boost::function<void(double)>& rThumbMotionListener) + : PresenterScrollBar(rxComponentContext, rxParentWindow, rpPaintManager, rThumbMotionListener), + mnScrollBarWidth(0) +{ +} + + + + +PresenterVerticalScrollBar::~PresenterVerticalScrollBar (void) +{ +} + + + + +double PresenterVerticalScrollBar::GetDragDistance (const sal_Int32 nX, const sal_Int32 nY) const +{ + (void)nX; + const double nDistance (nY - maDragAnchor.Y); + if (nDistance == 0) + return 0; + else + { + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + const double nBarWidth (aWindowBox.Width); + const double nPagerHeight (aWindowBox.Height - 2*nBarWidth); + const double nDragDistance (mnTotalSize / nPagerHeight * nDistance); + if (nDragDistance + mnThumbPosition < 0) + return -mnThumbPosition; + else if (mnThumbPosition + nDragDistance > mnTotalSize-mnThumbSize) + return mnTotalSize-mnThumbSize-mnThumbPosition; + else + return nDragDistance; + } +} + + + + +void PresenterVerticalScrollBar::UpdateDragAnchor (const double nDragDistance) +{ + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + const double nBarWidth (aWindowBox.Width); + const double nPagerHeight (aWindowBox.Height - 2*nBarWidth); + maDragAnchor.Y += nDragDistance * nPagerHeight / mnTotalSize; +} + + + + +sal_Int32 PresenterVerticalScrollBar::GetSize (void) const +{ + return mnScrollBarWidth; +} + + + + +geometry::RealPoint2D PresenterVerticalScrollBar::GetPoint ( + const double nMajor, const double nMinor) const +{ + return geometry::RealPoint2D(nMinor, nMajor); +} + + + + +double PresenterVerticalScrollBar::GetMajor (const double nX, const double nY) const +{ + (void)nX; + return nY; +} + + + + +double PresenterVerticalScrollBar::GetMinor (const double nX, const double nY) const +{ + (void)nY; + return nX; +} + + + + +void PresenterVerticalScrollBar::UpdateBorders (void) +{ + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + double nBottom = aWindowBox.Height; + + if (mpNextButtonDescriptor.get() != NULL) + { + Reference<rendering::XBitmap> xBitmap (mpNextButtonDescriptor->GetNormalBitmap()); + if (xBitmap.is()) + { + geometry::IntegerSize2D aSize (xBitmap->getSize()); + maBox[NextButton] = geometry::RealRectangle2D( + 0, nBottom - aSize.Height, aWindowBox.Width, nBottom); + nBottom -= aSize.Height + gnScrollBarGap; + } + } + if (mpPrevButtonDescriptor.get() != NULL) + { + Reference<rendering::XBitmap> xBitmap (mpPrevButtonDescriptor->GetNormalBitmap()); + if (xBitmap.is()) + { + geometry::IntegerSize2D aSize (xBitmap->getSize()); + maBox[PrevButton] = geometry::RealRectangle2D( + 0, nBottom - aSize.Height, aWindowBox.Width, nBottom); + nBottom -= aSize.Height + gnScrollBarGap; + } + } + const double nPagerHeight (nBottom); + maBox[Pager] = geometry::RealRectangle2D( + 0,0, aWindowBox.Width, nBottom); + if (mnTotalSize < 1) + { + maBox[Thumb] = maBox[Pager]; + + // Set up the enabled/disabled states. + maEnabledState[PrevButton] = false; + maEnabledState[PagerUp] = false; + maEnabledState[NextButton] = false; + maEnabledState[PagerDown] = false; + maEnabledState[Thumb] = false; + } + else + { + const double nThumbSize = ::std::min(mnThumbSize,mnTotalSize); + const double nThumbPosition = ::std::min(::std::max(0.0,mnThumbPosition), mnTotalSize - nThumbSize); + maBox[Thumb] = geometry::RealRectangle2D( + 0, nThumbPosition / mnTotalSize * nPagerHeight, + aWindowBox.Width, + (nThumbPosition+nThumbSize) / mnTotalSize * nPagerHeight); + + // Set up the enabled/disabled states. + maEnabledState[PrevButton] = nThumbPosition>0; + maEnabledState[PagerUp] = nThumbPosition>0; + maEnabledState[NextButton] = nThumbPosition+nThumbSize < mnTotalSize; + maEnabledState[PagerDown] = nThumbPosition+nThumbSize < mnTotalSize; + maEnabledState[Thumb] = nThumbSize < mnTotalSize; + } + maBox[PagerUp] = geometry::RealRectangle2D( + maBox[Pager].X1, maBox[Pager].Y1, maBox[Pager].X2, maBox[Thumb].Y1-1); + maBox[PagerDown] = geometry::RealRectangle2D( + maBox[Pager].X1, maBox[Thumb].Y2+1, maBox[Pager].X2, maBox[Pager].Y2); + maBox[Total] = PresenterGeometryHelper::Union( + PresenterGeometryHelper::Union(maBox[PrevButton], maBox[NextButton]), + maBox[Pager]); +} + + + + +void PresenterVerticalScrollBar::UpdateBitmaps (void) +{ + if (mpBitmaps.get() != NULL) + { + mpPrevButtonDescriptor = mpBitmaps->GetBitmap(A2S("Up")); + mpNextButtonDescriptor = mpBitmaps->GetBitmap(A2S("Down")); + mpPagerStartDescriptor = mpBitmaps->GetBitmap(A2S("PagerTop")); + mpPagerCenterDescriptor = mpBitmaps->GetBitmap(A2S("PagerVertical")); + mpPagerEndDescriptor = mpBitmaps->GetBitmap(A2S("PagerBottom")); + mpThumbStartDescriptor = mpBitmaps->GetBitmap(A2S("ThumbTop")); + mpThumbCenterDescriptor = mpBitmaps->GetBitmap(A2S("ThumbVertical")); + mpThumbEndDescriptor = mpBitmaps->GetBitmap(A2S("ThumbBottom")); + + mnScrollBarWidth = 0; + UpdateWidthOrHeight(mnScrollBarWidth, mpPrevButtonDescriptor); + UpdateWidthOrHeight(mnScrollBarWidth, mpNextButtonDescriptor); + UpdateWidthOrHeight(mnScrollBarWidth, mpPagerStartDescriptor); + UpdateWidthOrHeight(mnScrollBarWidth, mpPagerCenterDescriptor); + UpdateWidthOrHeight(mnScrollBarWidth, mpPagerEndDescriptor); + UpdateWidthOrHeight(mnScrollBarWidth, mpThumbStartDescriptor); + UpdateWidthOrHeight(mnScrollBarWidth, mpThumbCenterDescriptor); + UpdateWidthOrHeight(mnScrollBarWidth, mpThumbEndDescriptor); + if (mnScrollBarWidth == 0) + mnScrollBarWidth = 20; + } +} + + + + +void PresenterVerticalScrollBar::PaintComposite( + const css::awt::Rectangle& rUpdateBox, + const Area eArea, + const SharedBitmapDescriptor& rpStartBitmaps, + const SharedBitmapDescriptor& rpCenterBitmaps, + const SharedBitmapDescriptor& rpEndBitmaps) +{ + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + geometry::RealRectangle2D aBox (GetRectangle(eArea)); + aBox.X1 += aWindowBox.X; + aBox.Y1 += aWindowBox.Y; + aBox.X2 += aWindowBox.X; + aBox.Y2 += aWindowBox.Y; + + // Get bitmaps and sizes. + + PresenterUIPainter::PaintVerticalBitmapComposite( + mxCanvas, + rUpdateBox, + (eArea == Thumb + ? PresenterGeometryHelper::ConvertRectangleWithConstantSize(aBox) + : PresenterGeometryHelper::ConvertRectangle(aBox)), + GetBitmap(eArea, rpStartBitmaps), + GetBitmap(eArea, rpCenterBitmaps), + GetBitmap(eArea, rpEndBitmaps)); +} + + + + +//===== PresenterHorizontalScrollBar ============================================ + +PresenterHorizontalScrollBar::PresenterHorizontalScrollBar ( + const Reference<XComponentContext>& rxComponentContext, + const Reference<awt::XWindow>& rxParentWindow, + const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager, + const ::boost::function<void(double)>& rThumbMotionListener) + : PresenterScrollBar(rxComponentContext, rxParentWindow, rpPaintManager, rThumbMotionListener), + mnScrollBarHeight(0) +{ +} + + + + +PresenterHorizontalScrollBar::~PresenterHorizontalScrollBar (void) +{ +} + + + + +double PresenterHorizontalScrollBar::GetDragDistance (const sal_Int32 nX, const sal_Int32 nY) const +{ + (void)nY; + const double nDistance (nX - maDragAnchor.X); + if (nDistance == 0) + return 0; + else + { + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + const double nBarHeight (aWindowBox.Height); + const double nPagerWidth (aWindowBox.Width - 2*nBarHeight); + const double nDragDistance (mnTotalSize / nPagerWidth * nDistance); + if (nDragDistance + mnThumbPosition < 0) + return -mnThumbPosition; + else if (mnThumbPosition + nDragDistance > mnTotalSize-mnThumbSize) + return mnTotalSize-mnThumbSize-mnThumbPosition; + else + return nDragDistance; + } +} + + + + +void PresenterHorizontalScrollBar::UpdateDragAnchor (const double nDragDistance) +{ + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + const double nBarHeight (aWindowBox.Height); + const double nPagerWidth (aWindowBox.Width - 2*nBarHeight); + maDragAnchor.X += nDragDistance * nPagerWidth / mnTotalSize; +} + + + + +sal_Int32 PresenterHorizontalScrollBar::GetSize (void) const +{ + return mnScrollBarHeight; +} + + + + + +geometry::RealPoint2D PresenterHorizontalScrollBar::GetPoint ( + const double nMajor, const double nMinor) const +{ + return geometry::RealPoint2D(nMajor, nMinor); +} + + + + +double PresenterHorizontalScrollBar::GetMajor (const double nX, const double nY) const +{ + (void)nY; + return nX; +} + + + + +double PresenterHorizontalScrollBar::GetMinor (const double nX, const double nY) const +{ + (void)nX; + return nY; +} + + + + +void PresenterHorizontalScrollBar::UpdateBorders (void) +{ + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + double nRight = aWindowBox.Width; + const double nGap (2); + + if (mpNextButtonDescriptor.get() != NULL) + { + Reference<rendering::XBitmap> xBitmap (mpNextButtonDescriptor->GetNormalBitmap()); + if (xBitmap.is()) + { + geometry::IntegerSize2D aSize (xBitmap->getSize()); + maBox[NextButton] = geometry::RealRectangle2D( + nRight - aSize.Width,0, nRight, aWindowBox.Height); + nRight -= aSize.Width + nGap; + } + } + if (mpPrevButtonDescriptor.get() != NULL) + { + Reference<rendering::XBitmap> xBitmap (mpPrevButtonDescriptor->GetNormalBitmap()); + if (xBitmap.is()) + { + geometry::IntegerSize2D aSize (xBitmap->getSize()); + maBox[PrevButton] = geometry::RealRectangle2D( + nRight - aSize.Width,0, nRight, aWindowBox.Height); + nRight -= aSize.Width + nGap; + } + } + + const double nPagerWidth (nRight); + maBox[Pager] = geometry::RealRectangle2D( + 0,0, nRight, aWindowBox.Height); + if (mnTotalSize == 0) + { + maBox[Thumb] = maBox[Pager]; + + // Set up the enabled/disabled states. + maEnabledState[PrevButton] = false; + maEnabledState[PagerUp] = false; + maEnabledState[NextButton] = false; + maEnabledState[PagerDown] = false; + maEnabledState[Thumb] = false; + } + else + { + const double nThumbSize = ::std::min(mnThumbSize,mnTotalSize); + const double nThumbPosition = ::std::min(::std::max(0.0,mnThumbPosition), mnTotalSize - nThumbSize); + maBox[Thumb] = geometry::RealRectangle2D( + (nThumbPosition) / mnTotalSize * nPagerWidth, 0, + (nThumbPosition+nThumbSize) / mnTotalSize * nPagerWidth, aWindowBox.Height); + + // Set up the enabled/disabled states. + maEnabledState[PrevButton] = nThumbPosition>0; + maEnabledState[PagerUp] = nThumbPosition>0; + maEnabledState[NextButton] = nThumbPosition+nThumbSize < mnTotalSize; + maEnabledState[PagerDown] = nThumbPosition+nThumbSize < mnTotalSize; + maEnabledState[Thumb] = nThumbSize < mnTotalSize; + } + maBox[PagerUp] = geometry::RealRectangle2D( + maBox[Pager].X1, maBox[Pager].Y1, maBox[Thumb].X1-1, maBox[Pager].Y2); + maBox[PagerDown] = geometry::RealRectangle2D( + maBox[Thumb].X2+1, maBox[Pager].Y1, maBox[Pager].X2, maBox[Pager].Y2); + maBox[Total] = PresenterGeometryHelper::Union( + PresenterGeometryHelper::Union(maBox[PrevButton], maBox[NextButton]), + maBox[Pager]); +} + + + + +void PresenterHorizontalScrollBar::UpdateBitmaps (void) +{ + if (mpBitmaps.get() != NULL) + { + mpPrevButtonDescriptor = mpBitmaps->GetBitmap(A2S("Left")); + mpNextButtonDescriptor = mpBitmaps->GetBitmap(A2S("Right")); + mpPagerStartDescriptor = mpBitmaps->GetBitmap(A2S("PagerLeft")); + mpPagerCenterDescriptor = mpBitmaps->GetBitmap(A2S("PagerHorizontal")); + mpPagerEndDescriptor = mpBitmaps->GetBitmap(A2S("PagerRight")); + mpThumbStartDescriptor = mpBitmaps->GetBitmap(A2S("ThumbLeft")); + mpThumbCenterDescriptor = mpBitmaps->GetBitmap(A2S("ThumbHorizontal")); + mpThumbEndDescriptor = mpBitmaps->GetBitmap(A2S("ThumbRight")); + + mnScrollBarHeight = 0; + UpdateWidthOrHeight(mnScrollBarHeight, mpPrevButtonDescriptor); + UpdateWidthOrHeight(mnScrollBarHeight, mpNextButtonDescriptor); + UpdateWidthOrHeight(mnScrollBarHeight, mpPagerStartDescriptor); + UpdateWidthOrHeight(mnScrollBarHeight, mpPagerCenterDescriptor); + UpdateWidthOrHeight(mnScrollBarHeight, mpPagerEndDescriptor); + UpdateWidthOrHeight(mnScrollBarHeight, mpThumbStartDescriptor); + UpdateWidthOrHeight(mnScrollBarHeight, mpThumbCenterDescriptor); + UpdateWidthOrHeight(mnScrollBarHeight, mpThumbEndDescriptor); + if (mnScrollBarHeight == 0) + mnScrollBarHeight = 20; + } +} + + + +void PresenterHorizontalScrollBar::PaintComposite( + const css::awt::Rectangle& rUpdateBox, + const Area eArea, + const SharedBitmapDescriptor& rpStartBitmaps, + const SharedBitmapDescriptor& rpCenterBitmaps, + const SharedBitmapDescriptor& rpEndBitmaps) +{ + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + geometry::RealRectangle2D aBox (GetRectangle(eArea)); + aBox.X1 += aWindowBox.X; + aBox.Y1 += aWindowBox.Y; + aBox.X2 += aWindowBox.X; + aBox.Y2 += aWindowBox.Y; + + PresenterUIPainter::PaintHorizontalBitmapComposite( + mxCanvas, + rUpdateBox, + PresenterGeometryHelper::ConvertRectangle(aBox), + GetBitmap(eArea, rpStartBitmaps), + GetBitmap(eArea, rpCenterBitmaps), + GetBitmap(eArea, rpEndBitmaps)); +} + + + + +//===== PresenterScrollBar::MousePressRepeater ================================ + +PresenterScrollBar::MousePressRepeater::MousePressRepeater ( + const ::rtl::Reference<PresenterScrollBar>& rpScrollBar) + : mnMousePressRepeaterTaskId(PresenterTimer::NotAValidTaskId), + mpScrollBar(rpScrollBar), + meMouseArea(PresenterScrollBar::None) +{ +} + + + + +void PresenterScrollBar::MousePressRepeater::Dispose (void) +{ + Stop(); + mpScrollBar = NULL; +} + + + + +void PresenterScrollBar::MousePressRepeater::Start (const PresenterScrollBar::Area& reArea) +{ + meMouseArea = reArea; + + if (mnMousePressRepeaterTaskId == PresenterTimer::NotAValidTaskId) + { + // Execute key press operation at least this one time. + Execute(); + + // Schedule repeated executions. + mnMousePressRepeaterTaskId = PresenterTimer::ScheduleRepeatedTask ( + ::boost::bind(&PresenterScrollBar::MousePressRepeater::Callback, shared_from_this(), _1), + 500000000, + 250000000); + } + else + { + // There is already an active repeating task. + } +} + + + + +void PresenterScrollBar::MousePressRepeater::Stop (void) +{ + if (mnMousePressRepeaterTaskId != PresenterTimer::NotAValidTaskId) + { + const sal_Int32 nTaskId (mnMousePressRepeaterTaskId); + mnMousePressRepeaterTaskId = PresenterTimer::NotAValidTaskId; + PresenterTimer::CancelTask(nTaskId); + } +} + + + + +void PresenterScrollBar::MousePressRepeater::SetMouseArea(const PresenterScrollBar::Area& reArea) +{ + if (meMouseArea != reArea) + { + if (mnMousePressRepeaterTaskId != PresenterTimer::NotAValidTaskId) + { + Stop(); + } + } +} + + + + +void PresenterScrollBar::MousePressRepeater::Callback (const TimeValue& rCurrentTime) +{ + (void)rCurrentTime; + + if (mpScrollBar.get() == NULL) + { + Stop(); + return; + } + + Execute(); +} + + + + +void PresenterScrollBar::MousePressRepeater::Execute (void) +{ + const double nThumbPosition (mpScrollBar->GetThumbPosition()); + switch (meMouseArea) + { + case PrevButton: + mpScrollBar->SetThumbPosition(nThumbPosition - mpScrollBar->GetLineHeight(), true); + break; + + case NextButton: + mpScrollBar->SetThumbPosition(nThumbPosition + mpScrollBar->GetLineHeight(), true); + break; + + case PagerUp: + mpScrollBar->SetThumbPosition(nThumbPosition - mpScrollBar->GetThumbSize()*0.8, true); + break; + + case PagerDown: + mpScrollBar->SetThumbPosition(nThumbPosition + mpScrollBar->GetThumbSize()*0.8, true); + break; + + default: + break; + } +} + + + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterScrollBar.hxx b/sdext/source/presenter/PresenterScrollBar.hxx new file mode 100644 index 000000000000..bd2462387078 --- /dev/null +++ b/sdext/source/presenter/PresenterScrollBar.hxx @@ -0,0 +1,340 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_SCROLL_BAR_HXX +#define SDEXT_PRESENTER_PRESENTER_SCROLL_BAR_HXX + +#include "PresenterBitmapContainer.hxx" +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/rendering/XCanvas.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase4.hxx> +#include <boost/function.hpp> +#include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +class PresenterCanvasHelper; +class PresenterPaintManager; + +namespace { + typedef ::cppu::WeakComponentImplHelper4 < + css::awt::XWindowListener, + css::awt::XPaintListener, + css::awt::XMouseListener, + css::awt::XMouseMotionListener + > PresenterScrollBarInterfaceBase; +} + +/** Base class of horizontal and vertical scroll bars. +*/ +class PresenterScrollBar + : private ::boost::noncopyable, + private ::cppu::BaseMutex, + public PresenterScrollBarInterfaceBase +{ +public: + typedef ::boost::function<void(double)> ThumbMotionListener; + virtual ~PresenterScrollBar (void); + + virtual void SAL_CALL disposing (void); + + void SetVisible (const bool bIsVisible); + + /** Set the bounding box of the scroll bar. + */ + void SetPosSize (const css::geometry::RealRectangle2D& rBox); + + /** Set the position of the movable thumb. + @param nPosition + A value between 0 and the last value given to SetTotalSize() + minus the last value given to SetThumbSize(). + */ + void SetThumbPosition ( + double nPosition, + const bool bAsynchronousRepaint); + + double GetThumbPosition (void) const; + + /** Set the upper border of the slider range. + */ + void SetTotalSize (const double nTotalSize); + + double GetTotalSize (void) const; + + /** Set the size of the movable thumb. + @param nThumbSize + A value not larger than the last value given to SetTotalSize(). + */ + void SetThumbSize (const double nThumbSize); + double GetThumbSize (void) const; + + void SetLineHeight (const double nLineHeight); + double GetLineHeight (void) const; + + /** Set the canvas that is used for painting the scroll bar. + */ + void SetCanvas (const css::uno::Reference<css::rendering::XCanvas>& rxCanvas); + + void SetBackground (const SharedBitmapDescriptor& rpBackgroundBitmap); + + /** Call this after changing total size or thumb position or size to + move the thumb to a valid position. + */ + void CheckValues (void); + + /** On some occasions it is necessary to trigger the painting of a + scrollbar from the outside. + */ + virtual void Paint ( + const css::awt::Rectangle& rUpdateBox, + bool bNoClip = false); + + virtual sal_Int32 GetSize (void) const = 0; + + // XWindowListener + + virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // XPaintListener + + virtual void SAL_CALL windowPaint (const css::awt::PaintEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XMouseListener + + virtual void SAL_CALL mousePressed (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL mouseReleased (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL mouseEntered (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL mouseExited (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + + // XMouseMotionListener + + virtual void SAL_CALL mouseMoved (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseDragged (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + + // lang::XEventListener + virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + enum Area { Total, Pager, Thumb, PagerUp, PagerDown, PrevButton, NextButton, None, + __AreaCount__ = None }; + +protected: + css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + css::uno::Reference<css::awt::XWindow> mxParentWindow; + css::uno::Reference<css::awt::XWindow> mxWindow; + css::uno::Reference<css::rendering::XCanvas> mxCanvas; + css::uno::Reference<css::drawing::XPresenterHelper> mxPresenterHelper; + ::boost::shared_ptr<PresenterPaintManager> mpPaintManager; + double mnThumbPosition; + double mnTotalSize; + double mnThumbSize; + double mnLineHeight; + css::geometry::RealPoint2D maDragAnchor; + ::boost::function<void(double)> maThumbMotionListener; + Area meButtonDownArea; + Area meMouseMoveArea; + css::geometry::RealRectangle2D maBox[__AreaCount__]; + bool mbIsNotificationActive; + static boost::weak_ptr<PresenterBitmapContainer> mpSharedBitmaps; + boost::shared_ptr<PresenterBitmapContainer> mpBitmaps; + SharedBitmapDescriptor mpPrevButtonDescriptor; + SharedBitmapDescriptor mpNextButtonDescriptor; + SharedBitmapDescriptor mpPagerStartDescriptor; + SharedBitmapDescriptor mpPagerCenterDescriptor; + SharedBitmapDescriptor mpPagerEndDescriptor; + SharedBitmapDescriptor mpThumbStartDescriptor; + SharedBitmapDescriptor mpThumbCenterDescriptor; + SharedBitmapDescriptor mpThumbEndDescriptor; + bool maEnabledState[__AreaCount__]; + + virtual css::geometry::RealRectangle2D GetRectangle (const Area eArea) const; + virtual double GetDragDistance (const sal_Int32 nX, const sal_Int32 nY) const = 0; + virtual void UpdateDragAnchor (const double nDragDistance) = 0; + virtual css::geometry::RealPoint2D GetPoint (const double nMajor, const double nMinor) const = 0; + virtual double GetMajor (const double nX, const double nY) const = 0; + virtual double GetMinor (const double nX, const double nY) const = 0; + virtual void UpdateBorders (void) = 0; + virtual void UpdateBitmaps (void) = 0; + virtual void PaintComposite( + const css::awt::Rectangle& rRepaintBox, + const Area eArea, + const SharedBitmapDescriptor& rpStartBitmaps, + const SharedBitmapDescriptor& rpCenterBitmaps, + const SharedBitmapDescriptor& rpEndBitmaps) = 0; + + PresenterScrollBar ( + const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext, + const css::uno::Reference<css::awt::XWindow>& rxParentWindow, + const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager, + const ::boost::function<void(double)>& rThumbMotionListener); + + void Repaint ( + const css::geometry::RealRectangle2D aBox, + const bool bAsynchronous); + void PaintBackground ( + const css::awt::Rectangle& rRepaintBox); + void PaintBitmap( + const css::awt::Rectangle& rRepaintBox, + const Area eArea, + const SharedBitmapDescriptor& rpBitmaps); + void NotifyThumbPositionChange (void); + void UpdateWidthOrHeight (sal_Int32& rSize, + const SharedBitmapDescriptor& rpDescriptor); + css::uno::Reference<css::rendering::XBitmap> GetBitmap ( + const Area eArea, + const SharedBitmapDescriptor& rpBitmaps) const; + PresenterBitmapContainer::BitmapDescriptor::Mode GetBitmapMode ( + const Area eArea) const; + bool IsDisabled (const Area eArea) const; + double ValidateThumbPosition (double nPosition); + void SetThumbPosition ( + double nPosition, + const bool bAsynchronousRepaint, + const bool bValidate, + const bool bNotify); + +private: + class MousePressRepeater; + ::boost::shared_ptr<MousePressRepeater> mpMousePressRepeater; + SharedBitmapDescriptor mpBackgroundBitmap; + ::boost::scoped_ptr<PresenterCanvasHelper> mpCanvasHelper; + + Area GetArea (const double nX, const double nY) const; +}; + + + + +/** A vertical scroll bar. +*/ +class PresenterVerticalScrollBar : public PresenterScrollBar +{ +public: + PresenterVerticalScrollBar ( + const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext, + const css::uno::Reference<css::awt::XWindow>& rxParentWindow, + const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager, + const ::boost::function<void(double)>& rThumbMotionListener); + virtual ~PresenterVerticalScrollBar (void); + virtual sal_Int32 GetSize (void) const; + +protected: + virtual double GetDragDistance (const sal_Int32 nX, const sal_Int32 nY) const; + virtual void UpdateDragAnchor (const double nDragDistance); + virtual css::geometry::RealPoint2D GetPoint (const double nMajor, const double nMinor) const; + virtual double GetMinor (const double nX, const double nY) const; + virtual double GetMajor (const double nX, const double nY) const; + virtual void UpdateBorders (void); + virtual void UpdateBitmaps (void); + virtual void PaintComposite( + const css::awt::Rectangle& rRepaintBox, + const Area eArea, + const SharedBitmapDescriptor& rpStartBitmaps, + const SharedBitmapDescriptor& rpCenterBitmaps, + const SharedBitmapDescriptor& rpEndBitmaps); + +private: + sal_Int32 mnScrollBarWidth; +}; + + + + +/** A horizontal scroll bar. +*/ +class PresenterHorizontalScrollBar : public PresenterScrollBar +{ +public: + PresenterHorizontalScrollBar ( + const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext, + const css::uno::Reference<css::awt::XWindow>& rxParentWindow, + const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager, + const ::boost::function<void(double)>& rThumbMotionListener); + virtual ~PresenterHorizontalScrollBar (void); + virtual sal_Int32 GetSize (void) const; + +protected: + virtual double GetDragDistance (const sal_Int32 nX, const sal_Int32 nY) const; + virtual void UpdateDragAnchor (const double nDragDistance); + virtual css::geometry::RealPoint2D GetPoint (const double nMajor, const double nMinor) const; + virtual double GetMinor (const double nX, const double nY) const; + virtual double GetMajor (const double nX, const double nY) const; + virtual void UpdateBorders (void); + virtual void UpdateBitmaps (void); + virtual void PaintComposite( + const css::awt::Rectangle& rRepaintBox, + const Area eArea, + const SharedBitmapDescriptor& rpStartBitmaps, + const SharedBitmapDescriptor& rpCenterBitmaps, + const SharedBitmapDescriptor& rpEndBitmaps); + +private: + sal_Int32 mnScrollBarHeight; +}; + + + + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterSlidePreview.cxx b/sdext/source/presenter/PresenterSlidePreview.cxx new file mode 100644 index 000000000000..ce5c23a82829 --- /dev/null +++ b/sdext/source/presenter/PresenterSlidePreview.cxx @@ -0,0 +1,429 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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(RTL_CONSTASCII_USTRINGPARAM( + "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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("Width"))) >>= aSlideSize.Width; + xPropertySet->getPropertyValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterSlidePreview.hxx b/sdext/source/presenter/PresenterSlidePreview.hxx new file mode 100644 index 000000000000..57b9f9794b95 --- /dev/null +++ b/sdext/source/presenter/PresenterSlidePreview.hxx @@ -0,0 +1,176 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_SLIDE_PREVIEW_HXX +#define SDEXT_PRESENTER_SLIDE_PREVIEW_HXX + +#include "PresenterController.hxx" + +#include <boost/noncopyable.hpp> +#include <com/sun/star/awt/XBitmap.hpp> +#include <com/sun/star/awt/XDisplayBitmap.hpp> +#include <com/sun/star/awt/XPaintListener.hpp> +#include <com/sun/star/awt/XWindowListener.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/XDrawView.hpp> +#include <com/sun/star/drawing/XSlideRenderer.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/drawing/framework/XView.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase4.hxx> +#include <rtl/ref.hxx> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +namespace { + typedef ::cppu::WeakComponentImplHelper4 < + css::drawing::framework::XView, + css::drawing::XDrawView, + css::awt::XPaintListener, + css::awt::XWindowListener + > PresenterSlidePreviewInterfaceBase; +} + + +/** Static preview of a slide. Typically used for the preview of the next + slide. + This implementation shows a preview of the slide given to the + setCurrentSlide. For showing the next slide the PresenterViewFactory + uses a derived class that overloads the setCurrentSlide() method. +*/ +class PresenterSlidePreview + : private ::boost::noncopyable, + private ::cppu::BaseMutex, + public PresenterSlidePreviewInterfaceBase +{ +public: + PresenterSlidePreview ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId, + const css::uno::Reference<css::drawing::framework::XPane>& rxAnchorPane, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~PresenterSlidePreview (void); + virtual void SAL_CALL disposing (void); + + + // XResourceId + + virtual css::uno::Reference<css::drawing::framework::XResourceId> SAL_CALL getResourceId (void) + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isAnchorOnly (void) + throw (com::sun::star::uno::RuntimeException); + + // XWindowListener + + virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // XPaintListener + + virtual void SAL_CALL windowPaint (const css::awt::PaintEvent& rEvent) + throw (css::uno::RuntimeException); + + + // lang::XEventListener + virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // XDrawView + + virtual void SAL_CALL setCurrentPage ( + const css::uno::Reference<css::drawing::XDrawPage>& rxSlide) + throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::drawing::XDrawPage> SAL_CALL getCurrentPage (void) + throw (css::uno::RuntimeException); + +protected: + ::rtl::Reference<PresenterController> mpPresenterController; + +private: + css::uno::Reference<css::drawing::framework::XPane> mxPane; + css::uno::Reference<css::drawing::framework::XResourceId> mxViewId; + css::uno::Reference<css::drawing::XSlideRenderer> mxPreviewRenderer; + + /** This Image holds the preview of the current slide. After resize + requests the image may be empty. This results eventually in a call + to ProvideSlide() in order to created a preview in the correct new + size. + */ + css::uno::Reference<css::rendering::XBitmap> mxPreview; + + /** The current slide for which a preview is displayed. This may or + may not be the same as the current slide of the PresenterView. + */ + css::uno::Reference<css::drawing::XDrawPage> mxCurrentSlide; + double mnSlideAspectRatio; + + css::uno::Reference<css::awt::XWindow> mxWindow; + css::uno::Reference<css::rendering::XCanvas> mxCanvas; + + /** Set the given slide as the current slide of the called PresenterSlidePreview + object. + */ + void SetSlide (const css::uno::Reference<css::drawing::XDrawPage>& rxPage); + + /** Paint the preview of the current slide centered in the window of the + anchor pane. + */ + void Paint (const css::awt::Rectangle& rBoundingBox); + + /** React to a resize of the anchor pane. + */ + void Resize (void); + + /** This method throws a DisposedException when the object has already been + disposed. + */ + void ThrowIfDisposed (void) throw (css::lang::DisposedException); +}; + +} } // end of namespace ::sd::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterSlideShowView.cxx b/sdext/source/presenter/PresenterSlideShowView.cxx new file mode 100644 index 000000000000..312b07f5fda8 --- /dev/null +++ b/sdext/source/presenter/PresenterSlideShowView.cxx @@ -0,0 +1,1159 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterSlideShowView.hxx" + +#include "PresenterCanvasHelper.hxx" +#include "PresenterGeometryHelper.hxx" +#include "PresenterHelper.hxx" +#include "PresenterPaneContainer.hxx" +#include <com/sun/star/awt/InvalidateStyle.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/awt/WindowAttribute.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/XWindow2.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/drawing/CanvasFeature.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/drawing/framework/XControllerManager.hpp> +#include <com/sun/star/drawing/framework/XConfigurationController.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/TextDirection.hpp> +#include <com/sun/star/rendering/TexturingMode.hpp> +#include <osl/mutex.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) + +namespace sdext { namespace presenter { + +//===== PresenterSlideShowView ================================================ + +PresenterSlideShowView::PresenterSlideShowView ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId, + const css::uno::Reference<css::frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterSlideShowViewInterfaceBase(m_aMutex), + mxComponentContext(rxContext), + mpPresenterController(rpPresenterController), + mxViewId(rxViewId), + mxController(rxController), + mxSlideShowController(PresenterHelper::GetSlideShowController(rxController)), + mxSlideShow(), + mxCanvas(), + mxViewCanvas(), + mxPointer(), + mxWindow(), + mxViewWindow(), + mxTopPane(), + mxPresenterHelper(), + mxBackgroundPolygon1(), + mxBackgroundPolygon2(), + mbIsViewAdded(false), + mnPageAspectRatio(28.0/21.0), + maBroadcaster(m_aMutex), + mpBackground(), + mbIsInModifyNotification(false), + mbIsForcedPaintPending(false), + mbIsPaintPending(true), + msClickToExitPresentationText(), + msClickToExitPresentationTitle(), + msTitleTemplate(), + mbIsEndSlideVisible(false), + mxCurrentSlide() +{ + if (mpPresenterController.get() != NULL) + { + mnPageAspectRatio = mpPresenterController->GetSlideAspectRatio(); + mpBackground = mpPresenterController->GetViewBackground(mxViewId->getResourceURL()); + } +} + + + +void PresenterSlideShowView::LateInit (void) +{ + mxSlideShow = Reference<presentation::XSlideShow> ( + mxSlideShowController->getSlideShow(), UNO_QUERY_THROW); + Reference<lang::XComponent> xSlideShowComponent (mxSlideShow, UNO_QUERY); + if (xSlideShowComponent.is()) + xSlideShowComponent->addEventListener(static_cast<awt::XWindowListener*>(this)); + + Reference<lang::XMultiComponentFactory> xFactory ( + mxComponentContext->getServiceManager(), UNO_QUERY_THROW); + mxPresenterHelper.set (xFactory->createInstanceWithContext( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.PresenterHelper")), + mxComponentContext), + UNO_QUERY_THROW); + + // Use view id and controller to retrieve window and canvas from + // configuration controller. + Reference<XControllerManager> xCM (mxController, UNO_QUERY_THROW); + Reference<XConfigurationController> xCC (xCM->getConfigurationController()); + + if (xCC.is()) + { + mxTopPane.set(xCC->getResource(mxViewId->getAnchor()->getAnchor()), UNO_QUERY); + + Reference<XPane> xPane (xCC->getResource(mxViewId->getAnchor()), UNO_QUERY_THROW); + + mxWindow = xPane->getWindow(); + mxCanvas = xPane->getCanvas(); + + if (mxWindow.is()) + { + mxWindow->addPaintListener(this); + mxWindow->addWindowListener(this); + } + + // The window does not have to paint a background. We do + // that ourself. + Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY); + if (xPeer.is()) + xPeer->setBackground(util::Color(0xff000000)); + } + + // Create a window for the actual slide show view. It is places + // centered and with maximal size inside the pane. + mxViewWindow = CreateViewWindow(mxWindow); + + mxViewCanvas = CreateViewCanvas(mxViewWindow); + + if (mxViewWindow.is()) + { + // Register listeners at window. + mxViewWindow->addPaintListener(this); + mxViewWindow->addMouseListener(this); + mxViewWindow->addMouseMotionListener(this); + } + + if (mxViewWindow.is()) + Resize(); + + if (mxWindow.is()) + mxWindow->setVisible(sal_True); + + // Add the new slide show view to the slide show. + if (mxSlideShow.is() && ! mbIsViewAdded) + { + Reference<presentation::XSlideShowView> xView (this); + mxSlideShow->addView(xView); + // Prevent embeded sounds being played twice at the same time by + // disabling sound for the new slide show view. + beans::PropertyValue aProperty; + aProperty.Name = A2S("IsSoundEnabled"); + Sequence<Any> aValues (2); + aValues[0] <<= xView; + aValues[1] <<= sal_False; + aProperty.Value <<= aValues; + mxSlideShow->setProperty(aProperty); + mbIsViewAdded = true; + } + + // Read text for one past last slide. + PresenterConfigurationAccess aConfiguration ( + mxComponentContext, + PresenterConfigurationAccess::msPresenterScreenRootName, + PresenterConfigurationAccess::READ_ONLY); + aConfiguration.GetConfigurationNode( + A2S("Presenter/Views/CurrentSlidePreview/" + "Strings/ClickToExitPresentationText/String")) + >>= msClickToExitPresentationText; + aConfiguration.GetConfigurationNode( + A2S("Presenter/Views/CurrentSlidePreview/" + "Strings/ClickToExitPresentationTitle/String")) + >>= msClickToExitPresentationTitle; +} + + + + +PresenterSlideShowView::~PresenterSlideShowView (void) +{ +} + + + + +void PresenterSlideShowView::disposing (void) +{ + // Tell all listeners that we are disposed. + lang::EventObject aEvent; + aEvent.Source = static_cast<XWeak*>(this); + + ::cppu::OInterfaceContainerHelper* pIterator + = maBroadcaster.getContainer(getCppuType((Reference<lang::XEventListener>*)NULL)); + if (pIterator != NULL) + pIterator->disposeAndClear(aEvent); + + // Do this for + // XPaintListener, XModifyListener,XMouseListener,XMouseMotionListener,XWindowListener? + + if (mxWindow.is()) + { + mxWindow->removePaintListener(this); + mxWindow->removeMouseListener(this); + mxWindow->removeMouseMotionListener(this); + mxWindow->removeWindowListener(this); + mxWindow = NULL; + } + mxSlideShowController = NULL; + mxSlideShow = NULL; + if (mxViewCanvas.is()) + { + Reference<XComponent> xComponent (mxViewCanvas, UNO_QUERY); + mxViewCanvas = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + if (mxViewWindow.is()) + { + Reference<XComponent> xComponent (mxViewWindow, UNO_QUERY); + mxViewWindow = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + if (mxPointer.is()) + { + Reference<XComponent> xComponent (mxPointer, UNO_QUERY); + mxPointer = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + if (mxBackgroundPolygon1.is()) + { + Reference<XComponent> xComponent (mxBackgroundPolygon1, UNO_QUERY); + mxBackgroundPolygon1 = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + if (mxBackgroundPolygon2.is()) + { + Reference<XComponent> xComponent (mxBackgroundPolygon2, UNO_QUERY); + mxBackgroundPolygon2 = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + + mxComponentContext = NULL; + mpPresenterController = NULL; + mxViewId = NULL; + mxController = NULL; + mxCanvas = NULL; + mpBackground.reset(); + msClickToExitPresentationText = OUString(); + msClickToExitPresentationTitle = OUString(); + msTitleTemplate = OUString(); + mxCurrentSlide = NULL; +} + + + + +//----- XDrawView ------------------------------------------------------------- + +void SAL_CALL PresenterSlideShowView::setCurrentPage ( + const css::uno::Reference<css::drawing::XDrawPage>& rxSlide) + throw (css::uno::RuntimeException) +{ + mxCurrentSlide = rxSlide; + if (mpPresenterController.get() != NULL + && mxSlideShowController.is() + && ! mpPresenterController->GetCurrentSlide().is() + && ! mxSlideShowController->isPaused()) + { + mbIsEndSlideVisible = true; + Reference<awt::XWindowPeer> xPeer (mxViewWindow, UNO_QUERY); + if (xPeer.is()) + xPeer->invalidate(awt::InvalidateStyle::NOTRANSPARENT); + + // For the end slide we use a special title, without the (n of m) + // part. Save the title template for the case that the user goes + // backwards. + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPresenterController->GetPaneContainer()->FindViewURL(mxViewId->getResourceURL())); + if (pDescriptor.get() != NULL) + { + msTitleTemplate = pDescriptor->msTitleTemplate; + pDescriptor->msTitleTemplate = msClickToExitPresentationTitle; + mpPresenterController->UpdatePaneTitles(); + } + } + else if (mbIsEndSlideVisible) + { + mbIsEndSlideVisible = false; + + // Restore the title template. + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPresenterController->GetPaneContainer()->FindViewURL(mxViewId->getResourceURL())); + if (pDescriptor.get() != NULL) + { + pDescriptor->msTitleTemplate = msTitleTemplate; + pDescriptor->msTitle = OUString(); + mpPresenterController->UpdatePaneTitles(); + } + } +} + + + + +css::uno::Reference<css::drawing::XDrawPage> SAL_CALL PresenterSlideShowView::getCurrentPage (void) + throw (css::uno::RuntimeException) +{ + return mxCurrentSlide; +} + + + + +//----- CachablePresenterView ------------------------------------------------- + +void PresenterSlideShowView::ReleaseView (void) +{ + if (mxSlideShow.is() && mbIsViewAdded) + { + mxSlideShow->removeView(this); + mbIsViewAdded = false; + } +} + + + + +//----- XSlideShowView -------------------------------------------------------- + +Reference<rendering::XSpriteCanvas> SAL_CALL PresenterSlideShowView::getCanvas (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + return Reference<rendering::XSpriteCanvas>(mxViewCanvas, UNO_QUERY); +} + + + + +void SAL_CALL PresenterSlideShowView::clear (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + mbIsForcedPaintPending = false; + mbIsPaintPending = false; + + if (mxViewCanvas.is() && mxViewWindow.is()) + { + // Create a polygon for the window outline. + awt::Rectangle aViewWindowBox (mxViewWindow->getPosSize()); + Reference<rendering::XPolyPolygon2D> xPolygon (PresenterGeometryHelper::CreatePolygon( + awt::Rectangle(0,0, aViewWindowBox.Width,aViewWindowBox.Height), + mxViewCanvas->getDevice())); + + rendering::ViewState aViewState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL); + double aColor[3] = {0,0,0}; + rendering::RenderState aRenderState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(aColor,4), + rendering::CompositeOperation::SOURCE); + mxViewCanvas->fillPolyPolygon(xPolygon, aViewState, aRenderState); + } +} + + + + +geometry::AffineMatrix2D SAL_CALL PresenterSlideShowView::getTransformation (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + if (mxViewWindow.is()) + { + // When the mbIsInModifyNotification is set then a slightly modifed + // version of the transformation is returned in order to get past + // optimizations the avoid updates when the transformation is + // unchanged (when the window size changes then due to the constant + // aspect ratio the size of the preview may remain the same while + // the position changes. The position, however, is repesented by + // the position of the view window. This transformation is given + // relative to the view window and therefore does not contain the + // position.) + const awt::Rectangle aWindowBox = mxViewWindow->getPosSize(); + return geometry::AffineMatrix2D( + aWindowBox.Width-1, 0, (mbIsInModifyNotification ? 1 : 0), + 0, aWindowBox.Height-1, 0); + } + else + { + return geometry::AffineMatrix2D(1,0,0, 0,1,0); + } +} + + + + +void SAL_CALL PresenterSlideShowView::addTransformationChangedListener( + const Reference<util::XModifyListener>& rxListener) + throw (RuntimeException) +{ + ThrowIfDisposed(); + maBroadcaster.addListener( + getCppuType((Reference<util::XModifyListener>*)NULL), + rxListener); +} + + + + +void SAL_CALL PresenterSlideShowView::removeTransformationChangedListener( + const Reference<util::XModifyListener>& rxListener) + throw (RuntimeException) +{ + ThrowIfDisposed(); + maBroadcaster.removeListener( + getCppuType((Reference<util::XModifyListener>*)NULL), + rxListener); +} + + + + +void SAL_CALL PresenterSlideShowView::addPaintListener( + const Reference<awt::XPaintListener>& rxListener) + throw (RuntimeException) +{ + ThrowIfDisposed(); + maBroadcaster.addListener( + getCppuType((Reference<awt::XPaintListener>*)NULL), + rxListener); +} + + + + +void SAL_CALL PresenterSlideShowView::removePaintListener( + const Reference<awt::XPaintListener>& rxListener) + throw (RuntimeException) +{ + ThrowIfDisposed(); + maBroadcaster.removeListener( + getCppuType((Reference<awt::XPaintListener>*)NULL), + rxListener); +} + + + + +void SAL_CALL PresenterSlideShowView::addMouseListener( + const Reference<awt::XMouseListener>& rxListener) + throw (RuntimeException) +{ + ThrowIfDisposed(); + maBroadcaster.addListener( + getCppuType((Reference<awt::XMouseListener>*)NULL), + rxListener); +} + + + + +void SAL_CALL PresenterSlideShowView::removeMouseListener( + const Reference<awt::XMouseListener>& rxListener) + throw (RuntimeException) +{ + ThrowIfDisposed(); + maBroadcaster.removeListener( + getCppuType((Reference<awt::XMouseListener>*)NULL), + rxListener); +} + + + + +void SAL_CALL PresenterSlideShowView::addMouseMotionListener( + const Reference<awt::XMouseMotionListener>& rxListener) + throw (RuntimeException) +{ + ThrowIfDisposed(); + maBroadcaster.addListener( + getCppuType((Reference<awt::XMouseMotionListener>*)NULL), + rxListener); +} + + + + +void SAL_CALL PresenterSlideShowView::removeMouseMotionListener( + const Reference<awt::XMouseMotionListener>& rxListener) + throw (RuntimeException) +{ + ThrowIfDisposed(); + maBroadcaster.removeListener( + getCppuType((Reference<awt::XMouseMotionListener>*)NULL), + rxListener); +} + + + + +void SAL_CALL PresenterSlideShowView::setMouseCursor(::sal_Int16 nPointerShape) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + // Create a pointer when it does not yet exist. + if ( ! mxPointer.is()) + { + Reference<lang::XMultiServiceFactory> xFactory ( + mxComponentContext, UNO_QUERY); + if (xFactory.is()) + mxPointer = Reference<awt::XPointer>( + xFactory->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Pointer"))), + UNO_QUERY); + } + + // Set the pointer to the given shape and the window(peer) to the + // pointer. + Reference<awt::XWindowPeer> xPeer (mxViewWindow, UNO_QUERY); + if (mxPointer.is() && xPeer.is()) + { + mxPointer->setType(nPointerShape); + xPeer->setPointer(mxPointer); + } +} + + + +awt::Rectangle SAL_CALL PresenterSlideShowView::getCanvasArea( ) throw (RuntimeException) +{ + if( mxViewWindow.is() && mxTopPane.is() ) + return mxPresenterHelper->getWindowExtentsRelative( mxViewWindow, mxTopPane->getWindow() ); + + awt::Rectangle aRectangle; + + aRectangle.X = aRectangle.Y = aRectangle.Width = aRectangle.Height = 0; + + return aRectangle; +} + + + +//----- lang::XEventListener -------------------------------------------------- + +void SAL_CALL PresenterSlideShowView::disposing (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + if (rEvent.Source == mxViewWindow) + mxViewWindow = NULL; + else if (rEvent.Source == mxSlideShow) + mxSlideShow = NULL; +} + + + + +//----- XPaintListener -------------------------------------------------------- + +void SAL_CALL PresenterSlideShowView::windowPaint (const awt::PaintEvent& rEvent) + throw (RuntimeException) +{ + // Deactivated views must not be painted. + if ( ! mbIsPresenterViewActive) + return; + + awt::Rectangle aViewWindowBox (mxViewWindow->getPosSize()); + if (aViewWindowBox.Width <= 0 || aViewWindowBox.Height <= 0) + return; + + if (rEvent.Source == mxWindow) + PaintOuterWindow(rEvent.UpdateRect); + else if (mbIsEndSlideVisible) + PaintEndSlide(rEvent.UpdateRect); + else + PaintInnerWindow(rEvent); +} + + + + +//----- XMouseListener -------------------------------------------------------- + +void SAL_CALL PresenterSlideShowView::mousePressed (const awt::MouseEvent& rEvent) + throw (RuntimeException) +{ + awt::MouseEvent aEvent (rEvent); + aEvent.Source = static_cast<XWeak*>(this); + ::cppu::OInterfaceContainerHelper* pIterator + = maBroadcaster.getContainer(getCppuType((Reference<awt::XMouseListener>*)NULL)); + if (pIterator != NULL) + { + pIterator->notifyEach(&awt::XMouseListener::mousePressed, aEvent); + } + + // Only when the end slide is displayed we forward the mouse event to + // the PresenterController so that it switches to the next slide and + // ends the presentation. + if (mbIsEndSlideVisible) + if (mpPresenterController.get() != NULL) + mpPresenterController->HandleMouseClick(rEvent); +} + + + + +void SAL_CALL PresenterSlideShowView::mouseReleased (const awt::MouseEvent& rEvent) + throw (RuntimeException) +{ + awt::MouseEvent aEvent (rEvent); + aEvent.Source = static_cast<XWeak*>(this); + ::cppu::OInterfaceContainerHelper* pIterator + = maBroadcaster.getContainer(getCppuType((Reference<awt::XMouseListener>*)NULL)); + if (pIterator != NULL) + { + pIterator->notifyEach(&awt::XMouseListener::mouseReleased, aEvent); + } +} + + + + +void SAL_CALL PresenterSlideShowView::mouseEntered (const awt::MouseEvent& rEvent) + throw (RuntimeException) +{ + awt::MouseEvent aEvent (rEvent); + aEvent.Source = static_cast<XWeak*>(this); + ::cppu::OInterfaceContainerHelper* pIterator + = maBroadcaster.getContainer(getCppuType((Reference<awt::XMouseListener>*)NULL)); + if (pIterator != NULL) + { + pIterator->notifyEach(&awt::XMouseListener::mouseEntered, aEvent); + } +} + + + + +void SAL_CALL PresenterSlideShowView::mouseExited (const awt::MouseEvent& rEvent) + throw (RuntimeException) +{ + awt::MouseEvent aEvent (rEvent); + aEvent.Source = static_cast<XWeak*>(this); + ::cppu::OInterfaceContainerHelper* pIterator + = maBroadcaster.getContainer(getCppuType((Reference<awt::XMouseListener>*)NULL)); + if (pIterator != NULL) + { + pIterator->notifyEach(&awt::XMouseListener::mouseExited, aEvent); + } +} + + + + +//----- XMouseMotionListener -------------------------------------------------- + +void SAL_CALL PresenterSlideShowView::mouseDragged (const awt::MouseEvent& rEvent) + throw (RuntimeException) +{ + awt::MouseEvent aEvent (rEvent); + aEvent.Source = static_cast<XWeak*>(this); + ::cppu::OInterfaceContainerHelper* pIterator + = maBroadcaster.getContainer(getCppuType((Reference<awt::XMouseMotionListener>*)NULL)); + if (pIterator != NULL) + { + pIterator->notifyEach(&awt::XMouseMotionListener::mouseDragged, aEvent); + } +} + + + + +void SAL_CALL PresenterSlideShowView::mouseMoved (const awt::MouseEvent& rEvent) + throw (RuntimeException) +{ + awt::MouseEvent aEvent (rEvent); + aEvent.Source = static_cast<XWeak*>(this); + ::cppu::OInterfaceContainerHelper* pIterator + = maBroadcaster.getContainer(getCppuType((Reference<awt::XMouseMotionListener>*)NULL)); + if (pIterator != NULL) + { + pIterator->notifyEach(&awt::XMouseMotionListener::mouseMoved, aEvent); + } +} + + + + +//----- XWindowListener ------------------------------------------------------- + +void SAL_CALL PresenterSlideShowView::windowResized (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + + ThrowIfDisposed(); + ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex()); + + Resize(); +} + + + + + +void SAL_CALL PresenterSlideShowView::windowMoved (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + if ( ! mbIsPaintPending) + mbIsForcedPaintPending = true; +} + + + + +void SAL_CALL PresenterSlideShowView::windowShown (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + Resize(); +} + + + + +void SAL_CALL PresenterSlideShowView::windowHidden (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; +} + + + + +//----- XView ----------------------------------------------------------------- + +Reference<XResourceId> SAL_CALL PresenterSlideShowView::getResourceId (void) + throw(RuntimeException) +{ + return mxViewId; +} + + + + +sal_Bool SAL_CALL PresenterSlideShowView::isAnchorOnly (void) + throw (RuntimeException) +{ + return false; +} + + + + +//----- CachablePresenterView ------------------------------------------------- + +void PresenterSlideShowView::ActivatePresenterView (void) +{ + if (mxSlideShow.is() && ! mbIsViewAdded) + { + mxSlideShow->addView(this); + mbIsViewAdded = true; + } +} + + + + +void PresenterSlideShowView::DeactivatePresenterView (void) +{ + if (mxSlideShow.is() && mbIsViewAdded) + { + mxSlideShow->removeView(this); + mbIsViewAdded = false; + } +} + + + + +//----------------------------------------------------------------------------- + +void PresenterSlideShowView::PaintOuterWindow (const awt::Rectangle& rRepaintBox) +{ + if ( ! mxCanvas.is()) + return; + + if (mpBackground.get() == NULL) + return; + + const rendering::ViewState aViewState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + PresenterGeometryHelper::CreatePolygon(rRepaintBox, mxCanvas->getDevice())); + + rendering::RenderState aRenderState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + + Reference<rendering::XBitmap> xBackgroundBitmap (mpBackground->GetNormalBitmap()); + if (xBackgroundBitmap.is()) + { + Sequence<rendering::Texture> aTextures (1); + const geometry::IntegerSize2D aBitmapSize(xBackgroundBitmap->getSize()); + aTextures[0] = rendering::Texture ( + geometry::AffineMatrix2D( + aBitmapSize.Width,0,0, + 0,aBitmapSize.Height,0), + 1, + 0, + xBackgroundBitmap, + NULL, + NULL, + rendering::StrokeAttributes(), + rendering::TexturingMode::REPEAT, + rendering::TexturingMode::REPEAT); + + if (mxBackgroundPolygon1.is()) + mxCanvas->fillTexturedPolyPolygon( + mxBackgroundPolygon1, + aViewState, + aRenderState, + aTextures); + if (mxBackgroundPolygon2.is()) + mxCanvas->fillTexturedPolyPolygon( + mxBackgroundPolygon2, + aViewState, + aRenderState, + aTextures); + } + else + { + PresenterCanvasHelper::SetDeviceColor(aRenderState, mpBackground->maReplacementColor); + + if (mxBackgroundPolygon1.is()) + mxCanvas->fillPolyPolygon(mxBackgroundPolygon1, aViewState, aRenderState); + if (mxBackgroundPolygon2.is()) + mxCanvas->fillPolyPolygon(mxBackgroundPolygon2, aViewState, aRenderState); + } +} + + + + +void PresenterSlideShowView::PaintEndSlide (const awt::Rectangle& rRepaintBox) +{ + if ( ! mxCanvas.is()) + return; + + const rendering::ViewState aViewState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + PresenterGeometryHelper::CreatePolygon(rRepaintBox, mxCanvas->getDevice())); + + rendering::RenderState aRenderState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x00000000)); + mxCanvas->fillPolyPolygon( + PresenterGeometryHelper::CreatePolygon(mxViewWindow->getPosSize(), mxCanvas->getDevice()), + aViewState, + aRenderState); + + do + { + if (mpPresenterController.get() == NULL) + break; + ::boost::shared_ptr<PresenterTheme> pTheme (mpPresenterController->GetTheme()); + if (pTheme.get() == NULL) + break; + + const OUString sViewStyle (pTheme->GetStyleName(mxViewId->getResourceURL())); + PresenterTheme::SharedFontDescriptor pFont (pTheme->GetFont(sViewStyle)); + if (pFont.get() == NULL) + break; + + PresenterCanvasHelper::SetDeviceColor(aRenderState, util::Color(0x00ffffff)); + aRenderState.AffineTransform.m02 = 20; + aRenderState.AffineTransform.m12 = 40; + const rendering::StringContext aContext ( + msClickToExitPresentationText, 0, msClickToExitPresentationText.getLength()); + pFont->PrepareFont(mxCanvas); + mxCanvas->drawText( + aContext, + pFont->mxFont, + aViewState, + aRenderState, + rendering::TextDirection::WEAK_LEFT_TO_RIGHT); + } + while (false); + + // Finally, in double buffered environments, request the changes to be + // made visible. + Reference<rendering::XSpriteCanvas> mxSpriteCanvas (mxCanvas, UNO_QUERY); + if (mxSpriteCanvas.is()) + mxSpriteCanvas->updateScreen(sal_True); +} + + + + +void PresenterSlideShowView::PaintInnerWindow (const awt::PaintEvent& rEvent) +{ + // Forward window paint to listeners. + awt::PaintEvent aEvent (rEvent); + aEvent.Source = static_cast<XWeak*>(this); + ::cppu::OInterfaceContainerHelper* pIterator + = maBroadcaster.getContainer(getCppuType((Reference<awt::XPaintListener>*)NULL)); + if (pIterator != NULL) + { + pIterator->notifyEach(&awt::XPaintListener::windowPaint, aEvent); + } + + if (mbIsForcedPaintPending) + ForceRepaint(); + + // Finally, in double buffered environments, request the changes to be + // made visible. + Reference<rendering::XSpriteCanvas> mxSpriteCanvas (mxCanvas, UNO_QUERY); + if (mxSpriteCanvas.is()) + mxSpriteCanvas->updateScreen(sal_True); +} + + + + +Reference<awt::XWindow> PresenterSlideShowView::CreateViewWindow ( + const Reference<awt::XWindow>& rxParentWindow) const +{ + Reference<awt::XWindow> xViewWindow; + try + { + Reference<lang::XMultiComponentFactory> xFactory (mxComponentContext->getServiceManager()); + if ( ! xFactory.is()) + return xViewWindow; + + Reference<awt::XToolkit> xToolkit ( + xFactory->createInstanceWithContext( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Toolkit")), + mxComponentContext), + UNO_QUERY_THROW); + awt::WindowDescriptor aWindowDescriptor ( + awt::WindowClass_CONTAINER, + OUString(), + Reference<awt::XWindowPeer>(rxParentWindow,UNO_QUERY_THROW), + -1, // parent index not available + awt::Rectangle(0,0,10,10), + awt::WindowAttribute::SIZEABLE + | awt::WindowAttribute::MOVEABLE + | awt::WindowAttribute::NODECORATION); + xViewWindow = Reference<awt::XWindow>( + xToolkit->createWindow(aWindowDescriptor),UNO_QUERY_THROW); + + // Make the background transparent. The slide show paints its own background. + Reference<awt::XWindowPeer> xPeer (xViewWindow, UNO_QUERY_THROW); + if (xPeer.is()) + { + xPeer->setBackground(0xff000000); + } + + xViewWindow->setVisible(sal_True); + } + catch (RuntimeException&) + { + } + return xViewWindow; +} + + + + +Reference<rendering::XCanvas> PresenterSlideShowView::CreateViewCanvas ( + const Reference<awt::XWindow>& rxViewWindow) const +{ + // Create a canvas for the view window. + return mxPresenterHelper->createSharedCanvas( + Reference<rendering::XSpriteCanvas>(mxTopPane->getCanvas(), UNO_QUERY), + mxTopPane->getWindow(), + mxTopPane->getCanvas(), + mxTopPane->getWindow(), + rxViewWindow); +} + + + + +void PresenterSlideShowView::Resize (void) +{ + if ( ! mxWindow.is() || ! mxViewWindow.is()) + return; + + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + awt::Rectangle aViewWindowBox; + if (aWindowBox.Height > 0) + { + const double nWindowAspectRatio ( + double(aWindowBox.Width) / double(aWindowBox.Height)); + if (nWindowAspectRatio > mnPageAspectRatio) + { + // Slides will be painted with the full parent window height. + aViewWindowBox.Width = sal_Int32(aWindowBox.Height * mnPageAspectRatio + 0.5); + aViewWindowBox.Height = aWindowBox.Height; + aViewWindowBox.X = (aWindowBox.Width - aViewWindowBox.Width) / 2; + aViewWindowBox.Y = 0; + } + else + { + // Slides will be painted with the full parent window width. + aViewWindowBox.Width = aWindowBox.Width; + aViewWindowBox.Height = sal_Int32(aWindowBox.Width / mnPageAspectRatio + 0.5); + aViewWindowBox.X = 0; + aViewWindowBox.Y = (aWindowBox.Height - aViewWindowBox.Height) / 2; + } + mxViewWindow->setPosSize( + aViewWindowBox.X, + aViewWindowBox.Y, + aViewWindowBox.Width, + aViewWindowBox.Height, + awt::PosSize::POSSIZE); + } + + // Clear the background polygon so that on the next paint it is created + // for the new size. + CreateBackgroundPolygons(); + + // Notify listeners that the transformation that maps the view into the + // window has changed. + lang::EventObject aEvent (static_cast<XWeak*>(this)); + ::cppu::OInterfaceContainerHelper* pIterator + = maBroadcaster.getContainer(getCppuType((Reference<util::XModifyListener>*)NULL)); + if (pIterator != NULL) + { + pIterator->notifyEach(&util::XModifyListener::modified, aEvent); + } + + // Due to constant aspect ratio resizing may lead a preview that changes + // its position but not its size. This invalidates the back buffer and + // we have to enforce a complete repaint. + if ( ! mbIsPaintPending) + mbIsForcedPaintPending = true; +} + + + + +void PresenterSlideShowView::ForceRepaint (void) +{ + if (mxSlideShow.is() && mbIsViewAdded) + { + mxSlideShow->removeView(this); + mxSlideShow->addView(this); + } +} + + + + +void PresenterSlideShowView::CreateBackgroundPolygons (void) +{ + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + const awt::Rectangle aViewWindowBox (mxViewWindow->getPosSize()); + if (aWindowBox.Height == aViewWindowBox.Height && aWindowBox.Width == aViewWindowBox.Width) + { + mxBackgroundPolygon1 = NULL; + mxBackgroundPolygon2 = NULL; + } + else if (aWindowBox.Height == aViewWindowBox.Height) + { + // Paint two boxes to the left and right of the view window. + mxBackgroundPolygon1 = PresenterGeometryHelper::CreatePolygon( + awt::Rectangle( + 0, + 0, + aViewWindowBox.X, + aWindowBox.Height), + mxCanvas->getDevice()); + mxBackgroundPolygon2 = PresenterGeometryHelper::CreatePolygon( + awt::Rectangle( + aViewWindowBox.X + aViewWindowBox.Width, + 0, + aWindowBox.Width - aViewWindowBox.X - aViewWindowBox.Width, + aWindowBox.Height), + mxCanvas->getDevice()); + } + else + { + // Paint two boxes above and below the view window. + mxBackgroundPolygon1 = PresenterGeometryHelper::CreatePolygon( + awt::Rectangle( + 0, + 0, + aWindowBox.Width, + aViewWindowBox.Y), + mxCanvas->getDevice()); + mxBackgroundPolygon2 = PresenterGeometryHelper::CreatePolygon( + awt::Rectangle( + 0, + aViewWindowBox.Y + aViewWindowBox.Height, + aWindowBox.Width, + aWindowBox.Height - aViewWindowBox.Y - aViewWindowBox.Height), + mxCanvas->getDevice()); + } +} + + + + +void PresenterSlideShowView::ThrowIfDisposed (void) + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM("PresenterSlideShowView object has already been disposed")), + static_cast<uno::XWeak*>(this)); + } +} + + +} } // end of namespace ::sd::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterSlideShowView.hxx b/sdext/source/presenter/PresenterSlideShowView.hxx new file mode 100644 index 000000000000..bb91fb5e136c --- /dev/null +++ b/sdext/source/presenter/PresenterSlideShowView.hxx @@ -0,0 +1,300 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_SLIDE_SHOW_VIEW_HXX +#define SDEXT_PRESENTER_SLIDE_SHOW_VIEW_HXX + +#include "PresenterViewFactory.hxx" +#include <com/sun/star/presentation/XSlideShowView.hpp> +#include <com/sun/star/awt/XPaintListener.hpp> +#include <com/sun/star/awt/XMouseListener.hpp> +#include <com/sun/star/awt/XMouseMotionListener.hpp> +#include <com/sun/star/awt/XPointer.hpp> +#include <com/sun/star/awt/XWindowListener.hpp> +#include <com/sun/star/drawing/XDrawView.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/drawing/framework/XResourceId.hpp> +#include <com/sun/star/drawing/framework/XView.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/presentation/XSlideShowController.hpp> +#include <com/sun/star/rendering/XPolyPolygon2D.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/util/Color.hpp> +#include <cppuhelper/compbase7.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <cppuhelper/basemutex.hxx> +#include <boost/noncopyable.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +namespace { + typedef cppu::WeakComponentImplHelper7< + css::presentation::XSlideShowView, + css::awt::XPaintListener, + css::awt::XMouseListener, + css::awt::XMouseMotionListener, + css::awt::XWindowListener, + css::drawing::framework::XView, + css::drawing::XDrawView + > PresenterSlideShowViewInterfaceBase; +} + +/** Life view in a secondary windo of a full screen slide show. +*/ +class PresenterSlideShowView + : private ::boost::noncopyable, + protected ::cppu::BaseMutex, + public PresenterSlideShowViewInterfaceBase, + public CachablePresenterView +{ +public: + PresenterSlideShowView ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId, + const css::uno::Reference<css::frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~PresenterSlideShowView (void); + + void LateInit (void); + virtual void SAL_CALL disposing (void); + + + // CachablePresenterView + + virtual void ReleaseView (void); + + + // XSlideShowView + + virtual css::uno::Reference< + css::rendering::XSpriteCanvas > SAL_CALL getCanvas (void) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL clear (void) + throw (css::uno::RuntimeException); + + virtual css::geometry::AffineMatrix2D SAL_CALL getTransformation (void) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL addTransformationChangedListener( + const css::uno::Reference< + css::util::XModifyListener >& xListener) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL removeTransformationChangedListener( + const css::uno::Reference< + css::util::XModifyListener >& xListener) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL addPaintListener( + const css::uno::Reference< + css::awt::XPaintListener >& xListener) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL removePaintListener( + const css::uno::Reference< + css::awt::XPaintListener >& xListener) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL addMouseListener( + const css::uno::Reference< + css::awt::XMouseListener >& xListener) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL removeMouseListener( + const css::uno::Reference< + css::awt::XMouseListener >& xListener) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL addMouseMotionListener( + const css::uno::Reference< + css::awt::XMouseMotionListener >& xListener) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL removeMouseMotionListener( + const css::uno::Reference< + css::awt::XMouseMotionListener >& xListener) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL setMouseCursor(::sal_Int16 nPointerShape) + throw (css::uno::RuntimeException); + + virtual ::com::sun::star::awt::Rectangle SAL_CALL getCanvasArea( ) + throw (::com::sun::star::uno::RuntimeException); + + // lang::XEventListener + virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // XPaintListener + virtual void SAL_CALL windowPaint (const css::awt::PaintEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XMouseListener + virtual void SAL_CALL mousePressed (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseReleased (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseEntered (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseExited (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XMouseMotionListener + + virtual void SAL_CALL mouseDragged (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseMoved (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XWindowListener + + virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // XView + + virtual css::uno::Reference<css::drawing::framework::XResourceId> SAL_CALL + getResourceId (void) + throw(css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isAnchorOnly (void) + throw (com::sun::star::uno::RuntimeException); + + + // XDrawView + + virtual void SAL_CALL setCurrentPage ( + const css::uno::Reference<css::drawing::XDrawPage>& rxSlide) + throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::drawing::XDrawPage> SAL_CALL getCurrentPage (void) + throw (css::uno::RuntimeException); + + + // CachablePresenterView + + virtual void ActivatePresenterView (void); + + virtual void DeactivatePresenterView (void); + +private: + css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + ::rtl::Reference<PresenterController> mpPresenterController; + css::uno::Reference<css::drawing::framework::XResourceId> mxViewId; + css::uno::Reference<css::frame::XController> mxController; + css::uno::Reference<css::presentation::XSlideShowController> mxSlideShowController; + css::uno::Reference<css::presentation::XSlideShow> mxSlideShow; + css::uno::Reference<css::rendering::XCanvas> mxCanvas; + css::uno::Reference<css::rendering::XCanvas> mxViewCanvas; + css::uno::Reference<css::awt::XPointer> mxPointer; + css::uno::Reference<css::awt::XWindow> mxWindow; + css::uno::Reference<css::awt::XWindow> mxViewWindow; + css::uno::Reference<css::drawing::framework::XPane> mxTopPane; + css::uno::Reference<css::drawing::XPresenterHelper> mxPresenterHelper; + css::uno::Reference<css::rendering::XPolyPolygon2D> mxBackgroundPolygon1; + css::uno::Reference<css::rendering::XPolyPolygon2D> mxBackgroundPolygon2; + bool mbIsViewAdded; + + /** Aspect ratio of the current slide. + */ + double mnPageAspectRatio; + + /** This broadcast helper is used to notify listeners registed to a + SlideShowView object. + */ + ::cppu::OBroadcastHelper maBroadcaster; + + SharedBitmapDescriptor mpBackground; + + bool mbIsInModifyNotification; + bool mbIsForcedPaintPending; + bool mbIsPaintPending; + ::rtl::OUString msClickToExitPresentationText; + ::rtl::OUString msClickToExitPresentationTitle; + ::rtl::OUString msTitleTemplate; + bool mbIsEndSlideVisible; + css::uno::Reference<css::drawing::XDrawPage> mxCurrentSlide; + + /** Create the window into which the slide show will render its + content. This window has the correct aspect ratio and is displayed centered + and as large as possible in its parent window. + */ + css::uno::Reference<css::awt::XWindow> CreateViewWindow ( + const css::uno::Reference<css::awt::XWindow>& rxParentWindow) const; + css::uno::Reference<css::rendering::XCanvas> CreateViewCanvas ( + const css::uno::Reference<css::awt::XWindow>& rxWindow) const; + + void Resize (void); + + void PaintOuterWindow (const css::awt::Rectangle& rRepaintBox); + void PaintInnerWindow (const css::awt::PaintEvent& rEvent); + void PaintEndSlide (const css::awt::Rectangle& rRepaintBox); + + /** The slide show relies on the back buffer of the canvas not being + modified. With a shared canvas there are times when that can not be + guaranteed. + Call this method when the back buffer may have changed its content, + like when the window has been moved but not resized. + */ + void ForceRepaint (void); + + void CreateBackgroundPolygons (void); + + /** This method throws a DisposedException when the object has already been + disposed. + */ + void ThrowIfDisposed (void) + throw (css::lang::DisposedException); +}; + +} } // end of namespace ::sd::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterSlideSorter.cxx b/sdext/source/presenter/PresenterSlideSorter.cxx new file mode 100644 index 000000000000..3fe9051949c1 --- /dev/null +++ b/sdext/source/presenter/PresenterSlideSorter.cxx @@ -0,0 +1,2324 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterSlideSorter.hxx" +#include "PresenterButton.hxx" +#include "PresenterCanvasHelper.hxx" +#include "PresenterComponent.hxx" +#include "PresenterGeometryHelper.hxx" +#include "PresenterHelper.hxx" +#include "PresenterPaintManager.hxx" +#include "PresenterPaneBase.hxx" +#include "PresenterScrollBar.hxx" +#include "PresenterUIPainter.hxx" +#include "PresenterWindowManager.hxx" +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XNamed.hpp> +#include <com/sun/star/drawing/XSlideSorterBase.hpp> +#include <com/sun/star/drawing/framework/XConfigurationController.hpp> +#include <com/sun/star/drawing/framework/XControllerManager.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/TextDirection.hpp> +#include <com/sun/star/rendering/XPolyPolygon2D.hpp> +#include <com/sun/star/util/Color.hpp> +#include <algorithm> +#include <math.h> +#include <boost/bind.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) + +namespace { + const static sal_Int32 gnVerticalGap (10); + const static sal_Int32 gnVerticalBorder (10); + const static sal_Int32 gnHorizontalGap (10); + const static sal_Int32 gnHorizontalBorder (10); + + const static double gnMinimalPreviewWidth (200); + const static double gnPreferredPreviewWidth (300); + const static double gnMaximalPreviewWidth (400); + const static sal_Int32 gnPreferredColumnCount (6); + const static double gnMinimalHorizontalPreviewGap(15); + const static double gnPreferredHorizontalPreviewGap(25); + const static double gnMaximalHorizontalPreviewGap(50); + const static double gnMinimalVerticalPreviewGap(15); + const static double gnPreferredVerticalPreviewGap(25); + const static double gnMaximalVerticalPreviewGap(50); + + const static sal_Int32 gnHorizontalLabelBorder (3); + const static sal_Int32 gnHorizontalLabelPadding (5); + + const static sal_Int32 gnVerticalButtonPadding (gnVerticalGap); +} + +namespace sdext { namespace presenter { + +namespace { + sal_Int32 round (const double nValue) { return sal::static_int_cast<sal_Int32>(0.5 + nValue); } + sal_Int32 floor (const double nValue) { return sal::static_int_cast<sal_Int32>(nValue); } +} + + + +//===== PresenterSlideSorter::Layout ========================================== + +class PresenterSlideSorter::Layout +{ +public: + enum Orientation { Horizontal, Vertical }; + Layout ( + const Orientation eOrientation, + const ::rtl::Reference<PresenterScrollBar>& rpHorizontalScrollBar, + const ::rtl::Reference<PresenterScrollBar>& rpVerticalScrollBar); + + void Update (const geometry::RealRectangle2D& rBoundingBox, const double nSlideAspectRatio); + void SetupVisibleArea (void); + void UpdateScrollBars (void); + bool IsScrollBarNeeded (const sal_Int32 nSlideCount); + geometry::RealPoint2D GetLocalPosition (const geometry::RealPoint2D& rWindowPoint) const; + geometry::RealPoint2D GetWindowPosition(const geometry::RealPoint2D& rLocalPoint) const; + sal_Int32 GetColumn (const geometry::RealPoint2D& rLocalPoint, + const bool bReturnInvalidValue = false) const; + sal_Int32 GetRow (const geometry::RealPoint2D& rLocalPoint, + const bool bReturnInvalidValue = false) const; + sal_Int32 GetSlideIndexForPosition (const css::geometry::RealPoint2D& rPoint) const; + css::geometry::RealPoint2D GetPoint ( + const sal_Int32 nSlideIndex, + const sal_Int32 nRelativeHorizontalPosition, + const sal_Int32 nRelativeVerticalPosition) const; + css::awt::Rectangle GetBoundingBox (const sal_Int32 nSlideIndex) const; + void ForAllVisibleSlides (const ::boost::function<void(sal_Int32)>& rAction); + sal_Int32 GetFirstVisibleSlideIndex (void) const; + sal_Int32 GetLastVisibleSlideIndex (void) const; + bool SetHorizontalOffset (const double nOffset); + bool SetVerticalOffset (const double nOffset); + Orientation GetOrientation (void) const; + + css::geometry::RealRectangle2D maBoundingBox; + css::geometry::IntegerSize2D maPreviewSize; + sal_Int32 mnHorizontalOffset; + sal_Int32 mnVerticalOffset; + sal_Int32 mnHorizontalGap; + sal_Int32 mnVerticalGap; + sal_Int32 mnHorizontalBorder; + sal_Int32 mnVerticalBorder; + sal_Int32 mnRowCount; + sal_Int32 mnColumnCount; + sal_Int32 mnSlideCount; + sal_Int32 mnSlideIndexAtMouse; + sal_Int32 mnFirstVisibleColumn; + sal_Int32 mnLastVisibleColumn; + sal_Int32 mnFirstVisibleRow; + sal_Int32 mnLastVisibleRow; + +private: + Orientation meOrientation; + ::rtl::Reference<PresenterScrollBar> mpHorizontalScrollBar; + ::rtl::Reference<PresenterScrollBar> mpVerticalScrollBar; + + sal_Int32 GetIndex (const sal_Int32 nRow, const sal_Int32 nColumn) const; + sal_Int32 GetRow (const sal_Int32 nSlideIndex) const; + sal_Int32 GetColumn (const sal_Int32 nSlideIndex) const; +}; + + + + +//==== PresenterSlideSorter::MouseOverManager ================================= + +class PresenterSlideSorter::MouseOverManager + : ::boost::noncopyable +{ +public: + MouseOverManager ( + const Reference<container::XIndexAccess>& rxSlides, + const ::boost::shared_ptr<PresenterTheme>& rpTheme, + const Reference<awt::XWindow>& rxInvalidateTarget, + const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager); + ~MouseOverManager (void); + + void Paint ( + const sal_Int32 nSlideIndex, + const Reference<rendering::XCanvas>& rxCanvas, + const Reference<rendering::XPolyPolygon2D>& rxClip); + + void SetSlide ( + const sal_Int32 nSlideIndex, + const awt::Rectangle& rBox); + +private: + Reference<rendering::XCanvas> mxCanvas; + const Reference<container::XIndexAccess> mxSlides; + SharedBitmapDescriptor mpLeftLabelBitmap; + SharedBitmapDescriptor mpCenterLabelBitmap; + SharedBitmapDescriptor mpRightLabelBitmap; + PresenterTheme::SharedFontDescriptor mpFont; + sal_Int32 mnSlideIndex; + awt::Rectangle maSlideBoundingBox; + OUString msText; + Reference<rendering::XBitmap> mxBitmap; + Reference<awt::XWindow> mxInvalidateTarget; + ::boost::shared_ptr<PresenterPaintManager> mpPaintManager; + + void SetCanvas ( + const Reference<rendering::XCanvas>& rxCanvas); + /** Create a bitmap that shows the given text and is not wider than the + given maximal width. + */ + Reference<rendering::XBitmap> CreateBitmap ( + const OUString& rsText, + const sal_Int32 nMaximalWidth) const; + void Invalidate (void); + geometry::IntegerSize2D CalculateLabelSize ( + const OUString& rsText) const; + OUString GetFittingText (const OUString& rsText, const double nMaximalWidth) const; + void PaintButtonBackground ( + const Reference<rendering::XBitmapCanvas>& rxCanvas, + const geometry::IntegerSize2D& rSize) const; +}; + + + + +//==== PresenterSlideSorter::CurrentSlideFrameRenderer ======================== + +class PresenterSlideSorter::CurrentSlideFrameRenderer +{ +public: + CurrentSlideFrameRenderer ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas); + ~CurrentSlideFrameRenderer (void); + + void PaintCurrentSlideFrame ( + const awt::Rectangle& rSlideBoundingBox, + const Reference<rendering::XCanvas>& rxCanvas, + const geometry::RealRectangle2D& rClipBox); + + /** Enlarge the given rectangle to include the current slide indicator. + */ + awt::Rectangle GetBoundingBox ( + const awt::Rectangle& rSlideBoundingBox); + +private: + SharedBitmapDescriptor mpTopLeft; + SharedBitmapDescriptor mpTop; + SharedBitmapDescriptor mpTopRight; + SharedBitmapDescriptor mpLeft; + SharedBitmapDescriptor mpRight; + SharedBitmapDescriptor mpBottomLeft; + SharedBitmapDescriptor mpBottom; + SharedBitmapDescriptor mpBottomRight; + sal_Int32 mnTopFrameSize; + sal_Int32 mnLeftFrameSize; + sal_Int32 mnRightFrameSize; + sal_Int32 mnBottomFrameSize; + + void PaintBitmapOnce( + const css::uno::Reference<css::rendering::XBitmap>& rxBitmap, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const Reference<rendering::XPolyPolygon2D>& rxClip, + const double nX, + const double nY); + void PaintBitmapTiled( + const css::uno::Reference<css::rendering::XBitmap>& rxBitmap, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const geometry::RealRectangle2D& rClipBox, + const double nX, + const double nY, + const double nWidth, + const double nHeight); +}; + + + + +//===== PresenterSlideSorter ================================================== + +PresenterSlideSorter::PresenterSlideSorter ( + const Reference<uno::XComponentContext>& rxContext, + const Reference<XResourceId>& rxViewId, + const Reference<frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterSlideSorterInterfaceBase(m_aMutex), + mxComponentContext(rxContext), + mxViewId(rxViewId), + mxPane(), + mxCanvas(), + mxWindow(), + mpPresenterController(rpPresenterController), + mxSlideShowController(mpPresenterController->GetSlideShowController()), + mxPreviewCache(), + mbIsPaintPending(true), + mbIsLayoutPending(true), + mpLayout(), + mpHorizontalScrollBar(), + mpVerticalScrollBar(), + mpCloseButton(), + mpMouseOverManager(), + mnSlideIndexMousePressed(-1), + mnCurrentSlideIndex(-1), + mnSeparatorY(0), + maSeparatorColor(0x00ffffff), + maCloseButtonCenter(), + maCurrentSlideFrameBoundingBox(), + mpCurrentSlideFrameRenderer(), + mxPreviewFrame() +{ + if ( ! rxContext.is() + || ! rxViewId.is() + || ! rxController.is() + || rpPresenterController.get()==NULL) + { + throw lang::IllegalArgumentException(); + } + + if ( ! mxSlideShowController.is()) + throw RuntimeException(); + + try + { + // Get pane and window. + Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW); + Reference<XConfigurationController> xCC ( + xCM->getConfigurationController(), UNO_QUERY_THROW); + Reference<lang::XMultiComponentFactory> xFactory ( + mxComponentContext->getServiceManager(), UNO_QUERY_THROW); + + mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW); + mxWindow = mxPane->getWindow(); + + // Add window listener. + mxWindow->addWindowListener(this); + mxWindow->addPaintListener(this); + mxWindow->addMouseListener(this); + mxWindow->addMouseMotionListener(this); + mxWindow->setVisible(sal_True); + + // Remember the current slide. + mnCurrentSlideIndex = mxSlideShowController->getCurrentSlideIndex(); + + // Set the orientation. + const bool bIsVertical (true); + + // Create the scroll bar. + if (bIsVertical) + mpVerticalScrollBar = ::rtl::Reference<PresenterScrollBar>( + new PresenterVerticalScrollBar( + rxContext, + mxWindow, + mpPresenterController->GetPaintManager(), + ::boost::bind(&PresenterSlideSorter::SetVerticalOffset,this,_1))); + else + mpHorizontalScrollBar = ::rtl::Reference<PresenterScrollBar>( + new PresenterHorizontalScrollBar( + rxContext, + mxWindow, + mpPresenterController->GetPaintManager(), + ::boost::bind(&PresenterSlideSorter::SetHorizontalOffset,this,_1))); + mpCloseButton = PresenterButton::Create( + rxContext, + mpPresenterController, + mpPresenterController->GetTheme(), + mxWindow, + mxCanvas, + A2S("SlideSorterCloser")); + + if (mpPresenterController->GetTheme().get() != NULL) + { + PresenterTheme::SharedFontDescriptor pFont ( + mpPresenterController->GetTheme()->GetFont(A2S("ButtonFont"))); + if (pFont.get() != NULL) + maSeparatorColor = pFont->mnColor; + } + + // Create the layout. + mpLayout.reset(new Layout( + Layout::Vertical, + mpHorizontalScrollBar, + mpVerticalScrollBar)); + + // Create the preview cache. + mxPreviewCache = Reference<drawing::XSlidePreviewCache>( + xFactory->createInstanceWithContext( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.PresenterPreviewCache")), + mxComponentContext), + UNO_QUERY_THROW); + Reference<container::XIndexAccess> xSlides (mxSlideShowController, UNO_QUERY); + mxPreviewCache->setDocumentSlides(xSlides, rxController->getModel()); + mxPreviewCache->addPreviewCreationNotifyListener(this); + if (xSlides.is()) + { + mpLayout->mnSlideCount = xSlides->getCount(); + } + + // Create the mouse over manager. + mpMouseOverManager.reset(new MouseOverManager( + Reference<container::XIndexAccess>(mxSlideShowController, UNO_QUERY), + mpPresenterController->GetTheme(), + mxWindow, + mpPresenterController->GetPaintManager())); + + // Listen for changes of the current slide. + Reference<beans::XPropertySet> xControllerProperties (rxController, UNO_QUERY_THROW); + xControllerProperties->addPropertyChangeListener( + OUString(RTL_CONSTASCII_USTRINGPARAM("CurrentPage")), + this); + + // Move the current slide in the center of the window. + const awt::Rectangle aCurrentSlideBBox (mpLayout->GetBoundingBox(mnCurrentSlideIndex)); + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + SetHorizontalOffset(aCurrentSlideBBox.X - aWindowBox.Width/2.0); + } + catch (RuntimeException&) + { + disposing(); + throw; + } +} + + + + +PresenterSlideSorter::~PresenterSlideSorter (void) +{ +} + + + + +void SAL_CALL PresenterSlideSorter::disposing (void) +{ + mxComponentContext = NULL; + mxViewId = NULL; + mxPane = NULL; + + if (mpVerticalScrollBar.is()) + { + Reference<lang::XComponent> xComponent ( + static_cast<XWeak*>(mpVerticalScrollBar.get()), UNO_QUERY); + mpVerticalScrollBar = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + if (mpHorizontalScrollBar.is()) + { + Reference<lang::XComponent> xComponent ( + static_cast<XWeak*>(mpHorizontalScrollBar.get()), UNO_QUERY); + mpHorizontalScrollBar = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + if (mpCloseButton.is()) + { + Reference<lang::XComponent> xComponent ( + static_cast<XWeak*>(mpCloseButton.get()), UNO_QUERY); + mpCloseButton = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + + if (mxCanvas.is()) + { + Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY); + if (xComponent.is()) + xComponent->removeEventListener(static_cast<awt::XWindowListener*>(this)); + mxCanvas = NULL; + } + mpPresenterController = NULL; + mxSlideShowController = NULL; + mpLayout.reset(); + mpMouseOverManager.reset(); + + if (mxPreviewCache.is()) + { + mxPreviewCache->removePreviewCreationNotifyListener(this); + + Reference<XComponent> xComponent (mxPreviewCache, UNO_QUERY); + mxPreviewCache = NULL; + if (xComponent.is()) + xComponent->dispose(); + } + + if (mxWindow.is()) + { + mxWindow->removeWindowListener(this); + mxWindow->removePaintListener(this); + mxWindow->removeMouseListener(this); + mxWindow->removeMouseMotionListener(this); + } +} + + + + +void PresenterSlideSorter::SetActiveState (const bool bIsActive) +{ + (void)bIsActive; +} + + + + +//----- lang::XEventListener -------------------------------------------------- + +void SAL_CALL PresenterSlideSorter::disposing (const lang::EventObject& rEventObject) + throw (RuntimeException) +{ + if (rEventObject.Source == mxWindow) + { + mxWindow = NULL; + dispose(); + } + else if (rEventObject.Source == mxPreviewCache) + { + mxPreviewCache = NULL; + dispose(); + } + else if (rEventObject.Source == mxCanvas) + { + mxCanvas = NULL; + if (mpHorizontalScrollBar.is()) + mpHorizontalScrollBar->SetCanvas(NULL); + mbIsLayoutPending = true; + mbIsPaintPending = true; + + mpPresenterController->GetPaintManager()->Invalidate(mxWindow); + } +} + + + + +//----- XWindowListener ------------------------------------------------------- + +void SAL_CALL PresenterSlideSorter::windowResized (const awt::WindowEvent& rEvent) + throw (uno::RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); + mbIsLayoutPending = true; + mpPresenterController->GetPaintManager()->Invalidate(mxWindow); +} + + + + +void SAL_CALL PresenterSlideSorter::windowMoved (const awt::WindowEvent& rEvent) + throw (uno::RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); +} + + + + +void SAL_CALL PresenterSlideSorter::windowShown (const lang::EventObject& rEvent) + throw (uno::RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); + mbIsLayoutPending = true; + mpPresenterController->GetPaintManager()->Invalidate(mxWindow); +} + + + + +void SAL_CALL PresenterSlideSorter::windowHidden (const lang::EventObject& rEvent) + throw (uno::RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); +} + + + + +//----- XPaintListener -------------------------------------------------------- + +void SAL_CALL PresenterSlideSorter::windowPaint (const css::awt::PaintEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + + // Deactivated views must not be painted. + if ( ! mbIsPresenterViewActive) + return; + + Paint(rEvent.UpdateRect); + + Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); + if (xSpriteCanvas.is()) + xSpriteCanvas->updateScreen(sal_False); +} + + + + +//----- XMouseListener -------------------------------------------------------- + +void SAL_CALL PresenterSlideSorter::mousePressed (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + const geometry::RealPoint2D aPosition (rEvent.X, rEvent.Y); + mnSlideIndexMousePressed = mpLayout->GetSlideIndexForPosition(aPosition); +} + + + + +void SAL_CALL PresenterSlideSorter::mouseReleased (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + const geometry::RealPoint2D aPosition (rEvent.X, rEvent.Y); + const sal_Int32 nSlideIndex (mpLayout->GetSlideIndexForPosition(aPosition)); + + if (nSlideIndex == mnSlideIndexMousePressed && mnSlideIndexMousePressed >= 0) + { + switch (rEvent.ClickCount) + { + case 1: + default: + GotoSlide(nSlideIndex); + break; + + case 2: + OSL_ASSERT(mpPresenterController.get()!=NULL); + OSL_ASSERT(mpPresenterController->GetWindowManager().get()!=NULL); + mpPresenterController->GetWindowManager()->SetSlideSorterState(false); + GotoSlide(nSlideIndex); + break; + } + } +} + + + + +void SAL_CALL PresenterSlideSorter::mouseEntered (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterSlideSorter::mouseExited (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + (void)rEvent; + mnSlideIndexMousePressed = -1; + if (mpMouseOverManager.get() != NULL) + mpMouseOverManager->SetSlide(mnSlideIndexMousePressed, awt::Rectangle(0,0,0,0)); +} + + + + +//----- XMouseMotionListener -------------------------------------------------- + +void SAL_CALL PresenterSlideSorter::mouseMoved (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + if (mpMouseOverManager.get() != NULL) + { + const geometry::RealPoint2D aPosition (rEvent.X, rEvent.Y); + sal_Int32 nSlideIndex (mpLayout->GetSlideIndexForPosition(aPosition)); + + if (nSlideIndex < 0) + mnSlideIndexMousePressed = -1; + + if (nSlideIndex < 0) + { + mpMouseOverManager->SetSlide(nSlideIndex, awt::Rectangle(0,0,0,0)); + } + else + { + mpMouseOverManager->SetSlide( + nSlideIndex, + mpLayout->GetBoundingBox(nSlideIndex)); + } + } +} + + + + +void SAL_CALL PresenterSlideSorter::mouseDragged (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +//----- XResourceId ----------------------------------------------------------- + +Reference<XResourceId> SAL_CALL PresenterSlideSorter::getResourceId (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + return mxViewId; +} + + + + +sal_Bool SAL_CALL PresenterSlideSorter::isAnchorOnly (void) + throw (RuntimeException) +{ + return false; +} + + + + +//----- XPropertyChangeListener ----------------------------------------------- + +void SAL_CALL PresenterSlideSorter::propertyChange ( + const css::beans::PropertyChangeEvent& rEvent) + throw(css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +//----- XSlidePreviewCacheListener -------------------------------------------- + +void SAL_CALL PresenterSlideSorter::notifyPreviewCreation ( + sal_Int32 nSlideIndex) + throw(css::uno::RuntimeException) +{ + OSL_ASSERT(mpLayout.get()!=NULL); + + awt::Rectangle aBBox (mpLayout->GetBoundingBox(nSlideIndex)); + mpPresenterController->GetPaintManager()->Invalidate(mxWindow, aBBox, true); +} + + + + +//----- XDrawView ------------------------------------------------------------- + +void SAL_CALL PresenterSlideSorter::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide) + throw (RuntimeException) +{ + (void)rxSlide; + + ThrowIfDisposed(); + ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex()); + + if (mxSlideShowController.is()) + { + const sal_Int32 nNewCurrentSlideIndex (mxSlideShowController->getCurrentSlideIndex()); + if (nNewCurrentSlideIndex != mnCurrentSlideIndex) + { + mnCurrentSlideIndex = nNewCurrentSlideIndex; + + // Request a repaint of the previous current slide to hide its + // current slide indicator. + mpPresenterController->GetPaintManager()->Invalidate( + mxWindow, + maCurrentSlideFrameBoundingBox); + + // Request a repaint of the new current slide to show its + // current slide indicator. + maCurrentSlideFrameBoundingBox = mpCurrentSlideFrameRenderer->GetBoundingBox( + mpLayout->GetBoundingBox(mnCurrentSlideIndex)); + mpPresenterController->GetPaintManager()->Invalidate( + mxWindow, + maCurrentSlideFrameBoundingBox); + } + } +} + + + + +Reference<drawing::XDrawPage> SAL_CALL PresenterSlideSorter::getCurrentPage (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + return NULL; +} + + + + +//----------------------------------------------------------------------------- + +void PresenterSlideSorter::UpdateLayout (void) +{ + if ( ! mxWindow.is()) + return; + + mbIsLayoutPending = false; + mbIsPaintPending = true; + + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + awt::Rectangle aCenterBox (aWindowBox); + sal_Int32 nLeftBorderWidth (aWindowBox.X); + + // Get border width. + PresenterPaneContainer::SharedPaneDescriptor pPane ( + mpPresenterController->GetPaneContainer()->FindViewURL( + mxViewId->getResourceURL())); + do + { + if (pPane.get() == NULL) + break; + if ( ! pPane->mxPane.is()) + break; + + Reference<drawing::framework::XPaneBorderPainter> xBorderPainter ( + pPane->mxPane->GetPaneBorderPainter()); + if ( ! xBorderPainter.is()) + break; + aCenterBox = xBorderPainter->addBorder ( + mxViewId->getAnchor()->getResourceURL(), + awt::Rectangle(0, 0, aWindowBox.Width, aWindowBox.Height), + drawing::framework::BorderType_INNER_BORDER); + } + while(false); + + // Place vertical separator. + mnSeparatorY = aWindowBox.Height - mpCloseButton->GetSize().Height - gnVerticalButtonPadding; + + PlaceCloseButton(pPane, aWindowBox, nLeftBorderWidth); + + geometry::RealRectangle2D aUpperBox( + gnHorizontalBorder, + gnVerticalBorder, + aWindowBox.Width - 2*gnHorizontalBorder, + mnSeparatorY - gnVerticalGap); + + // Determine whether the scroll bar has to be displayed. + aUpperBox = PlaceScrollBars(aUpperBox); + + mpLayout->Update(aUpperBox, GetSlideAspectRatio()); + mpLayout->SetupVisibleArea(); + mpLayout->UpdateScrollBars(); + + // Tell the preview cache about some of the values. + mxPreviewCache->setPreviewSize(mpLayout->maPreviewSize); + mxPreviewCache->setVisibleRange( + mpLayout->GetFirstVisibleSlideIndex(), + mpLayout->GetLastVisibleSlideIndex()); + + // Clear the frame polygon so that it is re-created on the next paint. + mxPreviewFrame = NULL; +} + + + + +geometry::RealRectangle2D PresenterSlideSorter::PlaceScrollBars ( + const geometry::RealRectangle2D& rUpperBox) +{ + mpLayout->Update(rUpperBox, GetSlideAspectRatio()); + bool bIsScrollBarNeeded (false); + Reference<container::XIndexAccess> xSlides (mxSlideShowController, UNO_QUERY_THROW); + if (xSlides.is()) + bIsScrollBarNeeded = mpLayout->IsScrollBarNeeded(xSlides->getCount()); + + if (mpLayout->GetOrientation() == Layout::Vertical) + { + if (mpVerticalScrollBar.get() != NULL) + { + if (bIsScrollBarNeeded) + { + // Place vertical scroll bar at right border. + mpVerticalScrollBar->SetPosSize(geometry::RealRectangle2D( + rUpperBox.X2 - mpVerticalScrollBar->GetSize(), + rUpperBox.Y1, + rUpperBox.X2, + rUpperBox.Y2)); + mpVerticalScrollBar->SetVisible(true); + + // Reduce area covered by the scroll bar from the available + // space. + return geometry::RealRectangle2D( + rUpperBox.X1, + rUpperBox.Y1, + rUpperBox.X2 - mpVerticalScrollBar->GetSize() - gnHorizontalGap, + rUpperBox.Y2); + } + else + mpVerticalScrollBar->SetVisible(false); + } + } + else + { + if (mpHorizontalScrollBar.get() != NULL) + { + if (bIsScrollBarNeeded) + { + // Place horixontal scroll bar at the bottom. + mpHorizontalScrollBar->SetPosSize(geometry::RealRectangle2D( + rUpperBox.X1, + rUpperBox.Y2 - mpHorizontalScrollBar->GetSize(), + rUpperBox.X2, + rUpperBox.Y2)); + mpHorizontalScrollBar->SetVisible(true); + + // Reduce area covered by the scroll bar from the available + // space. + return geometry::RealRectangle2D( + rUpperBox.X1, + rUpperBox.Y1, + rUpperBox.X2, + rUpperBox.Y2 - mpHorizontalScrollBar->GetSize() - gnVerticalGap); + } + else + mpHorizontalScrollBar->SetVisible(false); + } + } + + return rUpperBox; +} + + + + +void PresenterSlideSorter::PlaceCloseButton ( + const PresenterPaneContainer::SharedPaneDescriptor& rpPane, + const awt::Rectangle& rCenterBox, + const sal_Int32 nLeftBorderWidth) +{ + // Place button. When the callout is near the center then the button is + // centered over the callout. Otherwise it is centered with respect to + // the whole window. + sal_Int32 nCloseButtonCenter (rCenterBox.Width/2); + if (rpPane.get() != NULL && rpPane->mxPane.is()) + { + const sal_Int32 nCalloutCenter (rpPane->mxPane->GetCalloutAnchor().X - nLeftBorderWidth); + const sal_Int32 nDistanceFromWindowCenter (abs(nCalloutCenter - rCenterBox.Width/2)); + const sal_Int32 nButtonWidth (mpCloseButton->GetSize().Width); + const static sal_Int32 nMaxDistanceForCalloutCentering (nButtonWidth * 2); + if (nDistanceFromWindowCenter < nMaxDistanceForCalloutCentering) + { + if (nCalloutCenter < nButtonWidth/2) + nCloseButtonCenter = nButtonWidth/2; + else if (nCalloutCenter > rCenterBox.Width-nButtonWidth/2) + nCloseButtonCenter = rCenterBox.Width-nButtonWidth/2; + else + nCloseButtonCenter = nCalloutCenter; + } + } + mpCloseButton->SetCenter(geometry::RealPoint2D( + nCloseButtonCenter, + rCenterBox.Height - mpCloseButton->GetSize().Height/ 2)); +} + + + + +void PresenterSlideSorter::ClearBackground ( + const Reference<rendering::XCanvas>& rxCanvas, + const awt::Rectangle& rUpdateBox) +{ + OSL_ASSERT(rxCanvas.is()); + + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + mpPresenterController->GetCanvasHelper()->Paint( + mpPresenterController->GetViewBackground(mxViewId->getResourceURL()), + rxCanvas, + rUpdateBox, + awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height), + awt::Rectangle()); +} + + + + +double PresenterSlideSorter::GetSlideAspectRatio (void) const +{ + double nSlideAspectRatio (28.0/21.0); + + try + { + Reference<container::XIndexAccess> xSlides(mxSlideShowController, UNO_QUERY_THROW); + if (mxSlideShowController.is() && xSlides->getCount()>0) + { + Reference<beans::XPropertySet> xProperties(xSlides->getByIndex(0),UNO_QUERY_THROW); + sal_Int32 nWidth (28000); + sal_Int32 nHeight (21000); + if ((xProperties->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Width"))) >>= nWidth) + && (xProperties->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Height"))) >>= nHeight) + && nHeight > 0) + { + nSlideAspectRatio = double(nWidth) / double(nHeight); + } + } + } + catch (RuntimeException&) + { + OSL_ASSERT(false); + } + + return nSlideAspectRatio; +} + + + + +Reference<rendering::XBitmap> PresenterSlideSorter::GetPreview (const sal_Int32 nSlideIndex) +{ + if (nSlideIndex < 0 || nSlideIndex>=mpLayout->mnSlideCount) + return NULL; + else if (mxPane.is()) + return mxPreviewCache->getSlidePreview(nSlideIndex, mxPane->getCanvas()); + else + return NULL; +} + + + + +void PresenterSlideSorter::PaintPreview ( + const Reference<rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rUpdateBox, + const sal_Int32 nSlideIndex) +{ + OSL_ASSERT(rxCanvas.is()); + + geometry::IntegerSize2D aSize (mpLayout->maPreviewSize); + + if (PresenterGeometryHelper::AreRectanglesDisjoint( + rUpdateBox, + mpLayout->GetBoundingBox(nSlideIndex))) + { + return; + } + + Reference<rendering::XBitmap> xPreview (GetPreview(nSlideIndex)); + + const geometry::RealPoint2D aTopLeft ( + mpLayout->GetWindowPosition( + mpLayout->GetPoint(nSlideIndex, -1, -1))); + + // Create clip rectangle as intersection of the current update area and + // the bounding box of all previews. + geometry::RealRectangle2D aBoundingBox (mpLayout->maBoundingBox); + aBoundingBox.Y2 += 1; + const geometry::RealRectangle2D aClipBox ( + PresenterGeometryHelper::Intersection( + PresenterGeometryHelper::ConvertRectangle(rUpdateBox), + aBoundingBox)); + Reference<rendering::XPolyPolygon2D> xClip ( + PresenterGeometryHelper::CreatePolygon(aClipBox, rxCanvas->getDevice())); + + const rendering::ViewState aViewState (geometry::AffineMatrix2D(1,0,0, 0,1,0), xClip); + + + rendering::RenderState aRenderState ( + geometry::AffineMatrix2D( + 1, 0, aTopLeft.X, + 0, 1, aTopLeft.Y), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + + + // Emphasize the current slide. + if (nSlideIndex == mnCurrentSlideIndex) + { + if (mpCurrentSlideFrameRenderer.get() != NULL) + { + const awt::Rectangle aSlideBoundingBox( + sal::static_int_cast<sal_Int32>(0.5 + aTopLeft.X), + sal::static_int_cast<sal_Int32>(0.5 + aTopLeft.Y), + aSize.Width, + aSize.Height); + maCurrentSlideFrameBoundingBox + = mpCurrentSlideFrameRenderer->GetBoundingBox(aSlideBoundingBox); + mpCurrentSlideFrameRenderer->PaintCurrentSlideFrame ( + aSlideBoundingBox, + mxCanvas, + aClipBox); + } + } + + // Paint the preview. + if (xPreview.is()) + { + aSize = xPreview->getSize(); + if (aSize.Width > 0 && aSize.Height > 0) + { + rxCanvas->drawBitmap(xPreview, aViewState, aRenderState); + } + } + + // Create a polygon that is used to paint a frame around previews. Its + // coordinates are chosen in the local coordinate system of a preview. + if ( ! mxPreviewFrame.is()) + mxPreviewFrame = PresenterGeometryHelper::CreatePolygon( + awt::Rectangle(-1, -1, aSize.Width+2, aSize.Height+2), + rxCanvas->getDevice()); + + // Paint a border around the preview. + if (mxPreviewFrame.is()) + { + const geometry::RealRectangle2D aBox (0, 0, aSize.Width, aSize.Height); + const util::Color aFrameColor (0x00000000); + PresenterCanvasHelper::SetDeviceColor(aRenderState, aFrameColor); + rxCanvas->drawPolyPolygon(mxPreviewFrame, aViewState, aRenderState); + } + + // Paint mouse over effect. + mpMouseOverManager->Paint(nSlideIndex, mxCanvas, xClip); +} + + + + +void PresenterSlideSorter::Paint (const awt::Rectangle& rUpdateBox) +{ + const bool bCanvasChanged ( ! mxCanvas.is()); + if ( ! ProvideCanvas()) + return; + + if (mpLayout->mnRowCount<=0 || mpLayout->mnColumnCount<=0) + { + OSL_ASSERT(mpLayout->mnRowCount>0 || mpLayout->mnColumnCount>0); + return; + } + + mbIsPaintPending = false; + + ClearBackground(mxCanvas, rUpdateBox); + + // Give the canvas to the controls. + if (bCanvasChanged) + { + if (mpHorizontalScrollBar.is()) + mpHorizontalScrollBar->SetCanvas(mxCanvas); + if (mpVerticalScrollBar.is()) + mpVerticalScrollBar->SetCanvas(mxCanvas); + if (mpCloseButton.is()) + mpCloseButton->SetCanvas(mxCanvas, mxWindow); + } + + // Now that the controls have a canvas we can do the layouting. + if (mbIsLayoutPending) + UpdateLayout(); + + // Paint the horizontal separator. + rendering::RenderState aRenderState (geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, Sequence<double>(4), rendering::CompositeOperation::SOURCE); + PresenterCanvasHelper::SetDeviceColor(aRenderState, maSeparatorColor); + mxCanvas->drawLine( + geometry::RealPoint2D(0, mnSeparatorY), + geometry::RealPoint2D(mxWindow->getPosSize().Width, mnSeparatorY), + rendering::ViewState(geometry::AffineMatrix2D(1,0,0, 0,1,0), NULL), + aRenderState); + + // Paint the slides. + if ( ! PresenterGeometryHelper::AreRectanglesDisjoint( + rUpdateBox, + PresenterGeometryHelper::ConvertRectangle(mpLayout->maBoundingBox))) + { + mpLayout->ForAllVisibleSlides( + ::boost::bind(&PresenterSlideSorter::PaintPreview, this, mxCanvas, rUpdateBox, _1)); + } + + Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); + if (xSpriteCanvas.is()) + xSpriteCanvas->updateScreen(sal_False); +} + + + + +void PresenterSlideSorter::SetHorizontalOffset (const double nXOffset) +{ + if (mpLayout->SetHorizontalOffset(nXOffset)) + { + mxPreviewCache->setVisibleRange( + mpLayout->GetFirstVisibleSlideIndex(), + mpLayout->GetLastVisibleSlideIndex()); + + mpPresenterController->GetPaintManager()->Invalidate(mxWindow); + } +} + + + + +void PresenterSlideSorter::SetVerticalOffset (const double nYOffset) +{ + if (mpLayout->SetVerticalOffset(nYOffset)) + { + mxPreviewCache->setVisibleRange( + mpLayout->GetFirstVisibleSlideIndex(), + mpLayout->GetLastVisibleSlideIndex()); + + mpPresenterController->GetPaintManager()->Invalidate(mxWindow); + } +} + + + + +void PresenterSlideSorter::GotoSlide (const sal_Int32 nSlideIndex) +{ + mxSlideShowController->gotoSlideIndex(nSlideIndex); + mpPresenterController->HideSlideSorter(); +} + + + + +bool PresenterSlideSorter::ProvideCanvas (void) +{ + if ( ! mxCanvas.is()) + { + if (mxPane.is()) + mxCanvas = mxPane->getCanvas(); + + // Register as event listener so that we are informed when the + // canvas is disposed (and we have to fetch another one). + Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY); + if (xComponent.is()) + xComponent->addEventListener(static_cast<awt::XWindowListener*>(this)); + + // Tell the scrollbar about the canvas. + if (mpHorizontalScrollBar.is()) + mpHorizontalScrollBar->SetCanvas(mxCanvas); + + mpCurrentSlideFrameRenderer.reset( + new CurrentSlideFrameRenderer(mxComponentContext, mxCanvas)); + } + return mxCanvas.is(); +} + + + + +void PresenterSlideSorter::ThrowIfDisposed (void) + throw (lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterSlideSorter has been already disposed")), + const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + } +} + + + + +//===== PresenterSlideSorter::Layout ========================================== + +PresenterSlideSorter::Layout::Layout ( + const Orientation eOrientation, + const ::rtl::Reference<PresenterScrollBar>& rpHorizontalScrollBar, + const ::rtl::Reference<PresenterScrollBar>& rpVerticalScrollBar) + : maBoundingBox(), + maPreviewSize(), + mnHorizontalOffset(0), + mnVerticalOffset(0), + mnHorizontalGap(0), + mnVerticalGap(0), + mnHorizontalBorder(0), + mnVerticalBorder(0), + mnRowCount(1), + mnColumnCount(1), + mnSlideCount(0), + mnSlideIndexAtMouse(-1), + mnFirstVisibleColumn(-1), + mnLastVisibleColumn(-1), + mnFirstVisibleRow(-1), + mnLastVisibleRow(-1), + meOrientation(eOrientation), + mpHorizontalScrollBar(rpHorizontalScrollBar), + mpVerticalScrollBar(rpVerticalScrollBar) +{ +} + + + + +void PresenterSlideSorter::Layout::Update ( + const geometry::RealRectangle2D& rBoundingBox, + const double nSlideAspectRatio) +{ + maBoundingBox = rBoundingBox; + + mnHorizontalBorder = gnHorizontalBorder; + mnVerticalBorder = gnVerticalBorder; + + const double nWidth (rBoundingBox.X2 - rBoundingBox.X1 - 2*mnHorizontalBorder); + const double nHeight (rBoundingBox.Y2 - rBoundingBox.Y1 - 2*mnVerticalBorder); + if (nWidth<=0 || nHeight<=0) + return; + + double nPreviewWidth; + + // Determine column count, preview width, and horizontal gap (borders + // are half the gap). Try to use the preferred values. Try more to + // stay in the valid intervalls. This last constraint may be not + // fullfilled in some cases. + const double nElementWidth = nWidth / gnPreferredColumnCount; + if (nElementWidth < gnMinimalPreviewWidth + gnMinimalHorizontalPreviewGap) + { + // The preferred column count is too large. + // Can we use the preferred preview width? + if (nWidth - gnMinimalHorizontalPreviewGap >= gnPreferredPreviewWidth) + { + // Yes. + nPreviewWidth = gnPreferredPreviewWidth; + mnColumnCount = floor((nWidth+gnPreferredHorizontalPreviewGap) + / (nPreviewWidth+gnPreferredHorizontalPreviewGap)); + mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount); + } + else + { + // No. Set the column count to 1 and adapt preview width and + // gap. + mnColumnCount = 1; + mnHorizontalGap = floor(gnMinimalHorizontalPreviewGap); + if (nWidth - gnMinimalHorizontalPreviewGap >= gnPreferredPreviewWidth) + nPreviewWidth = nWidth - gnMinimalHorizontalPreviewGap; + else + nPreviewWidth = ::std::max(gnMinimalPreviewWidth, nWidth-mnHorizontalGap); + } + } + else if (nElementWidth > gnMaximalPreviewWidth + gnMaximalHorizontalPreviewGap) + { + // The preferred column count is too small. + nPreviewWidth = gnPreferredPreviewWidth; + mnColumnCount = floor((nWidth+gnPreferredHorizontalPreviewGap) + / (nPreviewWidth+gnPreferredHorizontalPreviewGap)); + mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount); + } + else + { + // The preferred column count is possible. Determine gap and + // preview width. + mnColumnCount = gnPreferredColumnCount; + if (nElementWidth - gnPreferredPreviewWidth < gnMinimalHorizontalPreviewGap) + { + // Use the minimal gap and adapt the preview width. + mnHorizontalGap = floor(gnMinimalHorizontalPreviewGap); + nPreviewWidth = (nWidth - mnColumnCount*mnHorizontalGap) / mnColumnCount; + } + else if (nElementWidth - gnPreferredPreviewWidth <= gnMaximalHorizontalPreviewGap) + { + // Use the maximal gap and adapt the preview width. + mnHorizontalGap = round(gnMaximalHorizontalPreviewGap); + nPreviewWidth = (nWidth - mnColumnCount*mnHorizontalGap) / mnColumnCount; + } + else + { + // Use the preferred preview width and adapt the gap. + nPreviewWidth = gnPreferredPreviewWidth; + mnHorizontalGap = round((nWidth - mnColumnCount*nPreviewWidth) / mnColumnCount); + } + } + + // Now determine the row count, preview height, and vertical gap. + const double nPreviewHeight = nPreviewWidth / nSlideAspectRatio; + mnRowCount = ::std::max( + sal_Int32(1), + sal_Int32(ceil((nHeight+gnPreferredVerticalPreviewGap) + / (nPreviewHeight + gnPreferredVerticalPreviewGap)))); + mnVerticalGap = round(gnPreferredVerticalPreviewGap); + + maPreviewSize = geometry::IntegerSize2D(floor(nPreviewWidth), floor(nPreviewHeight)); + + // Reset the offset. + if (meOrientation == Horizontal) + { + mnVerticalOffset = round(-(nHeight + - mnRowCount*maPreviewSize.Height - (mnRowCount-1)*mnVerticalGap) + / 2); + mnHorizontalOffset = 0; + } + else + { + mnVerticalOffset = 0; + mnHorizontalOffset = round(-(nWidth + - mnColumnCount*maPreviewSize.Width + - (mnColumnCount-1)*mnHorizontalGap) + / 2); + } +} + + + + +void PresenterSlideSorter::Layout::SetupVisibleArea (void) +{ + geometry::RealPoint2D aPoint (GetLocalPosition( + geometry::RealPoint2D(maBoundingBox.X1, maBoundingBox.Y1))); + if (meOrientation == Horizontal) + { + mnFirstVisibleColumn = ::std::max(sal_Int32(0), GetColumn(aPoint)); + mnFirstVisibleRow = 0; + } + else + { + mnFirstVisibleColumn = 0; + mnFirstVisibleRow = ::std::max(sal_Int32(0), GetRow(aPoint)); + } + + aPoint = GetLocalPosition(geometry::RealPoint2D( maBoundingBox.X2, maBoundingBox.Y2)); + if (meOrientation == Horizontal) + { + mnLastVisibleColumn = GetColumn(aPoint, true); + mnLastVisibleRow = mnRowCount - 1; + } + else + { + mnLastVisibleColumn = mnColumnCount - 1; + mnLastVisibleRow = GetRow(aPoint, true); + } +} + + + + +bool PresenterSlideSorter::Layout::IsScrollBarNeeded (const sal_Int32 nSlideCount) +{ + geometry::RealPoint2D aBottomRight; + if (GetOrientation() == Layout::Vertical) + aBottomRight = GetPoint( + mnColumnCount * (GetRow(nSlideCount)+1) - 1, +1, +1); + else + aBottomRight = GetPoint( + mnRowCount * (GetColumn(nSlideCount)+1) - 1, +1, +1); + return aBottomRight.X > maBoundingBox.X2-maBoundingBox.X1 + || aBottomRight.Y > maBoundingBox.Y2-maBoundingBox.Y1; +} + + + + +geometry::RealPoint2D PresenterSlideSorter::Layout::GetLocalPosition( + const geometry::RealPoint2D& rWindowPoint) const +{ + return css::geometry::RealPoint2D( + rWindowPoint.X - maBoundingBox.X1 + mnHorizontalOffset, + rWindowPoint.Y - maBoundingBox.Y1 + mnVerticalOffset); +} + + + + +geometry::RealPoint2D PresenterSlideSorter::Layout::GetWindowPosition( + const geometry::RealPoint2D& rLocalPoint) const +{ + return css::geometry::RealPoint2D( + rLocalPoint.X - mnHorizontalOffset + maBoundingBox.X1, + rLocalPoint.Y - mnVerticalOffset + maBoundingBox.Y1); +} + + + + +sal_Int32 PresenterSlideSorter::Layout::GetColumn ( + const css::geometry::RealPoint2D& rLocalPoint, + const bool bReturnInvalidValue) const +{ + const sal_Int32 nColumn(floor( + (rLocalPoint.X + mnHorizontalGap/2.0) / (maPreviewSize.Width+mnHorizontalGap))); + if (bReturnInvalidValue + || (nColumn>=mnFirstVisibleColumn && nColumn<=mnLastVisibleColumn)) + { + return nColumn; + } + else + return -1; +} + + + + +sal_Int32 PresenterSlideSorter::Layout::GetRow ( + const css::geometry::RealPoint2D& rLocalPoint, + const bool bReturnInvalidValue) const +{ + const sal_Int32 nRow (floor( + (rLocalPoint.Y + mnVerticalGap/2.0) / (maPreviewSize.Height+mnVerticalGap))); + if (bReturnInvalidValue + || (nRow>=mnFirstVisibleRow && nRow<=mnLastVisibleRow)) + { + return nRow; + } + else + return -1; +} + + + + +sal_Int32 PresenterSlideSorter::Layout::GetSlideIndexForPosition ( + const css::geometry::RealPoint2D& rWindowPoint) const +{ + if ( ! PresenterGeometryHelper::IsInside(maBoundingBox, rWindowPoint)) + return -1; + + const css::geometry::RealPoint2D aLocalPosition (GetLocalPosition(rWindowPoint)); + const sal_Int32 nColumn (GetColumn(aLocalPosition)); + const sal_Int32 nRow (GetRow(aLocalPosition)); + + if (nColumn < 0 || nRow < 0) + return -1; + else + { + sal_Int32 nIndex (GetIndex(nRow, nColumn)); + if (nIndex >= mnSlideCount) + return -1; + else + return nIndex; + } +} + + + + +geometry::RealPoint2D PresenterSlideSorter::Layout::GetPoint ( + const sal_Int32 nSlideIndex, + const sal_Int32 nRelativeHorizontalPosition, + const sal_Int32 nRelativeVerticalPosition) const +{ + sal_Int32 nColumn (GetColumn(nSlideIndex)); + sal_Int32 nRow (GetRow(nSlideIndex)); + + geometry::RealPoint2D aPosition ( + mnHorizontalBorder + nColumn*(maPreviewSize.Width+mnHorizontalGap), + mnVerticalBorder + nRow*(maPreviewSize.Height+mnVerticalGap)); + + if (nRelativeHorizontalPosition >= 0) + { + if (nRelativeHorizontalPosition > 0) + aPosition.X += maPreviewSize.Width; + else + aPosition.X += maPreviewSize.Width / 2.0; + } + if (nRelativeVerticalPosition >= 0) + { + if (nRelativeVerticalPosition > 0) + aPosition.Y += maPreviewSize.Height; + else + aPosition.Y += maPreviewSize.Height / 2.0; + } + + return aPosition; +} + + + + +awt::Rectangle PresenterSlideSorter::Layout::GetBoundingBox (const sal_Int32 nSlideIndex) const +{ + const geometry::RealPoint2D aWindowPosition(GetWindowPosition(GetPoint(nSlideIndex, -1, -1))); + return PresenterGeometryHelper::ConvertRectangle( + geometry::RealRectangle2D( + aWindowPosition.X, + aWindowPosition.Y, + aWindowPosition.X + maPreviewSize.Width, + aWindowPosition.Y + maPreviewSize.Height)); +} + + + + +void PresenterSlideSorter::Layout::ForAllVisibleSlides (const ::boost::function<void(sal_Int32)>& rAction) +{ + for (sal_Int32 nRow=mnFirstVisibleRow; nRow<=mnLastVisibleRow; ++nRow) + { + for (sal_Int32 nColumn=mnFirstVisibleColumn; nColumn<=mnLastVisibleColumn; ++nColumn) + { + const sal_Int32 nSlideIndex (GetIndex(nRow, nColumn)); + if (nSlideIndex >= mnSlideCount) + return; + rAction(nSlideIndex); + } + } +} + + + + +sal_Int32 PresenterSlideSorter::Layout::GetFirstVisibleSlideIndex (void) const +{ + return GetIndex(mnFirstVisibleRow, mnFirstVisibleColumn); +} + + + + +sal_Int32 PresenterSlideSorter::Layout::GetLastVisibleSlideIndex (void) const +{ + return ::std::min( + GetIndex(mnLastVisibleRow, mnLastVisibleColumn), + mnSlideCount); +} + + + + +bool PresenterSlideSorter::Layout::SetHorizontalOffset (const double nOffset) +{ + if (mnHorizontalOffset != nOffset) + { + mnHorizontalOffset = round(nOffset); + SetupVisibleArea(); + UpdateScrollBars(); + return true; + } + else + return false; +} + + + + +bool PresenterSlideSorter::Layout::SetVerticalOffset (const double nOffset) +{ + if (mnVerticalOffset != nOffset) + { + mnVerticalOffset = round(nOffset); + SetupVisibleArea(); + UpdateScrollBars(); + return true; + } + else + return false; +} + + + + +PresenterSlideSorter::Layout::Orientation + PresenterSlideSorter::Layout::GetOrientation (void) const +{ + return meOrientation; +} + + + + +void PresenterSlideSorter::Layout::UpdateScrollBars (void) +{ + sal_Int32 nTotalColumnCount (0); + sal_Int32 nTotalRowCount (0); + if (meOrientation == Horizontal) + { + nTotalColumnCount = sal_Int32(ceil(double(mnSlideCount) / double(mnRowCount))); + nTotalRowCount = mnRowCount; + } + else + { + nTotalColumnCount = mnColumnCount; + nTotalRowCount = sal_Int32(ceil(double(mnSlideCount) / double(mnColumnCount))); + } + + if (mpHorizontalScrollBar.get() != NULL) + { + mpHorizontalScrollBar->SetTotalSize( + nTotalColumnCount * maPreviewSize.Width + + (nTotalColumnCount-1) * mnHorizontalGap + + 2*mnHorizontalBorder); + mpHorizontalScrollBar->SetThumbPosition(mnHorizontalOffset, false); + mpHorizontalScrollBar->SetThumbSize(maBoundingBox.X2 - maBoundingBox.X1 + 1); + mpHorizontalScrollBar->SetLineHeight(maPreviewSize.Width); + } + if (mpVerticalScrollBar.get() != NULL) + { + mpVerticalScrollBar->SetTotalSize( + nTotalRowCount * maPreviewSize.Height + + (nTotalRowCount-1) * mnVerticalGap + + 2*mnVerticalGap); + mpVerticalScrollBar->SetThumbPosition(mnVerticalOffset, false); + mpVerticalScrollBar->SetThumbSize(maBoundingBox.Y2 - maBoundingBox.Y1 + 1); + mpVerticalScrollBar->SetLineHeight(maPreviewSize.Height); + } + + + + // No place yet for the vertical scroll bar. +} + + + + +sal_Int32 PresenterSlideSorter::Layout::GetIndex ( + const sal_Int32 nRow, + const sal_Int32 nColumn) const +{ + if (meOrientation == Horizontal) + return nColumn * mnRowCount + nRow; + else + return nRow * mnColumnCount + nColumn; +} + + + + +sal_Int32 PresenterSlideSorter::Layout::GetRow (const sal_Int32 nSlideIndex) const +{ + if (meOrientation == Horizontal) + return nSlideIndex % mnRowCount; + else + return nSlideIndex / mnColumnCount; +} + + + + +sal_Int32 PresenterSlideSorter::Layout::GetColumn (const sal_Int32 nSlideIndex) const +{ + if (meOrientation == Horizontal) + return nSlideIndex / mnRowCount; + else + return nSlideIndex % mnColumnCount; +} + + + + +//===== PresenterSlideSorter::MouseOverManager ================================ + +PresenterSlideSorter::MouseOverManager::MouseOverManager ( + const Reference<container::XIndexAccess>& rxSlides, + const ::boost::shared_ptr<PresenterTheme>& rpTheme, + const Reference<awt::XWindow>& rxInvalidateTarget, + const ::boost::shared_ptr<PresenterPaintManager>& rpPaintManager) + : mxCanvas(), + mxSlides(rxSlides), + mpLeftLabelBitmap(), + mpCenterLabelBitmap(), + mpRightLabelBitmap(), + mpFont(), + mnSlideIndex(-1), + maSlideBoundingBox(), + mxInvalidateTarget(rxInvalidateTarget), + mpPaintManager(rpPaintManager) +{ + if (rpTheme.get()!=NULL) + { + ::boost::shared_ptr<PresenterBitmapContainer> pBitmaps (rpTheme->GetBitmapContainer()); + if (pBitmaps.get() != NULL) + { + mpLeftLabelBitmap = pBitmaps->GetBitmap(A2S("LabelLeft")); + mpCenterLabelBitmap = pBitmaps->GetBitmap(A2S("LabelCenter")); + mpRightLabelBitmap = pBitmaps->GetBitmap(A2S("LabelRight")); + } + + mpFont = rpTheme->GetFont(A2S("SlideSorterLabelFont")); + } +} + + + + +PresenterSlideSorter::MouseOverManager::~MouseOverManager (void) +{ +} + + + + +void PresenterSlideSorter::MouseOverManager::Paint ( + const sal_Int32 nSlideIndex, + const Reference<rendering::XCanvas>& rxCanvas, + const Reference<rendering::XPolyPolygon2D>& rxClip) +{ + if (nSlideIndex != mnSlideIndex) + return; + + if (mxCanvas != rxCanvas) + SetCanvas(rxCanvas); + if (rxCanvas != NULL) + { + if ( ! mxBitmap.is()) + mxBitmap = CreateBitmap(msText, maSlideBoundingBox.Width); + if (mxBitmap.is()) + { + geometry::IntegerSize2D aSize (mxBitmap->getSize()); + const double nXOffset (maSlideBoundingBox.X + + (maSlideBoundingBox.Width - aSize.Width) / 2.0); + const double nYOffset (maSlideBoundingBox.Y + + (maSlideBoundingBox.Height - aSize.Height) / 2.0); + rxCanvas->drawBitmap( + mxBitmap, + rendering::ViewState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + rxClip), + rendering::RenderState( + geometry::AffineMatrix2D(1,0,nXOffset, 0,1,nYOffset), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE)); + } + } +} + + + + +void PresenterSlideSorter::MouseOverManager::SetCanvas ( + const Reference<rendering::XCanvas>& rxCanvas) +{ + mxCanvas = rxCanvas; + if (mpFont.get() != NULL) + mpFont->PrepareFont(Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY)); +} + + + + +void PresenterSlideSorter::MouseOverManager::SetSlide ( + const sal_Int32 nSlideIndex, + const awt::Rectangle& rBox) +{ + if (mnSlideIndex == nSlideIndex) + return; + + mnSlideIndex = -1; + Invalidate(); + + maSlideBoundingBox = rBox; + mnSlideIndex = nSlideIndex; + + if (nSlideIndex >= 0) + { + if (mxSlides.get() != NULL) + { + msText = OUString(); + + Reference<beans::XPropertySet> xSlideProperties(mxSlides->getByIndex(nSlideIndex), UNO_QUERY); + if (xSlideProperties.is()) + xSlideProperties->getPropertyValue(A2S("LinkDisplayName")) >>= msText; + + if (msText.getLength() == 0) + msText = A2S("Slide ") + OUString::valueOf(nSlideIndex + 1); + } + } + else + { + msText = OUString(); + } + mxBitmap = NULL; + + Invalidate(); +} + + + + +Reference<rendering::XBitmap> PresenterSlideSorter::MouseOverManager::CreateBitmap ( + const OUString& rsText, + const sal_Int32 nMaximalWidth) const +{ + if ( ! mxCanvas.is()) + return NULL; + + if (mpFont.get()==NULL || !mpFont->mxFont.is()) + return NULL; + + // Long text has to be shortened. + const OUString sText (GetFittingText(rsText, nMaximalWidth + - 2*gnHorizontalLabelBorder + - 2*gnHorizontalLabelPadding)); + + // Determine the size of the label. Its height is defined by the + // bitmaps that are used to paints its background. The width is defined + // by the text. + geometry::IntegerSize2D aLabelSize (CalculateLabelSize(sText)); + + // Create a new bitmap that will contain the complete label. + Reference<rendering::XBitmap> xBitmap ( + mxCanvas->getDevice()->createCompatibleAlphaBitmap(aLabelSize)); + + if ( ! xBitmap.is()) + return NULL; + + Reference<rendering::XBitmapCanvas> xBitmapCanvas (xBitmap, UNO_QUERY); + if ( ! xBitmapCanvas.is()) + return NULL; + + // Paint the background. + PaintButtonBackground(xBitmapCanvas, aLabelSize); + + // Paint the text. + if (sText.getLength() > 0) + { + + const rendering::StringContext aContext (sText, 0, sText.getLength()); + const Reference<rendering::XTextLayout> xLayout (mpFont->mxFont->createTextLayout( + aContext, rendering::TextDirection::WEAK_LEFT_TO_RIGHT,0)); + const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds()); + + const double nXOffset = (aLabelSize.Width - aTextBBox.X2 + aTextBBox.X1) / 2; + const double nYOffset = aLabelSize.Height + - (aLabelSize.Height - aTextBBox.Y2 + aTextBBox.Y1)/2 - aTextBBox.Y2; + + const rendering::ViewState aViewState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL); + + rendering::RenderState aRenderState ( + geometry::AffineMatrix2D(1,0,nXOffset, 0,1,nYOffset), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor); + + xBitmapCanvas->drawText( + aContext, + mpFont->mxFont, + aViewState, + aRenderState, + rendering::TextDirection::WEAK_LEFT_TO_RIGHT); + } + + return xBitmap; +} + + + + +OUString PresenterSlideSorter::MouseOverManager::GetFittingText ( + const OUString& rsText, + const double nMaximalWidth) const +{ + const double nTextWidth ( + PresenterCanvasHelper::GetTextSize(mpFont->mxFont, rsText).Width); + if (nTextWidth > nMaximalWidth) + { + // Text is too wide. Shorten it by removing characters from the end + // and replacing them by ellipses. + + // Guess a start value of the final string length. + double nBestWidth (0); + OUString sBestCandidate; + sal_Int32 nLength (round(rsText.getLength() * nMaximalWidth / nTextWidth)); + const OUString sEllipses (A2S("...")); + while (true) + { + const OUString sCandidate (rsText.copy(0,nLength) + sEllipses); + const double nWidth ( + PresenterCanvasHelper::GetTextSize(mpFont->mxFont, sCandidate).Width); + if (nWidth > nMaximalWidth) + { + // Candidate still too wide, shorten it. + nLength -= 1; + if (nLength <= 0) + break; + } + else if (nWidth < nMaximalWidth) + { + // Candidate short enough. + if (nWidth > nBestWidth) + { + // Best length so far. + sBestCandidate = sCandidate; + nBestWidth = nWidth; + nLength += 1; + if (nLength >= rsText.getLength()) + break; + } + else + break; + } + else + { + // Candidate is exactly as long as it may be. Use it + // without looking any further. + sBestCandidate = sCandidate; + break; + } + } + return sBestCandidate; + } + else + return rsText; +} + + + + +geometry::IntegerSize2D PresenterSlideSorter::MouseOverManager::CalculateLabelSize ( + const OUString& rsText) const +{ + // Height is specified by the label bitmaps. + sal_Int32 nHeight (32); + if (mpCenterLabelBitmap.get() != NULL) + { + Reference<rendering::XBitmap> xBitmap (mpCenterLabelBitmap->GetNormalBitmap()); + if (xBitmap.is()) + nHeight = xBitmap->getSize().Height; + } + + // Width is specified by text width and maximal width. + const geometry::RealSize2D aTextSize ( + PresenterCanvasHelper::GetTextSize(mpFont->mxFont, rsText)); + + const sal_Int32 nWidth (round(aTextSize.Width + 2*gnHorizontalLabelPadding)); + + return geometry::IntegerSize2D(nWidth, nHeight); +} + + + + +void PresenterSlideSorter::MouseOverManager::PaintButtonBackground ( + const Reference<rendering::XBitmapCanvas>& rxCanvas, + const geometry::IntegerSize2D& rSize) const +{ + // Get the bitmaps for painting the label background. + Reference<rendering::XBitmap> xLeftLabelBitmap; + if (mpLeftLabelBitmap.get() != NULL) + xLeftLabelBitmap = mpLeftLabelBitmap->GetNormalBitmap(); + + Reference<rendering::XBitmap> xCenterLabelBitmap; + if (mpCenterLabelBitmap.get() != NULL) + xCenterLabelBitmap = mpCenterLabelBitmap->GetNormalBitmap(); + + Reference<rendering::XBitmap> xRightLabelBitmap; + if (mpRightLabelBitmap.get() != NULL) + xRightLabelBitmap = mpRightLabelBitmap->GetNormalBitmap(); + + PresenterUIPainter::PaintHorizontalBitmapComposite ( + Reference<rendering::XCanvas>(rxCanvas, UNO_QUERY), + awt::Rectangle(0,0, rSize.Width,rSize.Height), + awt::Rectangle(0,0, rSize.Width,rSize.Height), + xLeftLabelBitmap, + xCenterLabelBitmap, + xRightLabelBitmap); +} + + + + +void PresenterSlideSorter::MouseOverManager::Invalidate (void) +{ + if (mpPaintManager.get() != NULL) + mpPaintManager->Invalidate(mxInvalidateTarget, maSlideBoundingBox, true); +} + + + + +//===== PresenterSlideSorter::CurrentSlideFrameRenderer ======================= + +PresenterSlideSorter::CurrentSlideFrameRenderer::CurrentSlideFrameRenderer ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas) + : mpTopLeft(), + mpTop(), + mpTopRight(), + mpLeft(), + mpRight(), + mpBottomLeft(), + mpBottom(), + mpBottomRight(), + mnTopFrameSize(0), + mnLeftFrameSize(0), + mnRightFrameSize(0), + mnBottomFrameSize(0) +{ + PresenterConfigurationAccess aConfiguration ( + rxContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.extension.PresenterScreen/")), + PresenterConfigurationAccess::READ_ONLY); + Reference<container::XHierarchicalNameAccess> xBitmaps ( + aConfiguration.GetConfigurationNode( + A2S("PresenterScreenSettings/SlideSorter/CurrentSlideBorderBitmaps")), + UNO_QUERY); + if ( ! xBitmaps.is()) + return; + + PresenterBitmapContainer aContainer ( + A2S("PresenterScreenSettings/SlideSorter/CurrentSlideBorderBitmaps"), + ::boost::shared_ptr<PresenterBitmapContainer>(), + rxContext, + rxCanvas, + PresenterComponent::GetBasePath(rxContext)); + + mpTopLeft = aContainer.GetBitmap(A2S("TopLeft")); + mpTop = aContainer.GetBitmap(A2S("Top")); + mpTopRight = aContainer.GetBitmap(A2S("TopRight")); + mpLeft = aContainer.GetBitmap(A2S("Left")); + mpRight = aContainer.GetBitmap(A2S("Right")); + mpBottomLeft = aContainer.GetBitmap(A2S("BottomLeft")); + mpBottom = aContainer.GetBitmap(A2S("Bottom")); + mpBottomRight = aContainer.GetBitmap(A2S("BottomRight")); + + // Determine size of frame. + if (mpTop.get() != NULL) + mnTopFrameSize = mpTop->mnHeight; + if (mpLeft.get() != NULL) + mnLeftFrameSize = mpLeft->mnWidth; + if (mpRight.get() != NULL) + mnRightFrameSize = mpRight->mnWidth; + if (mpBottom.get() != NULL) + mnBottomFrameSize = mpBottom->mnHeight; + + if (mpTopLeft.get() != NULL) + { + mnTopFrameSize = ::std::max(mnTopFrameSize, mpTopLeft->mnHeight); + mnLeftFrameSize = ::std::max(mnLeftFrameSize, mpTopLeft->mnWidth); + } + if (mpTopRight.get() != NULL) + { + mnTopFrameSize = ::std::max(mnTopFrameSize, mpTopRight->mnHeight); + mnRightFrameSize = ::std::max(mnRightFrameSize, mpTopRight->mnWidth); + } + if (mpBottomLeft.get() != NULL) + { + mnLeftFrameSize = ::std::max(mnLeftFrameSize, mpBottomLeft->mnWidth); + mnBottomFrameSize = ::std::max(mnBottomFrameSize, mpBottomLeft->mnHeight); + } + if (mpBottomRight.get() != NULL) + { + mnRightFrameSize = ::std::max(mnRightFrameSize, mpBottomRight->mnWidth); + mnBottomFrameSize = ::std::max(mnBottomFrameSize, mpBottomRight->mnHeight); + } +} + + + + +PresenterSlideSorter::CurrentSlideFrameRenderer::~CurrentSlideFrameRenderer (void) +{ +} + + + + +void PresenterSlideSorter::CurrentSlideFrameRenderer::PaintCurrentSlideFrame ( + const awt::Rectangle& rSlideBoundingBox, + const Reference<rendering::XCanvas>& rxCanvas, + const geometry::RealRectangle2D& rClipBox) +{ + if ( ! rxCanvas.is()) + return; + + const Reference<rendering::XPolyPolygon2D> xClip ( + PresenterGeometryHelper::CreatePolygon(rClipBox, rxCanvas->getDevice())); + + if (mpTop.get() != NULL) + { + PaintBitmapTiled( + mpTop->GetNormalBitmap(), + rxCanvas, + rClipBox, + rSlideBoundingBox.X, + rSlideBoundingBox.Y - mpTop->mnHeight, + rSlideBoundingBox.Width, + mpTop->mnHeight); + } + if (mpLeft.get() != NULL) + { + PaintBitmapTiled( + mpLeft->GetNormalBitmap(), + rxCanvas, + rClipBox, + rSlideBoundingBox.X - mpLeft->mnWidth, + rSlideBoundingBox.Y, + mpLeft->mnWidth, + rSlideBoundingBox.Height); + } + if (mpRight.get() != NULL) + { + PaintBitmapTiled( + mpRight->GetNormalBitmap(), + rxCanvas, + rClipBox, + rSlideBoundingBox.X + rSlideBoundingBox.Width, + rSlideBoundingBox.Y, + mpRight->mnWidth, + rSlideBoundingBox.Height); + } + if (mpBottom.get() != NULL) + { + PaintBitmapTiled( + mpBottom->GetNormalBitmap(), + rxCanvas, + rClipBox, + rSlideBoundingBox.X, + rSlideBoundingBox.Y + rSlideBoundingBox.Height, + rSlideBoundingBox.Width, + mpBottom->mnHeight); + } + if (mpTopLeft.get() != NULL) + { + PaintBitmapOnce( + mpTopLeft->GetNormalBitmap(), + rxCanvas, + xClip, + rSlideBoundingBox.X - mpTopLeft->mnWidth, + rSlideBoundingBox.Y - mpTopLeft->mnHeight); + } + if (mpTopRight.get() != NULL) + { + PaintBitmapOnce( + mpTopRight->GetNormalBitmap(), + rxCanvas, + xClip, + rSlideBoundingBox.X + rSlideBoundingBox.Width, + rSlideBoundingBox.Y - mpTopLeft->mnHeight); + } + if (mpBottomLeft.get() != NULL) + { + PaintBitmapOnce( + mpBottomLeft->GetNormalBitmap(), + rxCanvas, + xClip, + rSlideBoundingBox.X - mpBottomLeft->mnWidth, + rSlideBoundingBox.Y + rSlideBoundingBox.Height); + } + if (mpBottomRight.get() != NULL) + { + PaintBitmapOnce( + mpBottomRight->GetNormalBitmap(), + rxCanvas, + xClip, + rSlideBoundingBox.X + rSlideBoundingBox.Width, + rSlideBoundingBox.Y + rSlideBoundingBox.Height); + } +} + + + + +awt::Rectangle PresenterSlideSorter::CurrentSlideFrameRenderer::GetBoundingBox ( + const awt::Rectangle& rSlideBoundingBox) +{ + return awt::Rectangle( + rSlideBoundingBox.X - mnLeftFrameSize, + rSlideBoundingBox.Y - mnTopFrameSize, + rSlideBoundingBox.Width + mnLeftFrameSize + mnRightFrameSize, + rSlideBoundingBox.Height + mnTopFrameSize + mnBottomFrameSize); +} + + + + +void PresenterSlideSorter::CurrentSlideFrameRenderer::PaintBitmapOnce( + const css::uno::Reference<css::rendering::XBitmap>& rxBitmap, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const Reference<rendering::XPolyPolygon2D>& rxClip, + const double nX, + const double nY) +{ + OSL_ASSERT(rxCanvas.is()); + if ( ! rxBitmap.is()) + return; + + const rendering::ViewState aViewState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + rxClip); + + const rendering::RenderState aRenderState ( + geometry::AffineMatrix2D( + 1, 0, nX, + 0, 1, nY), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + + rxCanvas->drawBitmap( + rxBitmap, + aViewState, + aRenderState); +} + + + + +void PresenterSlideSorter::CurrentSlideFrameRenderer::PaintBitmapTiled( + const css::uno::Reference<css::rendering::XBitmap>& rxBitmap, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const geometry::RealRectangle2D& rClipBox, + const double nX0, + const double nY0, + const double nWidth, + const double nHeight) +{ + OSL_ASSERT(rxCanvas.is()); + if ( ! rxBitmap.is()) + return; + + geometry::IntegerSize2D aSize (rxBitmap->getSize()); + + const rendering::ViewState aViewState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + PresenterGeometryHelper::CreatePolygon( + PresenterGeometryHelper::Intersection( + rClipBox, + geometry::RealRectangle2D(nX0,nY0,nX0+nWidth,nY0+nHeight)), + rxCanvas->getDevice())); + + rendering::RenderState aRenderState ( + geometry::AffineMatrix2D( + 1, 0, nX0, + 0, 1, nY0), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + + const double nX1 = nX0 + nWidth; + const double nY1 = nY0 + nHeight; + for (double nY=nY0; nY<nY1; nY+=aSize.Height) + for (double nX=nX0; nX<nX1; nX+=aSize.Width) + { + aRenderState.AffineTransform.m02 = nX; + aRenderState.AffineTransform.m12 = nY; + rxCanvas->drawBitmap( + rxBitmap, + aViewState, + aRenderState); + } +} + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterSlideSorter.hxx b/sdext/source/presenter/PresenterSlideSorter.hxx new file mode 100644 index 000000000000..e3e6ebe8c031 --- /dev/null +++ b/sdext/source/presenter/PresenterSlideSorter.hxx @@ -0,0 +1,236 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_SLIDE_SORTER_HXX +#define SDEXT_PRESENTER_PRESENTER_SLIDE_SORTER_HXX + +#include "PresenterController.hxx" +#include "PresenterPaneContainer.hxx" +#include "PresenterViewFactory.hxx" +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase8.hxx> +#include <com/sun/star/awt/XPaintListener.hpp> +#include <com/sun/star/awt/XWindowListener.hpp> +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#include <com/sun/star/drawing/XDrawView.hpp> +#include <com/sun/star/drawing/XSlidePreviewCache.hpp> +#include <com/sun/star/drawing/framework/XView.hpp> +#include <com/sun/star/drawing/framework/XResourceId.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/geometry/RealRectangle2D.hpp> +#include <com/sun/star/rendering/XPolyPolygon2D.hpp> +#include <com/sun/star/rendering/XSprite.hpp> +#include <com/sun/star/rendering/XSpriteCanvas.hpp> + +namespace css = ::com::sun::star; + +namespace { + typedef cppu::WeakComponentImplHelper8< + css::drawing::framework::XView, + css::awt::XWindowListener, + css::awt::XPaintListener, + css::beans::XPropertyChangeListener, + css::drawing::XSlidePreviewCacheListener, + css::awt::XMouseListener, + css::awt::XMouseMotionListener, + css::drawing::XDrawView + > PresenterSlideSorterInterfaceBase; +} + +namespace sdext { namespace presenter { + +class PresenterButton; +class PresenterScrollBar; + +/** A simple slide sorter for the presenter screen. It uses a preview cache + to create the slide previews. Painting is done via a canvas. +*/ +class PresenterSlideSorter + : private ::cppu::BaseMutex, + public PresenterSlideSorterInterfaceBase, + public CachablePresenterView +{ +public: + PresenterSlideSorter ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId, + const css::uno::Reference<css::frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~PresenterSlideSorter (void); + + virtual void SAL_CALL disposing (void); + + void SetActiveState (const bool bIsActive); + + + // lang::XEventListener + + virtual void SAL_CALL + disposing (const css::lang::EventObject& rEventObject) + throw (css::uno::RuntimeException); + + + // XWindowListener + + virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // XPaintListener + + virtual void SAL_CALL windowPaint (const css::awt::PaintEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XMouseListener + + virtual void SAL_CALL mousePressed (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL mouseReleased (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL mouseEntered (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL mouseExited (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + + // XMouseMotionListener + + virtual void SAL_CALL mouseMoved (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseDragged (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XResourceId + + virtual css::uno::Reference<css::drawing::framework::XResourceId> SAL_CALL getResourceId (void) + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isAnchorOnly (void) + throw (com::sun::star::uno::RuntimeException); + + + // XPropertyChangeListener + + virtual void SAL_CALL propertyChange ( + const css::beans::PropertyChangeEvent& rEvent) + throw(css::uno::RuntimeException); + + + // XSlidePreviewCacheListener + + virtual void SAL_CALL notifyPreviewCreation ( + sal_Int32 nSlideIndex) + throw(css::uno::RuntimeException); + + + // XDrawView + + virtual void SAL_CALL setCurrentPage ( + const css::uno::Reference<css::drawing::XDrawPage>& rxSlide) + throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::drawing::XDrawPage> SAL_CALL getCurrentPage (void) + throw (css::uno::RuntimeException); + +private: + css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + css::uno::Reference<css::drawing::framework::XResourceId> mxViewId; + css::uno::Reference<css::drawing::framework::XPane> mxPane; + css::uno::Reference<css::rendering::XCanvas> mxCanvas; + css::uno::Reference<css::awt::XWindow> mxWindow; + ::rtl::Reference<PresenterController> mpPresenterController; + css::uno::Reference<css::presentation::XSlideShowController> mxSlideShowController; + css::uno::Reference<css::drawing::XSlidePreviewCache> mxPreviewCache; + bool mbIsPaintPending; + bool mbIsLayoutPending; + class Layout; + ::boost::shared_ptr<Layout> mpLayout; + ::rtl::Reference<PresenterScrollBar> mpHorizontalScrollBar; + ::rtl::Reference<PresenterScrollBar> mpVerticalScrollBar; + ::rtl::Reference<PresenterButton> mpCloseButton; + class MouseOverManager; + ::boost::scoped_ptr<MouseOverManager> mpMouseOverManager; + sal_Int32 mnSlideIndexMousePressed; + sal_Int32 mnCurrentSlideIndex; + sal_Int32 mnSeparatorY; + css::util::Color maSeparatorColor; + css::awt::Point maCloseButtonCenter; + css::awt::Rectangle maCurrentSlideFrameBoundingBox; + class CurrentSlideFrameRenderer; + ::boost::shared_ptr<CurrentSlideFrameRenderer> mpCurrentSlideFrameRenderer; + css::uno::Reference<css::rendering::XPolyPolygon2D> mxPreviewFrame; + + void UpdateLayout (void); + css::geometry::RealRectangle2D PlaceScrollBars ( + const css::geometry::RealRectangle2D& rUpperBox); + void PlaceCloseButton ( + const PresenterPaneContainer::SharedPaneDescriptor& rpPane, + const css::awt::Rectangle& rCenterBox, + const sal_Int32 nLeftFrameWidth); + void ClearBackground ( + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRedrawArea); + double GetSlideAspectRatio (void) const; + css::uno::Reference<css::rendering::XBitmap> GetPreview (const sal_Int32 nSlideIndex); + void PaintPreview ( + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rUpdateBox, + const sal_Int32 nSlideIndex); + void Paint (const css::awt::Rectangle& rUpdateBox); + void SetHorizontalOffset (const double nXOffset); + void SetVerticalOffset (const double nYOffset); + void GotoSlide (const sal_Int32 nSlideIndex); + bool ProvideCanvas (void); + + /** This method throws a DisposedException when the object has already been + disposed. + */ + void ThrowIfDisposed (void) + throw (css::lang::DisposedException); +}; + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterSprite.cxx b/sdext/source/presenter/PresenterSprite.cxx new file mode 100644 index 000000000000..467fb5830dd5 --- /dev/null +++ b/sdext/source/presenter/PresenterSprite.cxx @@ -0,0 +1,292 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterSprite.hxx" + +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/RenderState.hpp> +#include <com/sun/star/rendering/ViewState.hpp> + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::UNO_QUERY; + +namespace sdext { namespace presenter { + +PresenterSprite::PresenterSprite (void) + : mxSpriteFactory(), + mxSprite(), + maSize(0,0), + maLocation(0,0), + maTransform(1,0,0, 0,1,0), + mbIsVisible(false), + mnPriority(0), + mnAlpha(1.0) +{ +} + + + + +PresenterSprite::~PresenterSprite (void) +{ + if (mxSprite.is()) + { + mxSprite->hide(); + Reference<lang::XComponent> xComponent (mxSprite, UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + mxSprite = NULL; + } +} + + + + +void PresenterSprite::SetFactory ( + const ::css::uno::Reference<css::rendering::XSpriteCanvas>& rxSpriteFactory) +{ + if (mxSpriteFactory != rxSpriteFactory) + { + DisposeSprite(); + mxSpriteFactory = rxSpriteFactory; + if (mbIsVisible) + PresenterSprite(); + } +} + + + + +::css::uno::Reference<css::rendering::XCanvas> PresenterSprite::GetCanvas (void) +{ + ProvideSprite(); + if (mxSprite.is()) + return mxSprite->getContentCanvas(); + else + return NULL; +} + + + + +void PresenterSprite::Show (void) +{ + mbIsVisible = true; + if (mxSprite.is()) + mxSprite->show(); + else + ProvideSprite(); +} + + + + +void PresenterSprite::Hide (void) +{ + mbIsVisible = false; + if (mxSprite.is()) + mxSprite->hide(); +} + + + + +bool PresenterSprite::IsVisible (void) const +{ + return mbIsVisible; +} + + + + +void PresenterSprite::SetPriority (const double nPriority) +{ + mnPriority = nPriority; + if (mxSprite.is()) + mxSprite->setPriority(mnPriority); +} + + + + +double PresenterSprite::GetPriority (void) const +{ + return mnPriority; +} + + + + +void PresenterSprite::Resize (const css::geometry::RealSize2D& rSize) +{ + maSize = rSize; + if (mxSprite.is()) + DisposeSprite(); + if (mbIsVisible) + ProvideSprite(); +} + + + + +css::geometry::RealSize2D PresenterSprite::GetSize (void) const +{ + return maSize; +} + + + + +void PresenterSprite::MoveTo (const css::geometry::RealPoint2D& rLocation) +{ + maLocation = rLocation; + if (mxSprite.is()) + mxSprite->move( + maLocation, + rendering::ViewState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL), + rendering::RenderState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + uno::Sequence<double>(4), + rendering::CompositeOperation::SOURCE) + ); +} + + + + +css::geometry::RealPoint2D PresenterSprite::GetLocation (void) const +{ + return maLocation; +} + + + + +void PresenterSprite::Transform (const css::geometry::AffineMatrix2D& rTransform) +{ + maTransform = rTransform; + if (mxSprite.is()) + mxSprite->transform(maTransform); +} + + + + +css::geometry::AffineMatrix2D PresenterSprite::GetTransform (void) const +{ + return maTransform; +} + + + + +void PresenterSprite::SetAlpha (const double nAlpha) +{ + mnAlpha = nAlpha; + if (mxSprite.is()) + mxSprite->setAlpha(mnAlpha); +} + + + + +double PresenterSprite::GetAlpha (void) const +{ + return mnAlpha; +} + + + + +void PresenterSprite::Update (void) +{ + if (mxSpriteFactory.is()) + mxSpriteFactory->updateScreen(sal_False); +} + + + + +void PresenterSprite::ProvideSprite (void) +{ + if ( ! mxSprite.is() + && mxSpriteFactory.is() + && maSize.Width>0 + && maSize.Height>0) + { + mxSprite = mxSpriteFactory->createCustomSprite(maSize); + if (mxSprite.is()) + { + mxSprite->transform(maTransform); + mxSprite->move(maLocation, + rendering::ViewState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL), + rendering::RenderState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + uno::Sequence<double>(4), + rendering::CompositeOperation::SOURCE) + ); + mxSprite->setAlpha(mnAlpha); + mxSprite->setPriority(mnPriority); + if (mbIsVisible) + mxSprite->show(); + } + } +} + + + + +void PresenterSprite::DisposeSprite (void) +{ + if (mxSprite.is()) + { + mxSprite->hide(); + Reference<lang::XComponent> xComponent (mxSprite, UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + mxSprite = NULL; + } +} + + + + +} } //end of namespace sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterSprite.hxx b/sdext/source/presenter/PresenterSprite.hxx new file mode 100644 index 000000000000..e6be8e46ebad --- /dev/null +++ b/sdext/source/presenter/PresenterSprite.hxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_SPRITE_HXX +#define SDEXT_PRESENTER_PRESENTER_SPRITE_HXX + +#include <com/sun/star/rendering/XCustomSprite.hpp> +#include <com/sun/star/rendering/XSpriteCanvas.hpp> +#include <boost/noncopyable.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +/** A wrapper around a com::sun::star::rendering::XCustomSprite that allows + not only setting values like size, location, and transformation but also + provides read access to them. + It also handles the showing and hiding of a sprite. This includes not + to show the sprite when its size is not yet defined (results in a crash) + and hiding a sprite before disposing it (results in zombie sprites.) +*/ +class PresenterSprite + : private ::boost::noncopyable +{ +public: + PresenterSprite (void); + virtual ~PresenterSprite (void); + + /** The given sprite canvas is used as factory to create the sprite that + is wrapped by objects of this class. + It is also used to call updateScreen() at (wrapped by the Update() method). + */ + void SetFactory ( + const ::css::uno::Reference<css::rendering::XSpriteCanvas>& rxSpriteFactory); + + ::css::uno::Reference<css::rendering::XCanvas> GetCanvas (void); + + void Show (void); + void Hide (void); + bool IsVisible (void) const; + + void SetPriority (const double nPriority); + double GetPriority (void) const; + + void Resize (const css::geometry::RealSize2D& rSize); + css::geometry::RealSize2D GetSize (void) const; + + void MoveTo (const css::geometry::RealPoint2D& rLocation); + css::geometry::RealPoint2D GetLocation (void) const; + + void Transform (const css::geometry::AffineMatrix2D& rTransform); + css::geometry::AffineMatrix2D GetTransform (void) const; + + void SetAlpha (const double nAlpha); + double GetAlpha (void) const; + + void Update (void); + +private: + ::css::uno::Reference<css::rendering::XSpriteCanvas> mxSpriteFactory; + ::css::uno::Reference<css::rendering::XCustomSprite> mxSprite; + css::geometry::RealSize2D maSize; + css::geometry::RealPoint2D maLocation; + css::geometry::AffineMatrix2D maTransform; + bool mbIsVisible; + double mnPriority; + double mnAlpha; + + void ProvideSprite (void); + void DisposeSprite (void); +}; + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterSpritePane.cxx b/sdext/source/presenter/PresenterSpritePane.cxx new file mode 100644 index 000000000000..ae4866f58879 --- /dev/null +++ b/sdext/source/presenter/PresenterSpritePane.cxx @@ -0,0 +1,263 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterSpritePane.hxx" +#include "PresenterGeometryHelper.hxx" +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <osl/mutex.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +namespace sdext { namespace presenter { + +//===== PresenterSpritePane ========================================================= + +PresenterSpritePane::PresenterSpritePane (const Reference<XComponentContext>& rxContext, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterPaneBase(rxContext, rpPresenterController), + mxParentWindow(), + mxParentCanvas(), + mpSprite(new PresenterSprite()) +{ + Reference<lang::XMultiComponentFactory> xFactory ( + mxComponentContext->getServiceManager(), UNO_QUERY_THROW); + mxPresenterHelper = Reference<drawing::XPresenterHelper>( + xFactory->createInstanceWithContext( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.PresenterHelper")), + mxComponentContext), + UNO_QUERY_THROW); +} + + + + +PresenterSpritePane::~PresenterSpritePane (void) +{ +} + + + + +void PresenterSpritePane::disposing (void) +{ + mpSprite->SetFactory(NULL); + mxParentWindow = NULL; + mxParentCanvas = NULL; + PresenterPaneBase::disposing(); +} + + + + +//----- XPane ----------------------------------------------------------------- + +Reference<awt::XWindow> SAL_CALL PresenterSpritePane::getWindow (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + return mxContentWindow; +} + + + + +Reference<rendering::XCanvas> SAL_CALL PresenterSpritePane::getCanvas (void) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + if ( ! mxContentCanvas.is()) + UpdateCanvases(); + + return mxContentCanvas; +} + + + + +//----- XWindowListener ------------------------------------------------------- + +void SAL_CALL PresenterSpritePane::windowResized (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + PresenterPaneBase::windowResized(rEvent); + + mpSprite->Resize(geometry::RealSize2D(rEvent.Width, rEvent.Height)); + LayoutContextWindow(); + UpdateCanvases(); +} + + + + + +void SAL_CALL PresenterSpritePane::windowMoved (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + PresenterPaneBase::windowMoved(rEvent); + + awt::Rectangle aBox ( + mxPresenterHelper->getWindowExtentsRelative(mxBorderWindow, mxParentWindow)); + mpSprite->MoveTo(geometry::RealPoint2D(aBox.X, aBox.Y)); + mpSprite->Update(); +} + + + + +void SAL_CALL PresenterSpritePane::windowShown (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + PresenterPaneBase::windowShown(rEvent); + + mpSprite->Show(); + ToTop(); + + if (mxContentWindow.is()) + { + LayoutContextWindow(); + mxContentWindow->setVisible(sal_True); + } +} + + + + +void SAL_CALL PresenterSpritePane::windowHidden (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + PresenterPaneBase::windowHidden(rEvent); + + mpSprite->Hide(); + if (mxContentWindow.is()) + mxContentWindow->setVisible(sal_False); +} + + + + +//----- XPaintListener -------------------------------------------------------- + +void SAL_CALL PresenterSpritePane::windowPaint (const awt::PaintEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + ThrowIfDisposed(); + + /* + Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxParentCanvas, UNO_QUERY); + if (xSpriteCanvas.is()) + xSpriteCanvas->updateScreen(sal_False); + */ +} + + + + +//----------------------------------------------------------------------------- + + +::boost::shared_ptr<PresenterSprite> PresenterSpritePane::GetSprite (void) +{ + return mpSprite; +} + + + + +void PresenterSpritePane::ShowTransparentBorder (void) +{ +} + + + + +void PresenterSpritePane::UpdateCanvases (void) +{ + Reference<XComponent> xContentCanvasComponent (mxContentCanvas, UNO_QUERY); + if (xContentCanvasComponent.is()) + { + if (xContentCanvasComponent.is()) + xContentCanvasComponent->dispose(); + } + + // The border canvas is the content canvas of the sprite. + mxBorderCanvas = mpSprite->GetCanvas(); + + // The content canvas is a wrapper of the border canvas. + if (mxBorderCanvas.is()) + mxContentCanvas = mxPresenterHelper->createSharedCanvas( + mxParentCanvas, + mxParentWindow, + mxBorderCanvas, + mxBorderWindow, + mxContentWindow); + + const awt::Rectangle aWindowBox (mxBorderWindow->getPosSize()); + PaintBorder(awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height)); +} + + + + +void PresenterSpritePane::CreateCanvases ( + const css::uno::Reference<css::awt::XWindow>& rxParentWindow, + const css::uno::Reference<css::rendering::XSpriteCanvas>& rxParentCanvas) +{ + OSL_ASSERT(!mxParentWindow.is() || mxParentWindow==rxParentWindow); + OSL_ASSERT(!mxParentCanvas.is() || mxParentCanvas==rxParentCanvas); + mxParentWindow = rxParentWindow; + mxParentCanvas = rxParentCanvas; + + mpSprite->SetFactory(mxParentCanvas); + if (mxBorderWindow.is()) + { + const awt::Rectangle aBorderBox (mxBorderWindow->getPosSize()); + mpSprite->Resize(geometry::RealSize2D(aBorderBox.Width, aBorderBox.Height)); + } + + UpdateCanvases(); +} + + + + +} } // end of namespace ::sd::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterSpritePane.hxx b/sdext/source/presenter/PresenterSpritePane.hxx new file mode 100644 index 000000000000..468f531f5e87 --- /dev/null +++ b/sdext/source/presenter/PresenterSpritePane.hxx @@ -0,0 +1,129 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SD_PRESENTER_PRESENTER_SPRITE_PANE_HXX +#define SD_PRESENTER_PRESENTER_SPRITE_PANE_HXX + +#include "PresenterPaneBase.hxx" +#include "PresenterSprite.hxx" +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/awt/XMouseListener.hpp> +#include <com/sun/star/awt/XMouseMotionListener.hpp> +#include <com/sun/star/awt/XWindowListener.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/drawing/framework/XPaneBorderPainter.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/rendering/XCanvas.hpp> +#include <com/sun/star/rendering/XSpriteCanvas.hpp> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase1.hxx> +#include <rtl/ref.hxx> +#include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> + +namespace css = ::com::sun::star; + + +namespace sdext { namespace presenter { + +/** Use a sprite to display the contents and the border of a pane. Windows + are still used to define the locations and sizes of both the border and + the pane content. Note that every resize results in a disposed canvas. + Therefore call getCanvas in every repaint or at least after every resize. +*/ +class PresenterSpritePane : public PresenterPaneBase +{ +public: + PresenterSpritePane ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~PresenterSpritePane (void); + + virtual void SAL_CALL disposing (void); + + using css::lang::XEventListener::disposing; + + ::boost::shared_ptr<PresenterSprite> GetSprite (void); + + static ::rtl::OUString getImplementationName_static (void); + static css::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static (void); + static css::uno::Reference<css::uno::XInterface> Create( + const css::uno::Reference<css::uno::XComponentContext>& rxContext) + SAL_THROW((css::uno::Exception)); + + void ShowTransparentBorder (void); + + // XPane + + virtual css::uno::Reference<css::awt::XWindow> SAL_CALL getWindow (void) + throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::rendering::XCanvas> SAL_CALL getCanvas (void) + throw (css::uno::RuntimeException); + + + // XWindowListener + + virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // XPaintListener + + virtual void SAL_CALL windowPaint (const css::awt::PaintEvent& rEvent) + throw (css::uno::RuntimeException); + + +private: + css::uno::Reference<css::awt::XWindow> mxParentWindow; + css::uno::Reference<css::rendering::XSpriteCanvas> mxParentCanvas; + ::boost::shared_ptr<PresenterSprite> mpSprite; + + virtual void CreateCanvases ( + const css::uno::Reference<css::awt::XWindow>& rxParentWindow, + const css::uno::Reference<css::rendering::XSpriteCanvas>& rxParentCanvas); + void UpdateCanvases (void); +}; + +} } // end of namespace ::sd::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterTextView.cxx b/sdext/source/presenter/PresenterTextView.cxx new file mode 100644 index 000000000000..1fe02450cf9b --- /dev/null +++ b/sdext/source/presenter/PresenterTextView.cxx @@ -0,0 +1,1594 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_sdext.hxx" + +#include "PresenterTextView.hxx" +#include "PresenterCanvasHelper.hxx" +#include "PresenterGeometryHelper.hxx" +#include "PresenterTimer.hxx" + +#include <cmath> + +#include <com/sun/star/accessibility/AccessibleTextType.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/i18n/CharType.hpp> +#include <com/sun/star/i18n/CharacterIteratorMode.hpp> +#include <com/sun/star/i18n/CTLScriptType.hpp> +#include <com/sun/star/i18n/ScriptDirection.hpp> +#include <com/sun/star/i18n/WordType.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/TextDirection.hpp> +#include <com/sun/star/text/WritingMode2.hpp> +#include <boost/bind.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::uno; + +#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) + +const static sal_Int64 CaretBlinkIntervall = 500 * 1000 * 1000; + +//#define SHOW_CHARACTER_BOXES + +namespace { + sal_Int32 Signum (const sal_Int32 nValue) + { + if (nValue < 0) + return -1; + else if (nValue > 0) + return +1; + else + return 0; + } +} + +namespace sdext { namespace presenter { + + +//===== PresenterTextView ===================================================== + +PresenterTextView::PresenterTextView ( + const Reference<XComponentContext>& rxContext, + const Reference<rendering::XCanvas>& rxCanvas, + const ::boost::function<void(const ::css::awt::Rectangle&)>& rInvalidator) + : mxCanvas(rxCanvas), + mbDoOuput(true), + mxBreakIterator(), + mxScriptTypeDetector(), + maLocation(0,0), + maSize(0,0), + mpFont(), + maParagraphs(), + mpCaret(new PresenterTextCaret( + ::boost::bind(&PresenterTextView::GetCaretBounds, this, _1, _2), + rInvalidator)), + mnLeftOffset(0), + mnTopOffset(0), + maInvalidator(rInvalidator), + mbIsFormatPending(false), + mnCharacterCount(-1), + maTextChangeBroadcaster() +{ + Reference<lang::XMultiComponentFactory> xFactory ( + rxContext->getServiceManager(), UNO_QUERY); + if ( ! xFactory.is()) + return; + + // Create the break iterator that we use to break text into lines. + mxBreakIterator = Reference<i18n::XBreakIterator>( + xFactory->createInstanceWithContext( + A2S("com.sun.star.i18n.BreakIterator"), + rxContext), + UNO_QUERY_THROW); + + // Create the script type detector that is used to split paragraphs into + // portions of the same text direction. + mxScriptTypeDetector = Reference<i18n::XScriptTypeDetector>( + xFactory->createInstanceWithContext( + A2S("com.sun.star.i18n.ScriptTypeDetector"), + rxContext), + UNO_QUERY_THROW); +} + + + + +PresenterTextView::PresenterTextView ( + const Reference<XComponentContext>& rxContext, + const Reference<rendering::XCanvas>& rxCanvas) + : mxCanvas(rxCanvas), + mbDoOuput(false), + mxBreakIterator(), + mxScriptTypeDetector(), + maLocation(0,0), + maSize(0,0), + mpFont(), + maParagraphs(), + mpCaret(new PresenterTextCaret( + ::boost::bind(&PresenterTextView::GetCaretBounds, this, _1, _2), + ::boost::function<void(const css::awt::Rectangle&)>())), + mnLeftOffset(0), + mnTopOffset(0), + maInvalidator(), + mbIsFormatPending(false), + mnCharacterCount(-1), + maTextChangeBroadcaster() +{ + Reference<lang::XMultiComponentFactory> xFactory ( + rxContext->getServiceManager(), UNO_QUERY); + if ( ! xFactory.is()) + return; + + // Create the break iterator that we use to break text into lines. + mxBreakIterator = Reference<i18n::XBreakIterator>( + xFactory->createInstanceWithContext( + A2S("com.sun.star.i18n.BreakIterator"), + rxContext), + UNO_QUERY_THROW); + + // Create the script type detector that is used to split paragraphs into + // portions of the same text direction. + mxScriptTypeDetector = Reference<i18n::XScriptTypeDetector>( + xFactory->createInstanceWithContext( + A2S("com.sun.star.i18n.ScriptTypeDetector"), + rxContext), + UNO_QUERY_THROW); +} + + + + +void PresenterTextView::SetText (const Reference<text::XText>& rxText) +{ + maParagraphs.clear(); + mnCharacterCount = -1; + + Reference<container::XEnumerationAccess> xParagraphAccess (rxText, UNO_QUERY); + if ( ! xParagraphAccess.is()) + return; + + Reference<container::XEnumeration> xParagraphs ( + xParagraphAccess->createEnumeration() , UNO_QUERY); + if ( ! xParagraphs.is()) + return; + + if ( ! mpFont || ! mpFont->PrepareFont(mxCanvas)) + return; + + sal_Int32 nCharacterCount (0); + while (xParagraphs->hasMoreElements()) + { + SharedPresenterTextParagraph pParagraph (new PresenterTextParagraph( + maParagraphs.size(), + mxBreakIterator, + mxScriptTypeDetector, + Reference<text::XTextRange>(xParagraphs->nextElement(), UNO_QUERY), + mpCaret)); + pParagraph->SetupCellArray(mpFont); + pParagraph->SetCharacterOffset(nCharacterCount); + nCharacterCount += pParagraph->GetCharacterCount(); + maParagraphs.push_back(pParagraph); + } + + if (mpCaret) + mpCaret->HideCaret(); + + RequestFormat(); +} + + + + +void PresenterTextView::SetText (const ::rtl::OUString& rsText) +{ + maParagraphs.clear(); + mnCharacterCount = -1; + + if ( ! mpFont || ! mpFont->PrepareFont(mxCanvas)) + return; + + sal_Int32 nCharacterCount (0); + + SharedPresenterTextParagraph pParagraph (new PresenterTextParagraph( + 0, + mxBreakIterator, + mxScriptTypeDetector, + rsText, + mpCaret)); + pParagraph->SetupCellArray(mpFont); + pParagraph->SetCharacterOffset(nCharacterCount); + nCharacterCount += pParagraph->GetCharacterCount(); + maParagraphs.push_back(pParagraph); + + if (mpCaret) + mpCaret->HideCaret(); + + RequestFormat(); +} + + + + +void PresenterTextView::SetTextChangeBroadcaster ( + const ::boost::function<void(void)>& rBroadcaster) +{ + maTextChangeBroadcaster = rBroadcaster; +} + + + + +void PresenterTextView::SetLocation (const css::geometry::RealPoint2D& rLocation) +{ + maLocation = rLocation; + + for (::std::vector<SharedPresenterTextParagraph>::iterator + iParagraph(maParagraphs.begin()), + iEnd(maParagraphs.end()); + iParagraph!=iEnd; + ++iParagraph) + { + (*iParagraph)->SetOrigin( + maLocation.X - mnLeftOffset, + maLocation.Y - mnTopOffset); + } +} + + + + +void PresenterTextView::SetSize (const css::geometry::RealSize2D& rSize) +{ + maSize = rSize; + RequestFormat(); +} + + + + +double PresenterTextView::GetTotalTextHeight (void) +{ + double nTotalHeight (0); + + if (mbIsFormatPending) + { + if ( ! mpFont->PrepareFont(mxCanvas)) + return 0; + Format(); + } + + for (::std::vector<SharedPresenterTextParagraph>::iterator + iParagraph(maParagraphs.begin()), + iEnd(maParagraphs.end()); + iParagraph!=iEnd; + ++iParagraph) + { + nTotalHeight += (*iParagraph)->GetTotalTextHeight(); + } + + return nTotalHeight; +} + + + + +void PresenterTextView::SetFont (const PresenterTheme::SharedFontDescriptor& rpFont) +{ + mpFont = rpFont; + RequestFormat(); +} + + + + +void PresenterTextView::SetOffset( + const double nLeft, + const double nTop) +{ + mnLeftOffset = nLeft; + mnTopOffset = nTop; + + // Trigger an update of the text origin stored at the individual paragraphs. + SetLocation(maLocation); +} + + + +void PresenterTextView::MoveCaret ( + const sal_Int32 nDistance, + const sal_Int16 nTextType) +{ + if ( ! mpCaret) + return; + + // When the caret has not been visible yet then move it to the beginning + // of the text. + if (mpCaret->GetParagraphIndex() < 0) + { + mpCaret->SetPosition(0,0); + return; + } + + sal_Int32 nParagraphIndex (mpCaret->GetParagraphIndex()); + sal_Int32 nCharacterIndex (mpCaret->GetCharacterIndex()); + switch (nTextType) + { + default: + case AccessibleTextType::CHARACTER: + nCharacterIndex += nDistance; + break; + + case AccessibleTextType::WORD: + { + sal_Int32 nRemainingDistance (nDistance); + while (nRemainingDistance != 0) + { + SharedPresenterTextParagraph pParagraph (GetParagraph(nParagraphIndex)); + if (pParagraph) + { + const sal_Int32 nDelta (Signum(nDistance)); + nCharacterIndex = pParagraph->GetWordBoundary(nCharacterIndex, nDelta); + if (nCharacterIndex < 0) + { + // Go to previous or next paragraph. + nParagraphIndex += nDelta; + if (nParagraphIndex < 0) + { + nParagraphIndex = 0; + nCharacterIndex = 0; + nRemainingDistance = 0; + } + else if (sal_uInt32(nParagraphIndex) >= maParagraphs.size()) + { + nParagraphIndex = maParagraphs.size()-1; + pParagraph = GetParagraph(nParagraphIndex); + if (pParagraph) + nCharacterIndex = pParagraph->GetCharacterCount(); + nRemainingDistance = 0; + } + else + { + nRemainingDistance -= nDelta; + + // Move caret one character to the end of + // the previous or the start of the next paragraph. + pParagraph = GetParagraph(nParagraphIndex); + if (pParagraph) + { + if (nDistance<0) + nCharacterIndex = pParagraph->GetCharacterCount(); + else + nCharacterIndex = 0; + } + } + } + else + nRemainingDistance -= nDelta; + } + else + break; + } + break; + } + } + + // Move the caret to the new position. + mpCaret->SetPosition(nParagraphIndex, nCharacterIndex); +} + + + + +void PresenterTextView::Paint ( + const css::awt::Rectangle& rUpdateBox) +{ + if ( ! mbDoOuput) + return; + if ( ! mxCanvas.is()) + return; + if ( ! mpFont->PrepareFont(mxCanvas)) + return; + + if (mbIsFormatPending) + Format(); + + // Setup the clipping rectangle. Horizontally we make it a little + // larger to allow characters (and the caret) to stick out of their + // bounding boxes. This can happen on some characters (like the + // uppercase J) for typographical reasons. + const sal_Int32 nAdditionalLeftBorder (10); + const sal_Int32 nAdditionalRightBorder (5); + double nX (maLocation.X - mnLeftOffset); + double nY (maLocation.Y - mnTopOffset); + const sal_Int32 nClipLeft (::std::max( + PresenterGeometryHelper::Round(maLocation.X)-nAdditionalLeftBorder, rUpdateBox.X)); + const sal_Int32 nClipTop (::std::max( + PresenterGeometryHelper::Round(maLocation.Y), rUpdateBox.Y)); + const sal_Int32 nClipRight (::std::min( + PresenterGeometryHelper::Round(maLocation.X+maSize.Width)+nAdditionalRightBorder, rUpdateBox.X+rUpdateBox.Width)); + const sal_Int32 nClipBottom (::std::min( + PresenterGeometryHelper::Round(maLocation.Y+maSize.Height), rUpdateBox.Y+rUpdateBox.Height)); + if (nClipLeft>=nClipRight || nClipTop>=nClipBottom) + return; + + const awt::Rectangle aClipBox( + nClipLeft, + nClipTop, + nClipRight - nClipLeft, + nClipBottom - nClipTop); + Reference<rendering::XPolyPolygon2D> xClipPolygon ( + PresenterGeometryHelper::CreatePolygon(aClipBox, mxCanvas->getDevice())); + + const rendering::ViewState aViewState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + xClipPolygon); + + rendering::RenderState aRenderState ( + geometry::AffineMatrix2D(1,0,nX, 0,1,nY), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor); + + for (::std::vector<SharedPresenterTextParagraph>::const_iterator + iParagraph(maParagraphs.begin()), + iEnd(maParagraphs.end()); + iParagraph!=iEnd; + ++iParagraph) + { + (*iParagraph)->Paint( + mxCanvas, + maSize, + mpFont, + aViewState, + aRenderState, + mnTopOffset, + nClipTop, + nClipBottom); + } + + aRenderState.AffineTransform.m02 = 0; + aRenderState.AffineTransform.m12 = 0; + +#ifdef SHOW_CHARACTER_BOXES + PresenterCanvasHelper::SetDeviceColor(aRenderState, 0x00808080); + for (sal_Int32 nParagraphIndex(0), nParagraphCount(GetParagraphCount()); + nParagraphIndex<nParagraphCount; + ++nParagraphIndex) + { + const SharedPresenterTextParagraph pParagraph (GetParagraph(nParagraphIndex)); + if ( ! pParagraph) + continue; + for (sal_Int32 nCharacterIndex(0),nCharacterCount(pParagraph->GetCharacterCount()); + nCharacterIndex<nCharacterCount; ++nCharacterIndex) + { + const awt::Rectangle aBox (pParagraph->GetCharacterBounds(nCharacterIndex, false)); + mxCanvas->drawPolyPolygon ( + PresenterGeometryHelper::CreatePolygon( + aBox, + mxCanvas->getDevice()), + aViewState, + aRenderState); + } + } + PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor); +#endif + + if (mpCaret && mpCaret->IsVisible()) + { + mxCanvas->fillPolyPolygon ( + PresenterGeometryHelper::CreatePolygon( + mpCaret->GetBounds(), + mxCanvas->getDevice()), + aViewState, + aRenderState); + } +} + + + + +SharedPresenterTextCaret PresenterTextView::GetCaret (void) const +{ + return mpCaret; +} + + + + +sal_Int32 PresenterTextView::GetCharacterOffset (const sal_Int32 nParagraphIndex) const +{ + sal_Int32 nCharacterOffset (0); + for (sal_Int32 nIndex=0; nIndex<nParagraphIndex; ++nIndex) + nCharacterOffset += maParagraphs[nIndex]->GetCharacterCount(); + return nCharacterOffset; +} + + + + +awt::Rectangle PresenterTextView::GetCaretBounds ( + sal_Int32 nParagraphIndex, + const sal_Int32 nCharacterIndex) const +{ + SharedPresenterTextParagraph pParagraph (GetParagraph(nParagraphIndex)); + + if (pParagraph) + return pParagraph->GetCharacterBounds(nCharacterIndex, true); + else + return awt::Rectangle(0,0,0,0); +} + + + + +//----- private --------------------------------------------------------------- + +void PresenterTextView::RequestFormat (void) +{ + mbIsFormatPending = true; +} + + + + +void PresenterTextView::Format (void) +{ + mbIsFormatPending = false; + + double nY (0); + for (::std::vector<SharedPresenterTextParagraph>::const_iterator + iParagraph(maParagraphs.begin()), + iEnd(maParagraphs.end()); + iParagraph!=iEnd; + ++iParagraph) + { + (*iParagraph)->Format(nY, maSize.Width, mpFont); + nY += (*iParagraph)->GetTotalTextHeight(); + } + + if (maTextChangeBroadcaster) + maTextChangeBroadcaster(); +} + + + + +sal_Int32 PresenterTextView::GetParagraphCount (void) const +{ + return maParagraphs.size(); +} + + + + +SharedPresenterTextParagraph PresenterTextView::GetParagraph ( + const sal_Int32 nParagraphIndex) const +{ + if (nParagraphIndex < 0) + return SharedPresenterTextParagraph(); + else if (nParagraphIndex>=sal_Int32(maParagraphs.size())) + return SharedPresenterTextParagraph(); + else + return maParagraphs[nParagraphIndex]; +} + + + + +//===== PresenterTextParagraph ================================================ + +PresenterTextParagraph::PresenterTextParagraph ( + const sal_Int32 nParagraphIndex, + const Reference<i18n::XBreakIterator>& rxBreakIterator, + const Reference<i18n::XScriptTypeDetector>& rxScriptTypeDetector, + const Reference<text::XTextRange>& rxTextRange, + const SharedPresenterTextCaret& rpCaret) + : msParagraphText(), + mnParagraphIndex(nParagraphIndex), + mpCaret(rpCaret), + mxBreakIterator(rxBreakIterator), + mxScriptTypeDetector(rxScriptTypeDetector), + maLines(), + mnVerticalOffset(0), + mnXOrigin(0), + mnYOrigin(0), + mnWidth(0), + mnAscent(0), + mnDescent(0), + mnLineHeight(-1), + meAdjust(style::ParagraphAdjust_LEFT), + mnWritingMode (text::WritingMode2::LR_TB), + mnCharacterOffset(0), + maCells() +{ + if (rxTextRange.is()) + { + Reference<beans::XPropertySet> xProperties (rxTextRange, UNO_QUERY); + lang::Locale aLocale; + try + { + xProperties->getPropertyValue(A2S("CharLocale")) >>= aLocale; + } + catch(beans::UnknownPropertyException&) + { + // Ignore the exception. Use the default value. + } + try + { + xProperties->getPropertyValue(A2S("ParaAdjust")) >>= meAdjust; + } + catch(beans::UnknownPropertyException&) + { + // Ignore the exception. Use the default value. + } + try + { + xProperties->getPropertyValue(A2S("WritingMode")) >>= mnWritingMode; + } + catch(beans::UnknownPropertyException&) + { + // Ignore the exception. Use the default value. + } + + msParagraphText = rxTextRange->getString(); + } +} + + + + +PresenterTextParagraph::PresenterTextParagraph ( + const sal_Int32 nParagraphIndex, + const Reference<i18n::XBreakIterator>& rxBreakIterator, + const Reference<i18n::XScriptTypeDetector>& rxScriptTypeDetector, + const ::rtl::OUString& rsText, + const SharedPresenterTextCaret& rpCaret) + : msParagraphText(rsText), + mnParagraphIndex(nParagraphIndex), + mpCaret(rpCaret), + mxBreakIterator(rxBreakIterator), + mxScriptTypeDetector(rxScriptTypeDetector), + maLines(), + mnVerticalOffset(0), + mnXOrigin(0), + mnYOrigin(0), + mnWidth(0), + mnAscent(0), + mnDescent(0), + mnLineHeight(-1), + meAdjust(style::ParagraphAdjust_LEFT), + mnWritingMode (text::WritingMode2::LR_TB), + mnCharacterOffset(0), + maCells() +{ +} + + + + +void PresenterTextParagraph::Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const geometry::RealSize2D& rSize, + const PresenterTheme::SharedFontDescriptor& rpFont, + const rendering::ViewState& rViewState, + rendering::RenderState& rRenderState, + const double nTopOffset, + const double nClipTop, + const double nClipBottom) +{ + if (mnLineHeight <= 0) + return; + + sal_Int8 nTextDirection (GetTextDirection()); + + const double nSavedM12 (rRenderState.AffineTransform.m12); + + if ( ! IsTextReferencePointLeft()) + rRenderState.AffineTransform.m02 += rSize.Width; + + +#ifdef SHOW_CHARACTER_BOXES + for (sal_Int32 nIndex=0,nCount=maLines.size(); + nIndex<nCount; + ++nIndex) + { + Line& rLine (maLines[nIndex]); + rLine.ProvideLayoutedLine(msParagraphText, rpFont, nTextDirection); + } +#endif + + for (sal_Int32 nIndex=0,nCount=maLines.size(); + nIndex<nCount; + ++nIndex, rRenderState.AffineTransform.m12 += mnLineHeight) + { + Line& rLine (maLines[nIndex]); + + // Paint only visible lines. + const double nLineTop = rLine.mnBaseLine - mnAscent - nTopOffset; + if (nLineTop + mnLineHeight< nClipTop) + continue; + else if (nLineTop > nClipBottom) + break; + rLine.ProvideLayoutedLine(msParagraphText, rpFont, nTextDirection); + + rRenderState.AffineTransform.m12 = nSavedM12 + rLine.mnBaseLine; + + rxCanvas->drawTextLayout ( + rLine.mxLayoutedLine, + rViewState, + rRenderState); + } + rRenderState.AffineTransform.m12 = nSavedM12; + + if ( ! IsTextReferencePointLeft()) + rRenderState.AffineTransform.m02 -= rSize.Width; +} + + + + +void PresenterTextParagraph::Format ( + const double nY, + const double nWidth, + const PresenterTheme::SharedFontDescriptor& rpFont) +{ + // Make sure that the text view is in a valid and sane state. + if ( ! mxBreakIterator.is() || ! mxScriptTypeDetector.is()) + return; + if (nWidth<=0) + return; + if ( ! rpFont || ! rpFont->mxFont.is()) + return; + + sal_Int32 nPosition (0); + + mnWidth = nWidth; + maLines.clear(); + mnLineHeight = 0; + mnAscent = 0; + mnDescent = 0; + mnVerticalOffset = nY; + maWordBoundaries.clear(); + maWordBoundaries.push_back(0); + + const rendering::FontMetrics aMetrics (rpFont->mxFont->getFontMetrics()); + mnAscent = aMetrics.Ascent; + mnDescent = aMetrics.Descent; + mnLineHeight = aMetrics.Ascent + aMetrics.Descent + aMetrics.ExternalLeading; + nPosition = 0; + i18n::Boundary aCurrentLine(0,0); + while (true) + { + const i18n::Boundary aWordBoundary = mxBreakIterator->nextWord( + msParagraphText, + nPosition, + lang::Locale(), + i18n::WordType::ANYWORD_IGNOREWHITESPACES); + AddWord(nWidth, aCurrentLine, aWordBoundary.startPos, rpFont); + + // Remember the new word boundary for caret travelling by words. + // Prevent duplicates. + if (aWordBoundary.startPos > maWordBoundaries.back()) + maWordBoundaries.push_back(aWordBoundary.startPos); + + if (aWordBoundary.endPos>aWordBoundary.startPos) + AddWord(nWidth, aCurrentLine, aWordBoundary.endPos, rpFont); + + if (aWordBoundary.startPos<0 || aWordBoundary.endPos<0) + break; + if (nPosition >= aWordBoundary.endPos) + break; + nPosition = aWordBoundary.endPos; + } + + if (aCurrentLine.endPos>aCurrentLine.startPos) + AddLine(aCurrentLine); + +} + + + + +sal_Int32 PresenterTextParagraph::GetWordBoundary( + const sal_Int32 nLocalCharacterIndex, + const sal_Int32 nDistance) +{ + OSL_ASSERT(nDistance==-1 || nDistance==+1); + + if (nLocalCharacterIndex < 0) + { + // The caller asked for the start or end position of the paragraph. + if (nDistance < 0) + return 0; + else + return GetCharacterCount(); + } + + sal_Int32 nIndex (0); + for (sal_Int32 nCount (maWordBoundaries.size()); nIndex<nCount; ++nIndex) + { + if (maWordBoundaries[nIndex] >= nLocalCharacterIndex) + { + // When inside the word (not at its start or end) then + // first move to the start or end before going the previous or + // next word. + if (maWordBoundaries[nIndex] > nLocalCharacterIndex) + if (nDistance > 0) + --nIndex; + break; + } + } + + nIndex += nDistance; + + if (nIndex < 0) + return -1; + else if (sal_uInt32(nIndex)>=maWordBoundaries.size()) + return -1; + else + return maWordBoundaries[nIndex]; +} + + + + +sal_Int32 PresenterTextParagraph::GetCaretPosition (void) const +{ + if (mpCaret && mpCaret->GetParagraphIndex()==mnParagraphIndex) + return mpCaret->GetCharacterIndex(); + else + return -1; +} + + + + +void PresenterTextParagraph::SetCaretPosition (const sal_Int32 nPosition) const +{ + if (mpCaret && mpCaret->GetParagraphIndex()==mnParagraphIndex) + return mpCaret->SetPosition(mnParagraphIndex, nPosition); +} + + + + +void PresenterTextParagraph::SetOrigin (const double nXOrigin, const double nYOrigin) +{ + mnXOrigin = nXOrigin; + mnYOrigin = nYOrigin; +} + + + + +awt::Point PresenterTextParagraph::GetRelativeLocation (void) const +{ + return awt::Point( + sal_Int32(mnXOrigin), + sal_Int32(mnYOrigin + mnVerticalOffset)); +} + + + + +awt::Size PresenterTextParagraph::GetSize (void) +{ + return awt::Size( + sal_Int32(mnWidth), + sal_Int32(GetTotalTextHeight())); +} + + + + +void PresenterTextParagraph::AddWord ( + const double nWidth, + i18n::Boundary& rCurrentLine, + const sal_Int32 nWordBoundary, + const PresenterTheme::SharedFontDescriptor& rpFont) +{ + sal_Int32 nLineStart (0); + if ( ! maLines.empty()) + nLineStart = rCurrentLine.startPos; + + const ::rtl::OUString sLineCandidate ( + msParagraphText.copy(nLineStart, nWordBoundary-nLineStart)); + + css::geometry::RealRectangle2D aLineBox ( + PresenterCanvasHelper::GetTextBoundingBox ( + rpFont->mxFont, + sLineCandidate, + mnWritingMode)); + const double nLineWidth (aLineBox.X2 - aLineBox.X1); + + if (nLineWidth >= nWidth) + { + // Add new line with a single word (so far). + AddLine(rCurrentLine); + } + rCurrentLine.endPos = nWordBoundary; +} + + + + +void PresenterTextParagraph::AddLine ( + i18n::Boundary& rCurrentLine) +{ + Line aLine (rCurrentLine.startPos, rCurrentLine.endPos); + + // Find the start and end of the line with respect to cells. + if (maLines.size() > 0) + { + aLine.mnLineStartCellIndex = maLines.back().mnLineEndCellIndex; + aLine.mnBaseLine = maLines.back().mnBaseLine + mnLineHeight; + } + else + { + aLine.mnLineStartCellIndex = 0; + aLine.mnBaseLine = mnVerticalOffset + mnAscent; + } + sal_Int32 nCellIndex (aLine.mnLineStartCellIndex); + double nWidth (0); + for ( ; nCellIndex<sal_Int32(maCells.size()); ++nCellIndex) + { + const Cell& rCell (maCells[nCellIndex]); + if (rCell.mnCharacterIndex+rCell.mnCharacterCount > aLine.mnLineEndCharacterIndex) + break; + nWidth += rCell.mnCellWidth; + } + aLine.mnLineEndCellIndex = nCellIndex; + aLine.mnWidth = nWidth; + + maLines.push_back(aLine); + + rCurrentLine.startPos = rCurrentLine.endPos; +} + + + + +sal_Int32 PresenterTextParagraph::GetParagraphIndex (void) const +{ + return mnParagraphIndex; +} + + + + +double PresenterTextParagraph::GetTotalTextHeight (void) +{ + return maLines.size() * mnLineHeight; +} + + + + +sal_Int32 PresenterTextParagraph::GetCharacterOffset (void) const +{ + return mnCharacterOffset; +} + + + + +void PresenterTextParagraph::SetCharacterOffset (const sal_Int32 nCharacterOffset) +{ + mnCharacterOffset = nCharacterOffset; +} + + + + +sal_Int32 PresenterTextParagraph::GetCharacterCount (void) const +{ + return msParagraphText.getLength(); +} + + + + +sal_Unicode PresenterTextParagraph::GetCharacter ( + const sal_Int32 nGlobalCharacterIndex) const +{ + if (nGlobalCharacterIndex<mnCharacterOffset + || nGlobalCharacterIndex>=mnCharacterOffset+msParagraphText.getLength()) + { + return sal_Unicode(); + } + else + { + return msParagraphText.getStr()[nGlobalCharacterIndex - mnCharacterOffset]; + } +} + + + + +::rtl::OUString PresenterTextParagraph::GetText (void) const +{ + return msParagraphText; +} + + + + +TextSegment PresenterTextParagraph::GetTextSegment ( + const sal_Int32 nOffset, + const sal_Int32 nIndex, + const sal_Int16 nTextType) const +{ + switch(nTextType) + { + case AccessibleTextType::PARAGRAPH: + return TextSegment( + msParagraphText, + mnCharacterOffset, + mnCharacterOffset+msParagraphText.getLength()); + + case AccessibleTextType::SENTENCE: + if (mxBreakIterator.is()) + { + const sal_Int32 nStart (mxBreakIterator->beginOfSentence( + msParagraphText, nIndex-mnCharacterOffset, lang::Locale())); + const sal_Int32 nEnd (mxBreakIterator->endOfSentence( + msParagraphText, nIndex-mnCharacterOffset, lang::Locale())); + if (nStart < nEnd) + return TextSegment( + msParagraphText.copy(nStart, nEnd-nStart), + nStart+mnCharacterOffset, + nEnd+mnCharacterOffset); + } + break; + + case AccessibleTextType::WORD: + if (mxBreakIterator.is()) + return GetWordTextSegment(nOffset, nIndex); + break; + + case AccessibleTextType::LINE: + { + for (::std::vector<Line>::const_iterator + iLine(maLines.begin()), + iEnd(maLines.end()); + iLine!=iEnd; + ++iLine) + { + if (nIndex < iLine->mnLineEndCharacterIndex) + { + return TextSegment( + msParagraphText.copy( + iLine->mnLineStartCharacterIndex, + iLine->mnLineEndCharacterIndex - iLine->mnLineStartCharacterIndex), + iLine->mnLineStartCharacterIndex, + iLine->mnLineEndCharacterIndex); + } + } + } + break; + + // Handle GLYPH and ATTRIBUTE_RUN like CHARACTER because we can not + // do better at the moment. + case AccessibleTextType::CHARACTER: + case AccessibleTextType::GLYPH: + case AccessibleTextType::ATTRIBUTE_RUN: + return CreateTextSegment(nIndex+nOffset, nIndex+nOffset+1); + } + + return TextSegment(::rtl::OUString(), 0,0); +} + + + + +TextSegment PresenterTextParagraph::GetWordTextSegment ( + const sal_Int32 nOffset, + const sal_Int32 nIndex) const +{ + sal_Int32 nCurrentOffset (nOffset); + sal_Int32 nCurrentIndex (nIndex); + + i18n::Boundary aWordBoundary; + if (nCurrentOffset == 0) + aWordBoundary = mxBreakIterator->getWordBoundary( + msParagraphText, + nIndex, + lang::Locale(), + i18n::WordType::ANYWORD_IGNOREWHITESPACES, + sal_True); + else if (nCurrentOffset < 0) + { + while (nCurrentOffset<0 && nCurrentIndex>0) + { + aWordBoundary = mxBreakIterator->previousWord( + msParagraphText, + nCurrentIndex, + lang::Locale(), + i18n::WordType::ANYWORD_IGNOREWHITESPACES); + nCurrentIndex = aWordBoundary.startPos; + ++nCurrentOffset; + } + } + else + { + while (nCurrentOffset>0 && nCurrentIndex<=GetCharacterCount()) + { + aWordBoundary = mxBreakIterator->nextWord( + msParagraphText, + nCurrentIndex, + lang::Locale(), + i18n::WordType::ANYWORD_IGNOREWHITESPACES); + nCurrentIndex = aWordBoundary.endPos; + --nCurrentOffset; + } + } + + return CreateTextSegment(aWordBoundary.startPos, aWordBoundary.endPos); +} + + + + +TextSegment PresenterTextParagraph::CreateTextSegment ( + sal_Int32 nStartIndex, + sal_Int32 nEndIndex) const +{ + if (nEndIndex <= nStartIndex) + return TextSegment( + ::rtl::OUString(), + nStartIndex, + nEndIndex); + else + return TextSegment( + msParagraphText.copy(nStartIndex, nEndIndex-nStartIndex), + nStartIndex, + nEndIndex); +} + + + + +awt::Rectangle PresenterTextParagraph::GetCharacterBounds ( + sal_Int32 nGlobalCharacterIndex, + const bool bCaretBox) +{ + // Find the line that contains the requested character and accumulate + // the previous line heights. + double nX (mnXOrigin); + double nY (mnYOrigin + mnVerticalOffset + mnAscent); + const sal_Int8 nTextDirection (GetTextDirection()); + for (sal_Int32 nLineIndex=0,nLineCount=maLines.size(); + nLineIndex<nLineCount; + ++nLineIndex, nY+=mnLineHeight) + { + Line& rLine (maLines[nLineIndex]); + // Skip lines before the indexed character. + if (nGlobalCharacterIndex >= rLine.mnLineEndCharacterIndex) + // When in the last line then allow the index past the last char. + if (nLineIndex<nLineCount-1) + continue; + + rLine.ProvideCellBoxes(); + + const sal_Int32 nCellIndex (nGlobalCharacterIndex - rLine.mnLineStartCharacterIndex); + + // The cell bounding box is defined relative to the origin of + // the current line. Therefore we have to add the absolute + // position of the line. + geometry::RealRectangle2D rCellBox (rLine.maCellBoxes[ + ::std::min(nCellIndex, rLine.maCellBoxes.getLength()-1)]); + + double nLeft = nX + rCellBox.X1; + double nRight = nX + rCellBox.X2; + if (nTextDirection == rendering::TextDirection::WEAK_RIGHT_TO_LEFT) + { + const double nOldRight (nRight); + nRight = rLine.mnWidth - nLeft; + nLeft = rLine.mnWidth - nOldRight; + } + double nTop (nY + rCellBox.Y1); + double nBottom (nY + rCellBox.Y2); + if (bCaretBox) + { + nTop = nTop - rCellBox.Y1 - mnAscent; + nBottom = nTop + mnLineHeight; + if (nCellIndex >= rLine.maCellBoxes.getLength()) + nLeft = nRight-2; + if (nLeft < nX) + nLeft = nX; + nRight = nLeft+2; + } + else + { + nTop = nTop - rCellBox.Y1 - mnAscent; + nBottom = nTop + mnAscent + mnDescent; + } + const sal_Int32 nX1 = sal_Int32(floor(nLeft)); + const sal_Int32 nY1 = sal_Int32(floor(nTop)); + const sal_Int32 nX2 = sal_Int32(ceil(nRight)); + const sal_Int32 nY2 = sal_Int32(ceil(nBottom)); + + return awt::Rectangle(nX1,nY1,nX2-nX1+1,nY2-nY1+1); + } + + // We are still here. That means that the given index lies past the + // last character in the paragraph. + // Return an empty box that lies past the last character. Better than nothing. + return awt::Rectangle(sal_Int32(nX+0.5), sal_Int32(nY+0.5), 0, 0); +} + + + + +sal_Int32 PresenterTextParagraph::GetIndexAtPoint (const awt::Point& rPoint) const +{ + (void)rPoint; + return -1; +} + + + + +sal_Int8 PresenterTextParagraph::GetTextDirection (void) const +{ + // Find first portion that has a non-neutral text direction. + sal_Int32 nPosition (0); + sal_Int32 nTextLength (msParagraphText.getLength()); + while (nPosition < nTextLength) + { + const sal_Int16 nScriptDirection ( + mxScriptTypeDetector->getScriptDirection( + msParagraphText, nPosition, i18n::ScriptDirection::NEUTRAL)); + switch (nScriptDirection) + { + case i18n::ScriptDirection::NEUTRAL: + // continue looping. + break; + case i18n::ScriptDirection::LEFT_TO_RIGHT: + return rendering::TextDirection::WEAK_LEFT_TO_RIGHT; + + case i18n::ScriptDirection::RIGHT_TO_LEFT: + return rendering::TextDirection::WEAK_RIGHT_TO_LEFT; + } + + nPosition = mxScriptTypeDetector->endOfScriptDirection( + msParagraphText, nPosition, nScriptDirection); + } + + // All text in paragraph is neutral. Fall back on writing mode taken + // from the XText (which may not be properly initialized.) + sal_Int8 nTextDirection(rendering::TextDirection::WEAK_LEFT_TO_RIGHT); + switch(mnWritingMode) + { + case text::WritingMode2::LR_TB: + nTextDirection = rendering::TextDirection::WEAK_LEFT_TO_RIGHT; + break; + + case text::WritingMode2::RL_TB: + nTextDirection = rendering::TextDirection::WEAK_RIGHT_TO_LEFT; + break; + + default: + case text::WritingMode2::TB_RL: + case text::WritingMode2::TB_LR: + // Can not handle this. Use default and hope for the best. + break; + } + return nTextDirection; +} + + + + +bool PresenterTextParagraph::IsTextReferencePointLeft (void) const +{ + return mnWritingMode != text::WritingMode2::RL_TB; +} + + + + +void PresenterTextParagraph::SetupCellArray ( + const PresenterTheme::SharedFontDescriptor& rpFont) +{ + maCells.clear(); + + if ( ! rpFont || ! rpFont->mxFont.is()) + return; + + sal_Int32 nPosition (0); + sal_Int32 nIndex (0); + const sal_Int32 nTextLength (msParagraphText.getLength()); + const sal_Int8 nTextDirection (GetTextDirection()); + while (nPosition < nTextLength) + { + const sal_Int32 nNewPosition (mxBreakIterator->nextCharacters( + msParagraphText, + nPosition, + lang::Locale(), + i18n::CharacterIteratorMode::SKIPCELL, + 1, + nIndex)); + + rendering::StringContext aContext (msParagraphText, nPosition, nNewPosition-nPosition); + Reference<rendering::XTextLayout> xLayout ( + rpFont->mxFont->createTextLayout(aContext, nTextDirection, 0)); + css::geometry::RealRectangle2D aCharacterBox (xLayout->queryTextBounds()); + + maCells.push_back(Cell( + nPosition, + nNewPosition-nPosition, + aCharacterBox.X2-aCharacterBox.X1)); + + nPosition = nNewPosition; + } +} + + + + +//===== PresenterTextCaret ================================================---- + +PresenterTextCaret::PresenterTextCaret ( + const ::boost::function<css::awt::Rectangle(const sal_Int32,const sal_Int32)>& rCharacterBoundsAccess, + const ::boost::function<void(const css::awt::Rectangle&)>& rInvalidator) + : mnParagraphIndex(-1), + mnCharacterIndex(-1), + mnCaretBlinkTaskId(0), + mbIsCaretVisible(false), + maCharacterBoundsAccess(rCharacterBoundsAccess), + maInvalidator(rInvalidator), + maBroadcaster(), + maCaretBounds() +{ +} + + + + +PresenterTextCaret::~PresenterTextCaret (void) +{ + HideCaret(); +} + + + + +void PresenterTextCaret::ShowCaret (void) +{ + if (mnCaretBlinkTaskId == 0) + { + mnCaretBlinkTaskId = PresenterTimer::ScheduleRepeatedTask ( + ::boost::bind(&PresenterTextCaret::InvertCaret, this), + CaretBlinkIntervall, + CaretBlinkIntervall); + } + mbIsCaretVisible = true; +} + + + + +void PresenterTextCaret::HideCaret (void) +{ + if (mnCaretBlinkTaskId != 0) + { + PresenterTimer::CancelTask(mnCaretBlinkTaskId); + mnCaretBlinkTaskId = 0; + } + mbIsCaretVisible = false; + // Reset the caret position. + mnParagraphIndex = -1; + mnCharacterIndex = -1; +} + + + + +sal_Int32 PresenterTextCaret::GetParagraphIndex (void) const +{ + return mnParagraphIndex; +} + + + + +sal_Int32 PresenterTextCaret::GetCharacterIndex (void) const +{ + return mnCharacterIndex; +} + + + + +void PresenterTextCaret::SetPosition ( + const sal_Int32 nParagraphIndex, + const sal_Int32 nCharacterIndex) +{ + if (mnParagraphIndex != nParagraphIndex + || mnCharacterIndex != nCharacterIndex) + { + if (mnParagraphIndex >= 0) + maInvalidator(maCaretBounds); + + const sal_Int32 nOldParagraphIndex (mnParagraphIndex); + const sal_Int32 nOldCharacterIndex (mnCharacterIndex); + mnParagraphIndex = nParagraphIndex; + mnCharacterIndex = nCharacterIndex; + maCaretBounds = maCharacterBoundsAccess(mnParagraphIndex, mnCharacterIndex); + if (mnParagraphIndex >= 0) + ShowCaret(); + else + HideCaret(); + + if (mnParagraphIndex >= 0) + maInvalidator(maCaretBounds); + + if (maBroadcaster) + maBroadcaster( + nOldParagraphIndex, + nOldCharacterIndex, + mnParagraphIndex, + mnCharacterIndex); + + } +} + + + + +bool PresenterTextCaret::IsVisible (void) const +{ + return mbIsCaretVisible; +} + + + + +void PresenterTextCaret::SetCaretMotionBroadcaster ( + const ::boost::function<void(sal_Int32,sal_Int32,sal_Int32,sal_Int32)>& rBroadcaster) +{ + maBroadcaster = rBroadcaster; +} + + + + +css::awt::Rectangle PresenterTextCaret::GetBounds (void) const +{ + return maCaretBounds; +} + + + + +void PresenterTextCaret::InvertCaret (void) +{ + mbIsCaretVisible = !mbIsCaretVisible; + if (mnParagraphIndex >= 0) + maInvalidator(maCaretBounds); +} + + + + + + + +//===== PresenterTextParagraph::Cell ========================================== + +PresenterTextParagraph::Cell::Cell ( + const sal_Int32 nCharacterIndex, + const sal_Int32 nCharacterCount, + const double nCellWidth) + : mnCharacterIndex(nCharacterIndex), + mnCharacterCount(nCharacterCount), + mnCellWidth(nCellWidth) +{ +} + + + + +//===== PresenterTextParagraph::Line ========================================== + +PresenterTextParagraph::Line::Line ( + const sal_Int32 nLineStartCharacterIndex, + const sal_Int32 nLineEndCharacterIndex) + : mnLineStartCharacterIndex(nLineStartCharacterIndex), + mnLineEndCharacterIndex(nLineEndCharacterIndex), + mnLineStartCellIndex(-1), mnLineEndCellIndex(-1), + mxLayoutedLine(), + mnBaseLine(0), mnWidth(0), + maCellBoxes() +{ +} + + + + +sal_Int32 PresenterTextParagraph::Line::GetLength (void) const +{ + return mnLineEndCharacterIndex-mnLineStartCharacterIndex; +} + + + + +void PresenterTextParagraph::Line::ProvideCellBoxes (void) +{ + if ( ! IsEmpty() && maCellBoxes.getLength()==0) + { + if (mxLayoutedLine.is()) + maCellBoxes = mxLayoutedLine->queryInkMeasures(); + else + { + OSL_ASSERT(mxLayoutedLine.is()); + } + } +} + + + + +void PresenterTextParagraph::Line::ProvideLayoutedLine ( + const ::rtl::OUString& rsParagraphText, + const PresenterTheme::SharedFontDescriptor& rpFont, + const sal_Int8 nTextDirection) +{ + if ( ! mxLayoutedLine.is()) + { + const rendering::StringContext aContext ( + rsParagraphText, + mnLineStartCharacterIndex, + mnLineEndCharacterIndex - mnLineStartCharacterIndex); + + mxLayoutedLine = rpFont->mxFont->createTextLayout( + aContext, + nTextDirection, + 0); + } +} + + + + +bool PresenterTextParagraph::Line::IsEmpty (void) const +{ + return mnLineStartCharacterIndex >= mnLineEndCharacterIndex; +} + + + + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterTextView.hxx b/sdext/source/presenter/PresenterTextView.hxx new file mode 100644 index 000000000000..d8bf260443c1 --- /dev/null +++ b/sdext/source/presenter/PresenterTextView.hxx @@ -0,0 +1,322 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_TEXT_VIEW_HXX +#define SDEXT_PRESENTER_TEXT_VIEW_HXX + +#include "PresenterTheme.hxx" +#include <com/sun/star/accessibility/XAccessibleText.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/geometry/RealPoint2D.hpp> +#include <com/sun/star/geometry/RealSize2D.hpp> +#include <com/sun/star/i18n/XBreakIterator.hpp> +#include <com/sun/star/i18n/XScriptTypeDetector.hpp> +#include <com/sun/star/rendering/XCanvas.hpp> +#include <com/sun/star/style/ParagraphAdjust.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/compbase1.hxx> +#include <cppuhelper/basemutex.hxx> + +namespace css = ::com::sun::star; +namespace cssu = ::com::sun::star::uno; +namespace cssa = ::com::sun::star::accessibility; + +namespace sdext { namespace presenter { + +class PresenterTextCaret +{ +public: + PresenterTextCaret ( + const ::boost::function<css::awt::Rectangle(const sal_Int32,const sal_Int32)>& + rCharacterBoundsAccess, + const ::boost::function<void(const css::awt::Rectangle&)>& + rInvalidator); + ~PresenterTextCaret (void); + + void ShowCaret (void); + void HideCaret (void); + + sal_Int32 GetParagraphIndex (void) const; + sal_Int32 GetCharacterIndex (void) const; + void SetPosition ( + const sal_Int32 nParagraphIndex, + const sal_Int32 nCharacterIndex); + + bool IsVisible (void) const; + + /** Set a (possibly empty) functor that broadcasts changes of the caret + position. This is used when a PresenterTextView object is set at + the accessibility object so that accessibility events can be sent + when the caret changes position. + */ + void SetCaretMotionBroadcaster ( + const ::boost::function<void(sal_Int32,sal_Int32,sal_Int32,sal_Int32)>& rBroadcaster); + + css::awt::Rectangle GetBounds (void) const; + +private: + sal_Int32 mnParagraphIndex; + sal_Int32 mnCharacterIndex; + sal_Int32 mnCaretBlinkTaskId; + bool mbIsCaretVisible; + const ::boost::function<css::awt::Rectangle(const sal_Int32,const sal_Int32)> maCharacterBoundsAccess; + const ::boost::function<void(const css::awt::Rectangle&)> maInvalidator; + ::boost::function<void(sal_Int32,sal_Int32,sal_Int32,sal_Int32)> maBroadcaster; + css::awt::Rectangle maCaretBounds; + + void InvertCaret (void); +}; +typedef ::boost::shared_ptr<PresenterTextCaret> SharedPresenterTextCaret; + + + + +//===== PresenterTextParagraph ================================================ + +class PresenterTextParagraph +{ +public: + PresenterTextParagraph ( + const sal_Int32 nParagraphIndex, + const cssu::Reference<css::i18n::XBreakIterator>& rxBreakIterator, + const cssu::Reference<css::i18n::XScriptTypeDetector>& rxScriptTypeDetector, + const cssu::Reference<css::text::XTextRange>& rxTextRange, + const SharedPresenterTextCaret& rpCaret); + PresenterTextParagraph ( + const sal_Int32 nParagraphIndex, + const cssu::Reference<css::i18n::XBreakIterator>& rxBreakIterator, + const cssu::Reference<css::i18n::XScriptTypeDetector>& rxScriptTypeDetector, + const ::rtl::OUString& rsText, + const SharedPresenterTextCaret& rpCaret); + + void Paint ( + const cssu::Reference<css::rendering::XCanvas>& rxCanvas, + const css::geometry::RealSize2D& rSize, + const PresenterTheme::SharedFontDescriptor& rpFont, + const css::rendering::ViewState& rViewState, + css::rendering::RenderState& rRenderState, + const double nTopOffset, + const double nClipTop, + const double nClipBottom); + + sal_Int32 GetParagraphIndex (void) const; + double GetTotalTextHeight (void); + + sal_Int32 GetCharacterOffset (void) const; + void SetCharacterOffset (const sal_Int32 nCharacterOffset); + sal_Int32 GetCharacterCount (void) const; + sal_Unicode GetCharacter (const sal_Int32 nGlobalCharacterIndex) const; + ::rtl::OUString GetText (void) const; + cssa::TextSegment GetTextSegment ( + const sal_Int32 nOffset, + const sal_Int32 nGlobalCharacterIndex, + const sal_Int16 nTextType) const; + cssa::TextSegment GetWordTextSegment ( + const sal_Int32 nOffset, + const sal_Int32 nIndex) const; + cssa::TextSegment CreateTextSegment ( + sal_Int32 nStartIndex, + sal_Int32 nEndIndex) const; + css::awt::Rectangle GetCharacterBounds ( + sal_Int32 nGlobalCharacterIndex, + const bool bCaretBox); + sal_Int32 GetIndexAtPoint (const css::awt::Point& rPoint) const; + void SetupCellArray ( + const PresenterTheme::SharedFontDescriptor& rpFont); + void Format ( + const double nY, + const double nWidth, + const PresenterTheme::SharedFontDescriptor& rpFont); + sal_Int32 GetWordBoundary( + const sal_Int32 nLocalCharacterIndex, + const sal_Int32 nDistance); + sal_Int32 GetCaretPosition (void) const; + void SetCaretPosition (const sal_Int32 nPosition) const; + void SetOrigin (const double nXOrigin, const double nYOrigin); + css::awt::Point GetRelativeLocation (void) const; + css::awt::Size GetSize (void); + +private: + ::rtl::OUString msParagraphText; + const sal_Int32 mnParagraphIndex; + SharedPresenterTextCaret mpCaret; + + /** A portion of a string that encodes one unicode cell. It describes + number of characters in the unicode string that make up the cell and its + width in pixel (with respect to some configuration that is stored + externally or implicitly). + */ + class Cell + { + public: + Cell (const sal_Int32 nCharacterIndex, const sal_Int32 nCharacterCount, const double nCellWidth); + sal_Int32 mnCharacterIndex; + sal_Int32 mnCharacterCount; + double mnCellWidth; + }; + + class Line + { + public: + Line (const sal_Int32 nLineStartCharacterIndex, const sal_Int32 nLineEndCharacterIndex); + sal_Int32 mnLineStartCharacterIndex; + sal_Int32 mnLineEndCharacterIndex; + sal_Int32 mnLineStartCellIndex; + sal_Int32 mnLineEndCellIndex; + cssu::Reference<css::rendering::XTextLayout> mxLayoutedLine; + double mnBaseLine; + double mnWidth; + cssu::Sequence<css::geometry::RealRectangle2D> maCellBoxes; + + sal_Int32 GetLength (void) const; + void ProvideLayoutedLine ( + const ::rtl::OUString& rsParagraphText, + const PresenterTheme::SharedFontDescriptor& rpFont, + const sal_Int8 nTextDirection); + void ProvideCellBoxes (void); + bool IsEmpty (void) const; + }; + + + cssu::Reference<css::i18n::XBreakIterator> mxBreakIterator; + cssu::Reference<css::i18n::XScriptTypeDetector> mxScriptTypeDetector; + ::std::vector<Line> maLines; + ::std::vector<sal_Int32> maWordBoundaries; + // Offset of the top of the paragraph with respect to the origin of the + // whole text (specified by mnXOrigin and mnYOrigin). + double mnVerticalOffset; + double mnXOrigin; + double mnYOrigin; + double mnWidth; + double mnAscent; + double mnDescent; + double mnLineHeight; + css::style::ParagraphAdjust meAdjust; + sal_Int8 mnWritingMode; + /// The index of the first character in this paragraph with respect to + /// the whole text. + sal_Int32 mnCharacterOffset; + ::std::vector<Cell> maCells; + + void AddWord ( + const double nWidth, + css::i18n::Boundary& rCurrentLine, + const sal_Int32 nWordBoundary, + const PresenterTheme::SharedFontDescriptor& rpFont); + void AddLine ( + css::i18n::Boundary& rCurrentLine); + sal_Int8 GetTextDirection (void) const; + bool IsTextReferencePointLeft (void) const; +}; +typedef ::boost::shared_ptr<PresenterTextParagraph> SharedPresenterTextParagraph; + + + + +/** A simple text view that paints text onto a given canvas. +*/ +class PresenterTextView +{ +public: + + PresenterTextView ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const ::boost::function<void(const ::css::awt::Rectangle&)>& rInvalidator); + /** Create a new instance that does no output but only provides + geometric information to an accessibility object. + */ + PresenterTextView ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas); + + void SetText (const css::uno::Reference<css::text::XText>& rxText); + void SetText (const ::rtl::OUString& rsText); + void SetTextChangeBroadcaster (const ::boost::function<void(void)>& rBroadcaster); + + void SetLocation (const css::geometry::RealPoint2D& rLocation); + void SetSize (const css::geometry::RealSize2D& rSize); + double GetTotalTextHeight (void); + + void SetFont (const PresenterTheme::SharedFontDescriptor& rpFont); + + void SetOffset ( + const double nLeft, + const double nTop); + + /** Move the caret forward or backward by character or by word. + @param nDistance + Should be either -1 or +1 to move caret backwards or forwards, + respectively. + @param nTextType + Valid values are the + com::sun::star::accessibility::AccessibleTextType constants. + */ + void MoveCaret ( + const sal_Int32 nDistance, + const sal_Int16 nTextType); + + void Paint (const css::awt::Rectangle& rUpdateBox); + + SharedPresenterTextCaret GetCaret (void) const; + + sal_Int32 GetParagraphCount (void) const; + SharedPresenterTextParagraph GetParagraph (const sal_Int32 nParagraphIndex) const; + +private: + css::uno::Reference<css::rendering::XCanvas> mxCanvas; + bool mbDoOuput; + css::uno::Reference<css::i18n::XBreakIterator> mxBreakIterator; + css::uno::Reference<css::i18n::XScriptTypeDetector> mxScriptTypeDetector; + css::geometry::RealPoint2D maLocation; + css::geometry::RealSize2D maSize; + PresenterTheme::SharedFontDescriptor mpFont; + ::std::vector<SharedPresenterTextParagraph> maParagraphs; + SharedPresenterTextCaret mpCaret; + double mnLeftOffset; + double mnTopOffset; + const ::boost::function<void(const ::css::awt::Rectangle&)> maInvalidator; + bool mbIsFormatPending; + sal_Int32 mnCharacterCount; + ::boost::function<void(void)> maTextChangeBroadcaster; + + void RequestFormat (void); + void Format (void); + SharedPresenterTextParagraph GetParagraphForCharacterIndex (const sal_Int32 nCharacterIndex) const; + sal_Int32 GetCharacterOffset (const sal_Int32 nParagraphIndex) const; + css::awt::Rectangle GetCaretBounds ( + const sal_Int32 nParagraphIndex, + const sal_Int32 nCharacterIndex) const; +}; + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterTheme.cxx b/sdext/source/presenter/PresenterTheme.cxx new file mode 100644 index 000000000000..6688f7e8b679 --- /dev/null +++ b/sdext/source/presenter/PresenterTheme.cxx @@ -0,0 +1,1417 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterTheme.hxx" +#include "PresenterBitmapContainer.hxx" +#include "PresenterCanvasHelper.hxx" +#include "PresenterComponent.hxx" +#include "PresenterConfigurationAccess.hxx" +#include "PresenterHelper.hxx" +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/beans/UnknownPropertyException.hpp> +#include <com/sun/star/deployment/XPackageInformationProvider.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/rendering/PanoseWeight.hpp> +#include <com/sun/star/rendering/XBitmap.hpp> +#include <com/sun/star/util/Color.hpp> +#include <boost/bind.hpp> +#include <map> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::std; +using ::rtl::OUString; + +#define A2S(s) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))) + +namespace sdext { namespace presenter { + +namespace { + +class BorderSize +{ +public: + const static sal_Int32 mnInvalidValue = -10000; + + BorderSize (void) : mnLeft(mnInvalidValue), + mnTop(mnInvalidValue), + mnRight(mnInvalidValue), + mnBottom(mnInvalidValue) {} + + sal_Int32 mnLeft; + sal_Int32 mnTop; + sal_Int32 mnRight; + sal_Int32 mnBottom; + + vector<sal_Int32> ToVector (void) + { + vector<sal_Int32> aSequence (4); + aSequence[0] = mnLeft == mnInvalidValue ? 0 : mnLeft; + aSequence[1] = mnTop == mnInvalidValue ? 0 : mnTop; + aSequence[2] = mnRight == mnInvalidValue ? 0 : mnRight; + aSequence[3] = mnBottom == mnInvalidValue ? 0 : mnBottom; + return aSequence; + }; + + + void Merge (const BorderSize& rBorderSize) + { + if (mnLeft == mnInvalidValue) + mnLeft = rBorderSize.mnLeft; + if (mnTop == mnInvalidValue) + mnTop = rBorderSize.mnTop; + if (mnRight == mnInvalidValue) + mnRight = rBorderSize.mnRight; + if (mnBottom == mnInvalidValue) + mnBottom = rBorderSize.mnBottom; + } +}; + + +/** Reading a theme from the configurations is done in various classes. The + ReadContext gives access to frequently used objects and functions to make + the configuration handling easier. +*/ +class ReadContext +{ +public: + Reference<XComponentContext> mxComponentContext; + Reference<rendering::XCanvas> mxCanvas; + Reference<drawing::XPresenterHelper> mxPresenterHelper; + OUString msBasePath; + + ReadContext ( + const Reference<XComponentContext>& rxContext, + const Reference<rendering::XCanvas>& rxCanvas); + ~ReadContext (void); + + /** Read data describing a font from the node that can be reached from + the given root via the given path. + @param rsFontPath + May be empty. + */ + static PresenterTheme::SharedFontDescriptor ReadFont ( + const css::uno::Reference<css::container::XHierarchicalNameAccess>& rxTheme, + const ::rtl::OUString& rsFontPath, + const PresenterTheme::SharedFontDescriptor& rpDefault); + static PresenterTheme::SharedFontDescriptor ReadFont ( + const Reference<beans::XPropertySet>& rxFontProperties, + const PresenterTheme::SharedFontDescriptor& rpDefault); + + ::boost::shared_ptr<PresenterTheme::Theme> ReadTheme ( + PresenterConfigurationAccess& rConfiguration, + const OUString& rsThemeName); + + BorderSize ReadBorderSize (const Reference<container::XNameAccess>& rxNode); + + void SetBitmapSourceExtension (const OUString& rsExtensionName); + +private: + Any GetByName ( + const Reference<container::XNameAccess>& rxNode, + const OUString& rsName) const; +}; + + + + +/** A PaneStyle describes how a pane is rendered. +*/ +class PaneStyle +{ +public: + PaneStyle (void); + ~PaneStyle (void); + + const SharedBitmapDescriptor GetBitmap (const OUString& sBitmapName) const; + + OUString msStyleName; + ::boost::shared_ptr<PaneStyle> mpParentStyle; + PresenterTheme::SharedFontDescriptor mpFont; + BorderSize maInnerBorderSize; + BorderSize maOuterBorderSize; + ::boost::shared_ptr<PresenterBitmapContainer> mpBitmaps; + + PresenterTheme::SharedFontDescriptor GetFont (void) const; + +private: + + void UpdateBorderSize (BorderSize& rBorderSize, bool bInner); +}; + +typedef ::boost::shared_ptr<PaneStyle> SharedPaneStyle; + + + + +class PaneStyleContainer : vector<SharedPaneStyle> +{ +public: + void Read ( + ReadContext& rReadContext, + const Reference<container::XHierarchicalNameAccess>& rThemeRoot); + + SharedPaneStyle GetPaneStyle (const OUString& rsStyleName) const; + +private: + void ProcessPaneStyle ( + ReadContext& rReadContext, + const ::rtl::OUString& rsKey, + const ::std::vector<css::uno::Any>& rValues); +}; + + + + +/** A ViewStyle describes how a view is displayed. +*/ +class ViewStyle +{ +public: + ViewStyle (void); + ~ViewStyle (void); + + const SharedBitmapDescriptor GetBitmap (const OUString& sBitmapName) const; + + PresenterTheme::SharedFontDescriptor GetFont (void) const; + + OUString msStyleName; + ::boost::shared_ptr<ViewStyle> mpParentStyle; + PresenterTheme::SharedFontDescriptor mpFont; + ::boost::shared_ptr<PresenterBitmapContainer> mpBitmaps; + SharedBitmapDescriptor mpBackground; +}; + +typedef ::boost::shared_ptr<ViewStyle> SharedViewStyle; + + + + +class ViewStyleContainer : vector<SharedViewStyle> +{ +public: + void Read ( + ReadContext& rReadContext, + const Reference<container::XHierarchicalNameAccess>& rThemeRoot); + + SharedViewStyle GetViewStyle (const OUString& rsStyleName) const; + +private: + void ProcessViewStyle( + ReadContext& rReadContext, + const Reference<beans::XPropertySet>& rxProperties); +}; + + + + +class ViewDescriptor +{ +}; +typedef ::boost::shared_ptr<ViewDescriptor> SharedViewDescriptor; +typedef ::std::vector<SharedViewDescriptor> ViewDescriptorContainer; + + + +class StyleAssociationContainer +{ +public: + void Read ( + ReadContext& rReadContext, + const Reference<container::XHierarchicalNameAccess>& rThemeRoot); + + OUString GetStyleName (const OUString& rsResourceName) const; + +private: + typedef map<OUString, OUString> StyleAssociations; + StyleAssociations maStyleAssociations; + + void ProcessStyleAssociation( + ReadContext& rReadContext, + const ::rtl::OUString& rsKey, + const ::std::vector<css::uno::Any>& rValues); +}; + +} // end of anonymous namespace + + +class PresenterTheme::Theme +{ +public: + Theme ( + const OUString& rsName, + const Reference<container::XHierarchicalNameAccess>& rThemeRoot, + const OUString& rsNodeName); + ~Theme (void); + + void Read ( + PresenterConfigurationAccess& rConfiguration, + ReadContext& rReadContext); + + OUString msThemeName; + OUString msConfigurationNodeName; + ::boost::shared_ptr<Theme> mpParentTheme; + SharedBitmapDescriptor mpBackground; + PaneStyleContainer maPaneStyles; + ViewStyleContainer maViewStyles; + ViewDescriptorContainer maViewDescriptors; + StyleAssociationContainer maStyleAssociations; + Reference<container::XHierarchicalNameAccess> mxThemeRoot; + ::boost::shared_ptr<PresenterBitmapContainer> mpIconContainer; + typedef map<rtl::OUString,SharedFontDescriptor> FontContainer; + FontContainer maFontContainer; + + SharedPaneStyle GetPaneStyle (const OUString& rsStyleName) const; + SharedViewStyle GetViewStyle (const OUString& rsStyleName) const; + +private: + void ProcessFont( + ReadContext& rReadContext, + const OUString& rsKey, + const Reference<beans::XPropertySet>& rxProperties); +}; + + + + +//===== PresenterTheme ======================================================== + +PresenterTheme::PresenterTheme ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const rtl::OUString& rsThemeName, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas) + : mxContext(rxContext), + msThemeName(rsThemeName), + mpTheme(), + mpBitmapContainer(), + mxCanvas(rxCanvas) +{ + mpTheme = ReadTheme(); +} + + + + +PresenterTheme::~PresenterTheme (void) +{ +} + + + + +void SAL_CALL PresenterTheme::disposing (void) +{ +} + + + + +::boost::shared_ptr<PresenterTheme::Theme> PresenterTheme::ReadTheme (void) +{ + ReadContext aReadContext(mxContext, mxCanvas); + + PresenterConfigurationAccess aConfiguration ( + mxContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.extension.PresenterScreen/")), + PresenterConfigurationAccess::READ_ONLY); + + return aReadContext.ReadTheme(aConfiguration, msThemeName); +} + + + + +bool PresenterTheme::HasCanvas (void) const +{ + return mxCanvas.is(); +} + + + + +void PresenterTheme::ProvideCanvas (const Reference<rendering::XCanvas>& rxCanvas) +{ + if ( ! mxCanvas.is() && rxCanvas.is()) + { + mxCanvas = rxCanvas; + ReadTheme(); + } +} + + + + +OUString PresenterTheme::GetStyleName (const ::rtl::OUString& rsResourceURL) const +{ + OUString sStyleName; + ::boost::shared_ptr<Theme> pTheme (mpTheme); + while (sStyleName.getLength()==0 && pTheme.get()!=NULL) + { + sStyleName = pTheme->maStyleAssociations.GetStyleName(rsResourceURL); + pTheme = pTheme->mpParentTheme; + } + return sStyleName; +} + + + + +::std::vector<sal_Int32> PresenterTheme::GetBorderSize ( + const ::rtl::OUString& rsStyleName, + const bool bOuter) const +{ + OSL_ASSERT(mpTheme.get() != NULL); + + SharedPaneStyle pPaneStyle (mpTheme->GetPaneStyle(rsStyleName)); + if (pPaneStyle.get() != NULL) + if (bOuter) + return pPaneStyle->maOuterBorderSize.ToVector(); + else + return pPaneStyle->maInnerBorderSize.ToVector(); + else + { + return ::std::vector<sal_Int32>(4,0); + } +} + + + + +PresenterTheme::SharedFontDescriptor PresenterTheme::ReadFont ( + const Reference<container::XHierarchicalNameAccess>& rxNode, + const OUString& rsFontPath, + const PresenterTheme::SharedFontDescriptor& rpDefault) +{ + return ReadContext::ReadFont(rxNode, rsFontPath, rpDefault); +} + + + + +bool PresenterTheme::ConvertToColor ( + const Any& rColorSequence, + sal_uInt32& rColor) +{ + Sequence<sal_Int8> aByteSequence; + if (rColorSequence >>= aByteSequence) + { + const sal_Int32 nByteCount (aByteSequence.getLength()); + const sal_uInt8* pArray = reinterpret_cast<const sal_uInt8*>(aByteSequence.getConstArray()); + rColor = 0; + for (sal_Int32 nIndex=0; nIndex<nByteCount; ++nIndex) + { + rColor = (rColor << 8) | *pArray++; + } + return true; + } + else + return false; +} + + + + +::boost::shared_ptr<PresenterConfigurationAccess> PresenterTheme::GetNodeForViewStyle ( + const ::rtl::OUString& rsStyleName, + const PresenterConfigurationAccess::WriteMode) const +{ + if (mpTheme.get() == NULL) + return ::boost::shared_ptr<PresenterConfigurationAccess>(); + + // Open configuration for writing. + ::boost::shared_ptr<PresenterConfigurationAccess> pConfiguration ( + new PresenterConfigurationAccess( + mxContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.extension.PresenterScreen/")), + PresenterConfigurationAccess::READ_WRITE)); + + // Get configuration node for the view style container of the current + // theme. + if (pConfiguration->GoToChild( + A2S("Presenter/Themes/") + mpTheme->msConfigurationNodeName + A2S("/ViewStyles"))) + { + pConfiguration->GoToChild( + ::boost::bind(&PresenterConfigurationAccess::IsStringPropertyEqual, + rsStyleName, + A2S("StyleName"), + _2)); + } + return pConfiguration; +} + + + + +::rtl::OUString PresenterTheme::GetThemeName (void) const +{ + if (mpTheme.get() != NULL) + return mpTheme->msThemeName; + else + return OUString(); +} + + + + +SharedBitmapDescriptor PresenterTheme::GetBitmap ( + const OUString& rsStyleName, + const OUString& rsBitmapName) const +{ + if (mpTheme.get() != NULL) + { + if (rsStyleName.getLength() == 0) + { + if (rsBitmapName == A2S("Background")) + { + ::boost::shared_ptr<Theme> pTheme (mpTheme); + while (pTheme.get()!=NULL && pTheme->mpBackground.get()==NULL) + pTheme = pTheme->mpParentTheme; + if (pTheme.get() != NULL) + return pTheme->mpBackground; + else + return SharedBitmapDescriptor(); + } + } + else + { + SharedPaneStyle pPaneStyle (mpTheme->GetPaneStyle(rsStyleName)); + if (pPaneStyle.get() != NULL) + { + SharedBitmapDescriptor pBitmap (pPaneStyle->GetBitmap(rsBitmapName)); + if (pBitmap.get() != NULL) + return pBitmap; + } + + SharedViewStyle pViewStyle (mpTheme->GetViewStyle(rsStyleName)); + if (pViewStyle.get() != NULL) + { + SharedBitmapDescriptor pBitmap (pViewStyle->GetBitmap(rsBitmapName)); + if (pBitmap.get() != NULL) + return pBitmap; + } + } + } + + return SharedBitmapDescriptor(); +} + + + + +SharedBitmapDescriptor PresenterTheme::GetBitmap ( + const OUString& rsBitmapName) const +{ + if (mpTheme.get() != NULL) + { + if (rsBitmapName == A2S("Background")) + { + ::boost::shared_ptr<Theme> pTheme (mpTheme); + while (pTheme.get()!=NULL && pTheme->mpBackground.get()==NULL) + pTheme = pTheme->mpParentTheme; + if (pTheme.get() != NULL) + return pTheme->mpBackground; + else + return SharedBitmapDescriptor(); + } + else + { + if (mpTheme->mpIconContainer.get() != NULL) + return mpTheme->mpIconContainer->GetBitmap(rsBitmapName); + } + } + + return SharedBitmapDescriptor(); +} + + + + +::boost::shared_ptr<PresenterBitmapContainer> PresenterTheme::GetBitmapContainer (void) const +{ + if (mpTheme.get() != NULL) + return mpTheme->mpIconContainer; + else + return ::boost::shared_ptr<PresenterBitmapContainer>(); +} + + + + +PresenterTheme::SharedFontDescriptor PresenterTheme::GetFont ( + const OUString& rsStyleName) const +{ + if (mpTheme.get() != NULL) + { + SharedPaneStyle pPaneStyle (mpTheme->GetPaneStyle(rsStyleName)); + if (pPaneStyle.get() != NULL) + return pPaneStyle->GetFont(); + + SharedViewStyle pViewStyle (mpTheme->GetViewStyle(rsStyleName)); + if (pViewStyle.get() != NULL) + return pViewStyle->GetFont(); + + ::boost::shared_ptr<Theme> pTheme (mpTheme); + while (pTheme.get() != NULL) + { + Theme::FontContainer::const_iterator iFont (pTheme->maFontContainer.find(rsStyleName)); + if (iFont != pTheme->maFontContainer.end()) + return iFont->second; + + pTheme = pTheme->mpParentTheme; + } + } + + return SharedFontDescriptor(); +} + + + + +//===== FontDescriptor ======================================================== + +PresenterTheme::FontDescriptor::FontDescriptor (void) + : msFamilyName(), + msStyleName(), + mnSize(12), + mnColor(0x00000000), + msAnchor(OUString(RTL_CONSTASCII_USTRINGPARAM("Left"))), + mnXOffset(0), + mnYOffset(0) +{ +} + + + + +PresenterTheme::FontDescriptor::FontDescriptor ( + const ::boost::shared_ptr<FontDescriptor>& rpDescriptor) + : msFamilyName(), + msStyleName(), + mnSize(12), + mnColor(0x00000000), + msAnchor(OUString(RTL_CONSTASCII_USTRINGPARAM("Left"))), + mnXOffset(0), + mnYOffset(0) +{ + if (rpDescriptor.get() != NULL) + { + msFamilyName = rpDescriptor->msFamilyName; + msStyleName = rpDescriptor->msStyleName; + mnSize = rpDescriptor->mnSize; + mnColor = rpDescriptor->mnColor; + msAnchor = rpDescriptor->msAnchor; + mnXOffset = rpDescriptor->mnXOffset; + mnYOffset = rpDescriptor->mnYOffset; + } +} + + + + +bool PresenterTheme::FontDescriptor::PrepareFont ( + const Reference<rendering::XCanvas>& rxCanvas) +{ + if (mxFont.is()) + return true; + + if ( ! rxCanvas.is()) + return false; + + + const double nCellSize (GetCellSizeForDesignSize(rxCanvas, mnSize)); + mxFont = CreateFont(rxCanvas, nCellSize); + + return mxFont.is(); +} + + + + +Reference<rendering::XCanvasFont> PresenterTheme::FontDescriptor::CreateFont ( + const Reference<rendering::XCanvas>& rxCanvas, + const double nCellSize) const +{ + rendering::FontRequest aFontRequest; + aFontRequest.FontDescription.FamilyName = msFamilyName; + if (msFamilyName.getLength() == 0) + aFontRequest.FontDescription.FamilyName = A2S("Tahoma"); + aFontRequest.FontDescription.StyleName = msStyleName; + aFontRequest.CellSize = nCellSize; + + // Make an attempt at translating the style name(s)into a corresponding + // font description. + if (msStyleName == A2S("Bold")) + aFontRequest.FontDescription.FontDescription.Weight = rendering::PanoseWeight::HEAVY; + + return rxCanvas->createFont( + aFontRequest, + Sequence<beans::PropertyValue>(), + geometry::Matrix2D(1,0,0,1)); +} + + + + +double PresenterTheme::FontDescriptor::GetCellSizeForDesignSize ( + const Reference<rendering::XCanvas>& rxCanvas, + const double nDesignSize) const +{ + // Use the given design size as initial value in calculating the cell + // size. + double nCellSize (nDesignSize); + + if ( ! rxCanvas.is()) + { + // We need the canvas to do the conversion. Return the design size, + // it is the our best guess in this circumstance. + return nDesignSize; + } + + Reference<rendering::XCanvasFont> xFont (CreateFont(rxCanvas, nCellSize)); + if ( ! xFont.is()) + return nDesignSize; + + geometry::RealRectangle2D aBox (PresenterCanvasHelper::GetTextBoundingBox (xFont, A2S("X"))); + + const double nAscent (-aBox.Y1); + const double nDescent (aBox.Y2); + const double nScale = (nAscent+nDescent) / nAscent; + return nDesignSize * nScale; +} + + + + +//===== Theme ================================================================= + +PresenterTheme::Theme::Theme ( + const OUString& rsName, + const Reference<container::XHierarchicalNameAccess>& rxThemeRoot, + const OUString& rsNodeName) + : msThemeName(rsName), + msConfigurationNodeName(rsNodeName), + mpParentTheme(), + maPaneStyles(), + maViewStyles(), + maStyleAssociations(), + mxThemeRoot(rxThemeRoot), + mpIconContainer() +{ +} + + + + +PresenterTheme::Theme::~Theme (void) +{ +} + + + + +void PresenterTheme::Theme::Read ( + PresenterConfigurationAccess& rConfiguration, + ReadContext& rReadContext) +{ + PresenterConfigurationAccess::GetConfigurationNode(mxThemeRoot, A2S("ThemeName")) + >>= msThemeName; + + // Parent theme name. + OUString sParentThemeName; + if ((PresenterConfigurationAccess::GetConfigurationNode(mxThemeRoot, A2S("ParentTheme")) + >>= sParentThemeName) + && sParentThemeName.getLength()>0) + { + mpParentTheme = rReadContext.ReadTheme(rConfiguration, sParentThemeName); + } + + // Read the extension that contains the bitmaps referenced in this + // theme. + OUString sBitmapSourceExtension; + if ((PresenterConfigurationAccess::GetConfigurationNode( + mxThemeRoot, A2S("BitmapSourceExtension")) >>= sBitmapSourceExtension) + && sBitmapSourceExtension.getLength()>0) + { + rReadContext.SetBitmapSourceExtension(sBitmapSourceExtension); + } + else + { + rReadContext.SetBitmapSourceExtension(PresenterComponent::gsExtensionIdentifier); + } + + // Background. + mpBackground = PresenterBitmapContainer::LoadBitmap( + mxThemeRoot, + A2S("Background"), + rReadContext.mxPresenterHelper, + rReadContext.msBasePath, + rReadContext.mxCanvas, + SharedBitmapDescriptor()); + + // Style associations. + maStyleAssociations.Read(rReadContext, mxThemeRoot); + + // Pane styles. + maPaneStyles.Read(rReadContext, mxThemeRoot); + + // View styles. + maViewStyles.Read(rReadContext, mxThemeRoot); + + // Read bitmaps. + mpIconContainer.reset( + new PresenterBitmapContainer( + Reference<container::XNameAccess>( + PresenterConfigurationAccess::GetConfigurationNode(mxThemeRoot, A2S("Bitmaps")), + UNO_QUERY), + mpParentTheme.get()!=NULL + ? mpParentTheme->mpIconContainer + : ::boost::shared_ptr<PresenterBitmapContainer>(), + rReadContext.mxComponentContext, + rReadContext.mxCanvas, + rReadContext.msBasePath)); + + // Read fonts. + Reference<container::XNameAccess> xFontNode( + PresenterConfigurationAccess::GetConfigurationNode(mxThemeRoot, A2S("Fonts")), + UNO_QUERY); + PresenterConfigurationAccess::ForAll( + xFontNode, + ::boost::bind(&PresenterTheme::Theme::ProcessFont, + this, ::boost::ref(rReadContext), _1, _2)); +} + + + + +SharedPaneStyle PresenterTheme::Theme::GetPaneStyle (const OUString& rsStyleName) const +{ + SharedPaneStyle pPaneStyle (maPaneStyles.GetPaneStyle(rsStyleName)); + if (pPaneStyle.get() != NULL) + return pPaneStyle; + else if (mpParentTheme.get() != NULL) + return mpParentTheme->GetPaneStyle(rsStyleName); + else + return SharedPaneStyle(); +} + + + + +SharedViewStyle PresenterTheme::Theme::GetViewStyle (const OUString& rsStyleName) const +{ + SharedViewStyle pViewStyle (maViewStyles.GetViewStyle(rsStyleName)); + if (pViewStyle.get() != NULL) + return pViewStyle; + else if (mpParentTheme.get() != NULL) + return mpParentTheme->GetViewStyle(rsStyleName); + else + return SharedViewStyle(); +} + + + + +void PresenterTheme::Theme::ProcessFont( + ReadContext& rReadContext, + const OUString& rsKey, + const Reference<beans::XPropertySet>& rxProperties) +{ + (void)rReadContext; + maFontContainer[rsKey] = ReadContext::ReadFont(rxProperties, SharedFontDescriptor()); +} + + + + +namespace { + +//===== ReadContext =========================================================== + +ReadContext::ReadContext ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const Reference<rendering::XCanvas>& rxCanvas) + : mxComponentContext(rxContext), + mxCanvas(rxCanvas), + mxPresenterHelper(), + msBasePath() +{ + Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager()); + if (xFactory.is()) + { + mxPresenterHelper = Reference<drawing::XPresenterHelper>( + xFactory->createInstanceWithContext( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.PresenterHelper")), + rxContext), + UNO_QUERY_THROW); + } + + // Get base path to bitmaps. + SetBitmapSourceExtension(PresenterComponent::gsExtensionIdentifier); +} + + + + +ReadContext::~ReadContext (void) +{ +} + + + + +PresenterTheme::SharedFontDescriptor ReadContext::ReadFont ( + const Reference<container::XHierarchicalNameAccess>& rxNode, + const OUString& rsFontPath, + const PresenterTheme::SharedFontDescriptor& rpDefault) +{ + if ( ! rxNode.is()) + return PresenterTheme::SharedFontDescriptor(); + + try + { + Reference<container::XHierarchicalNameAccess> xFont ( + PresenterConfigurationAccess::GetConfigurationNode( + rxNode, + rsFontPath), + UNO_QUERY_THROW); + + Reference<beans::XPropertySet> xProperties (xFont, UNO_QUERY_THROW); + return ReadFont(xProperties, rpDefault); + } + catch (Exception&) + { + OSL_ASSERT(false); + } + + return PresenterTheme::SharedFontDescriptor(); +} + + + + +PresenterTheme::SharedFontDescriptor ReadContext::ReadFont ( + const Reference<beans::XPropertySet>& rxProperties, + const PresenterTheme::SharedFontDescriptor& rpDefault) +{ + ::boost::shared_ptr<PresenterTheme::FontDescriptor> pDescriptor ( + new PresenterTheme::FontDescriptor(rpDefault)); + + PresenterConfigurationAccess::GetProperty(rxProperties, A2S("FamilyName")) >>= pDescriptor->msFamilyName; + PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Style")) >>= pDescriptor->msStyleName; + PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Size")) >>= pDescriptor->mnSize; + PresenterTheme::ConvertToColor( + PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Color")), + pDescriptor->mnColor); + PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Anchor")) >>= pDescriptor->msAnchor; + PresenterConfigurationAccess::GetProperty(rxProperties, A2S("XOffset")) >>= pDescriptor->mnXOffset; + PresenterConfigurationAccess::GetProperty(rxProperties, A2S("YOffset")) >>= pDescriptor->mnYOffset; + + return pDescriptor; +} + + + + +Any ReadContext::GetByName ( + const Reference<container::XNameAccess>& rxNode, + const OUString& rsName) const +{ + OSL_ASSERT(rxNode.is()); + if (rxNode->hasByName(rsName)) + return rxNode->getByName(rsName); + else + return Any(); +} + + + + +::boost::shared_ptr<PresenterTheme::Theme> ReadContext::ReadTheme ( + PresenterConfigurationAccess& rConfiguration, + const OUString& rsThemeName) +{ + ::boost::shared_ptr<PresenterTheme::Theme> pTheme; + + OUString sCurrentThemeName (rsThemeName); + if (sCurrentThemeName.getLength() == 0) + { + // No theme name given. Look up the CurrentTheme property. + rConfiguration.GetConfigurationNode(A2S("Presenter/CurrentTheme")) >>= sCurrentThemeName; + if (sCurrentThemeName.getLength() == 0) + { + // Still no name. Use "DefaultTheme". + sCurrentThemeName = A2S("DefaultTheme"); + } + } + + Reference<container::XNameAccess> xThemes ( + rConfiguration.GetConfigurationNode(A2S("Presenter/Themes")), + UNO_QUERY); + if (xThemes.is()) + { + // Iterate over all themes and search the one with the given name. + Sequence<OUString> aKeys (xThemes->getElementNames()); + for (sal_Int32 nItemIndex=0; nItemIndex<aKeys.getLength(); ++nItemIndex) + { + const OUString& rsKey (aKeys[nItemIndex]); + Reference<container::XHierarchicalNameAccess> xTheme ( + xThemes->getByName(rsKey), UNO_QUERY); + if (xTheme.is()) + { + OUString sThemeName; + PresenterConfigurationAccess::GetConfigurationNode(xTheme, A2S("ThemeName")) + >>= sThemeName; + if (sThemeName == sCurrentThemeName) + { + pTheme.reset(new PresenterTheme::Theme(sThemeName,xTheme,rsKey)); + break; + } + } + } + } + + if (pTheme.get() != NULL) + { + pTheme->Read(rConfiguration, *this); + } + + return pTheme; +} + + + + +BorderSize ReadContext::ReadBorderSize (const Reference<container::XNameAccess>& rxNode) +{ + BorderSize aBorderSize; + + if (rxNode.is()) + { + GetByName(rxNode, A2S("Left")) >>= aBorderSize.mnLeft; + GetByName(rxNode, A2S("Top")) >>= aBorderSize.mnTop; + GetByName(rxNode, A2S("Right")) >>= aBorderSize.mnRight; + GetByName(rxNode, A2S("Bottom")) >>= aBorderSize.mnBottom; + } + + return aBorderSize; +} + + + + +void ReadContext::SetBitmapSourceExtension (const OUString& rsExtensionIdentifier) +{ + // Get base path to bitmaps. + msBasePath = PresenterComponent::GetBasePath(mxComponentContext, rsExtensionIdentifier); +} + + + + +//===== PaneStyleContainer ==================================================== + +void PaneStyleContainer::Read ( + ReadContext& rReadContext, + const Reference<container::XHierarchicalNameAccess>& rxThemeRoot) +{ + Reference<container::XNameAccess> xPaneStyleList ( + PresenterConfigurationAccess::GetConfigurationNode( + rxThemeRoot, + A2S("PaneStyles")), + UNO_QUERY); + if (xPaneStyleList.is()) + { + ::std::vector<rtl::OUString> aProperties; + aProperties.reserve(6); + aProperties.push_back(A2S("StyleName")); + aProperties.push_back(A2S("ParentStyle")); + aProperties.push_back(A2S("TitleFont")); + aProperties.push_back(A2S("InnerBorderSize")); + aProperties.push_back(A2S("OuterBorderSize")); + aProperties.push_back(A2S("BorderBitmapList")); + PresenterConfigurationAccess::ForAll( + xPaneStyleList, + aProperties, + ::boost::bind(&PaneStyleContainer::ProcessPaneStyle, + this, ::boost::ref(rReadContext), _1, _2)); + } +} + + + + +void PaneStyleContainer::ProcessPaneStyle( + ReadContext& rReadContext, + const OUString& rsKey, + const ::std::vector<Any>& rValues) +{ + (void)rsKey; + + if (rValues.size() != 6) + return; + + ::boost::shared_ptr<PaneStyle> pStyle (new PaneStyle()); + + rValues[0] >>= pStyle->msStyleName; + + OUString sParentStyleName; + if (rValues[1] >>= sParentStyleName) + { + // Find parent style. + PaneStyleContainer::const_iterator iStyle; + for (iStyle=begin(); iStyle!=end(); ++iStyle) + if ((*iStyle)->msStyleName.equals(sParentStyleName)) + { + pStyle->mpParentStyle = *iStyle; + break; + } + } + + Reference<container::XHierarchicalNameAccess> xFontNode (rValues[2], UNO_QUERY); + pStyle->mpFont = rReadContext.ReadFont( + xFontNode, A2S(""), PresenterTheme::SharedFontDescriptor()); + + Reference<container::XNameAccess> xInnerBorderSizeNode (rValues[3], UNO_QUERY); + pStyle->maInnerBorderSize = rReadContext.ReadBorderSize(xInnerBorderSizeNode); + Reference<container::XNameAccess> xOuterBorderSizeNode (rValues[4], UNO_QUERY); + pStyle->maOuterBorderSize = rReadContext.ReadBorderSize(xOuterBorderSizeNode); + + if (pStyle->mpParentStyle.get() != NULL) + { + pStyle->maInnerBorderSize.Merge(pStyle->mpParentStyle->maInnerBorderSize); + pStyle->maOuterBorderSize.Merge(pStyle->mpParentStyle->maOuterBorderSize); + } + + if (rReadContext.mxCanvas.is()) + { + Reference<container::XNameAccess> xBitmapsNode (rValues[5], UNO_QUERY); + pStyle->mpBitmaps.reset(new PresenterBitmapContainer( + xBitmapsNode, + pStyle->mpParentStyle.get()!=NULL + ? pStyle->mpParentStyle->mpBitmaps + : ::boost::shared_ptr<PresenterBitmapContainer>(), + rReadContext.mxComponentContext, + rReadContext.mxCanvas, + rReadContext.msBasePath, + rReadContext.mxPresenterHelper)); + } + + push_back(pStyle); +} + + + + +SharedPaneStyle PaneStyleContainer::GetPaneStyle (const OUString& rsStyleName) const +{ + const_iterator iEnd (end()); + for (const_iterator iStyle=begin(); iStyle!=iEnd; ++iStyle) + if ((*iStyle)->msStyleName == rsStyleName) + return *iStyle; + return SharedPaneStyle(); +} + + + + +//===== PaneStyle ============================================================= + +PaneStyle::PaneStyle (void) + : msStyleName(), + mpParentStyle(), + mpFont(), + maInnerBorderSize(), + maOuterBorderSize(), + mpBitmaps() +{ +} + + + + +PaneStyle::~PaneStyle (void) +{ +} + + + + +void PaneStyle::UpdateBorderSize (BorderSize& rBorderSize, bool bInner) +{ + if (mpParentStyle.get() != NULL) + mpParentStyle->UpdateBorderSize(rBorderSize, bInner); + + BorderSize& rThisBorderSize (bInner ? maInnerBorderSize : maOuterBorderSize); + if (rThisBorderSize.mnLeft >= 0) + rBorderSize.mnLeft = rThisBorderSize.mnLeft; + if (rThisBorderSize.mnTop >= 0) + rBorderSize.mnTop = rThisBorderSize.mnTop; + if (rThisBorderSize.mnRight >= 0) + rBorderSize.mnRight = rThisBorderSize.mnRight; + if (rThisBorderSize.mnBottom >= 0) + rBorderSize.mnBottom = rThisBorderSize.mnBottom; +} + + + + +const SharedBitmapDescriptor PaneStyle::GetBitmap (const OUString& rsBitmapName) const +{ + if (mpBitmaps.get() != NULL) + { + const SharedBitmapDescriptor pBitmap = mpBitmaps->GetBitmap(rsBitmapName); + if (pBitmap.get() != NULL) + return pBitmap; + } + + if (mpParentStyle.get() != NULL) + return mpParentStyle->GetBitmap(rsBitmapName); + else + return SharedBitmapDescriptor(); +} + + + + +PresenterTheme::SharedFontDescriptor PaneStyle::GetFont (void) const +{ + if (mpFont.get() != NULL) + return mpFont; + else if (mpParentStyle.get() != NULL) + return mpParentStyle->GetFont(); + else + return PresenterTheme::SharedFontDescriptor(); +} + + + + +//===== ViewStyleContainer ==================================================== + +void ViewStyleContainer::Read ( + ReadContext& rReadContext, + const Reference<container::XHierarchicalNameAccess>& rxThemeRoot) +{ + (void)rReadContext; + + Reference<container::XNameAccess> xViewStyleList ( + PresenterConfigurationAccess::GetConfigurationNode( + rxThemeRoot, + A2S("ViewStyles")), + UNO_QUERY); + if (xViewStyleList.is()) + { + PresenterConfigurationAccess::ForAll( + xViewStyleList, + ::boost::bind(&ViewStyleContainer::ProcessViewStyle, + this, ::boost::ref(rReadContext), _2)); + } +} + + + + +void ViewStyleContainer::ProcessViewStyle( + ReadContext& rReadContext, + const Reference<beans::XPropertySet>& rxProperties) +{ + ::boost::shared_ptr<ViewStyle> pStyle (new ViewStyle()); + + PresenterConfigurationAccess::GetProperty(rxProperties, A2S("StyleName")) + >>= pStyle->msStyleName; + + OUString sParentStyleName; + if (PresenterConfigurationAccess::GetProperty(rxProperties, A2S("ParentStyle")) + >>= sParentStyleName) + { + // Find parent style. + ViewStyleContainer::const_iterator iStyle; + for (iStyle=begin(); iStyle!=end(); ++iStyle) + if ((*iStyle)->msStyleName.equals(sParentStyleName)) + { + pStyle->mpParentStyle = *iStyle; + pStyle->mpFont = (*iStyle)->mpFont; + pStyle->mpBackground = (*iStyle)->mpBackground; + break; + } + } + + const OUString sPathToFont; // empty string + Reference<container::XHierarchicalNameAccess> xFontNode ( + PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Font")), UNO_QUERY); + PresenterTheme::SharedFontDescriptor pFont ( + rReadContext.ReadFont(xFontNode, sPathToFont, PresenterTheme::SharedFontDescriptor())); + if (pFont.get() != NULL) + pStyle->mpFont = pFont; + + Reference<container::XHierarchicalNameAccess> xBackgroundNode ( + PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Background")), + UNO_QUERY); + SharedBitmapDescriptor pBackground (PresenterBitmapContainer::LoadBitmap( + xBackgroundNode, + OUString(), + rReadContext.mxPresenterHelper, + rReadContext.msBasePath, + rReadContext.mxCanvas, + SharedBitmapDescriptor())); + if (pBackground.get() != NULL && pBackground->GetNormalBitmap().is()) + pStyle->mpBackground = pBackground; + + push_back(pStyle); +} + + + + +SharedViewStyle ViewStyleContainer::GetViewStyle (const OUString& rsStyleName) const +{ + const_iterator iEnd (end()); + for (const_iterator iStyle=begin(); iStyle!=iEnd; ++iStyle) + if ((*iStyle)->msStyleName == rsStyleName) + return *iStyle; + return SharedViewStyle(); +} + + + + +//===== ViewStyle ============================================================= + +ViewStyle::ViewStyle (void) + : msStyleName(), + mpParentStyle(), + mpFont(), + mpBackground() +{ +} + + + + +ViewStyle::~ViewStyle (void) +{ +} + + + + +const SharedBitmapDescriptor ViewStyle::GetBitmap (const OUString& rsBitmapName) const +{ + if (rsBitmapName == A2S("Background")) + return mpBackground; + else + return SharedBitmapDescriptor(); +} + + + + +PresenterTheme::SharedFontDescriptor ViewStyle::GetFont (void) const +{ + if (mpFont.get() != NULL) + return mpFont; + else if (mpParentStyle.get() != NULL) + return mpParentStyle->GetFont(); + else + return PresenterTheme::SharedFontDescriptor(); +} + + + + +//===== StyleAssociationContainer ============================================= + +void StyleAssociationContainer::Read ( + ReadContext& rReadContext, + const Reference<container::XHierarchicalNameAccess>& rxThemeRoot) +{ + Reference<container::XNameAccess> xStyleAssociationList ( + PresenterConfigurationAccess::GetConfigurationNode( + rxThemeRoot, + A2S("StyleAssociations")), + UNO_QUERY); + if (xStyleAssociationList.is()) + { + ::std::vector<rtl::OUString> aProperties (2); + aProperties[0] = A2S("ResourceURL"); + aProperties[1] = A2S("StyleName"); + PresenterConfigurationAccess::ForAll( + xStyleAssociationList, + aProperties, + ::boost::bind(&StyleAssociationContainer::ProcessStyleAssociation, + this, ::boost::ref(rReadContext), _1, _2)); + } +} + + + + +OUString StyleAssociationContainer::GetStyleName (const OUString& rsResourceName) const +{ + StyleAssociations::const_iterator iAssociation (maStyleAssociations.find(rsResourceName)); + if (iAssociation != maStyleAssociations.end()) + return iAssociation->second; + else + return OUString(); +} + + + + +void StyleAssociationContainer::ProcessStyleAssociation( + ReadContext& rReadContext, + const OUString& rsKey, + const ::std::vector<Any>& rValues) +{ + (void)rReadContext; + (void)rsKey; + + if (rValues.size() != 2) + return; + + OUString sResourceURL; + OUString sStyleName; + if ((rValues[0] >>= sResourceURL) + && (rValues[1] >>= sStyleName)) + { + maStyleAssociations[sResourceURL] = sStyleName; + } +} + + + + +} // end of anonymous namespace + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterTheme.hxx b/sdext/source/presenter/PresenterTheme.hxx new file mode 100644 index 000000000000..e76cabcf28d0 --- /dev/null +++ b/sdext/source/presenter/PresenterTheme.hxx @@ -0,0 +1,160 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_THEME_HXX +#define SDEXT_PRESENTER_PRESENTER_THEME_HXX + +#include "PresenterBitmapContainer.hxx" +#include "PresenterConfigurationAccess.hxx" +#include "PresenterTheme.hxx" +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/rendering/XCanvas.hpp> +#include <com/sun/star/rendering/XCanvasFont.hpp> +#include <com/sun/star/rendering/XIntegerBitmap.hpp> +#include <com/sun/star/util/Color.hpp> +#include <boost/shared_ptr.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +/** A theme is a set of properties describing fonts, colors, and bitmaps to be used to draw + background, pane borders, and view content. + + At the moment the properties can be accessed via the getPropertyValue() method. + + For a resource URL of a pane or a view you get the name of the + associated PaneStyle or ViewStyle. + + For the name of pane or view style suffixed with and underscore and the + name of configuration property, and maybe additionally suffixed by + another underscore and sub property name you get the associated + property. + + Example: you want to access the top left bitmap of a pane border + (simplified code): + + String sStyleName = getPropertyValue("private:resource/pane/Presenter/Pane1"); + XBitmap xBitmap = getPropertyValue(sStyleName + "_TopLeftBitmap"); + + For the offset of the bitmap you can call + Point aOffset = getPropertyValue(sStyleName + "_TopLeftOffset"); + + This is work in progress. +*/ +class PresenterTheme +{ +public: + PresenterTheme ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const rtl::OUString& rsThemeName, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas); + ~PresenterTheme (void); + + void SAL_CALL disposing (void); + + bool HasCanvas (void) const; + void ProvideCanvas (const css::uno::Reference<css::rendering::XCanvas>& rxCanvas); + + ::rtl::OUString GetStyleName (const ::rtl::OUString& rsResourceURL) const; + ::std::vector<sal_Int32> GetBorderSize ( + const ::rtl::OUString& rsStyleName, + const bool bOuter) const; + + class FontDescriptor; + class Theme; + + class FontDescriptor + { + public: + explicit FontDescriptor (void); + explicit FontDescriptor (const ::boost::shared_ptr<FontDescriptor>& rpDescriptor); + + ::rtl::OUString msFamilyName; + ::rtl::OUString msStyleName; + sal_Int32 mnSize; + sal_uInt32 mnColor; + ::rtl::OUString msAnchor; + sal_Int32 mnXOffset; + sal_Int32 mnYOffset; + css::uno::Reference<css::rendering::XCanvasFont> mxFont; + + bool PrepareFont (const css::uno::Reference<css::rendering::XCanvas>& rxCanvas); + + private: + css::uno::Reference<css::rendering::XCanvasFont> CreateFont ( + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const double nCellSize) const; + double GetCellSizeForDesignSize ( + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const double nDesignSize) const; + }; + typedef ::boost::shared_ptr<FontDescriptor> SharedFontDescriptor; + + ::rtl::OUString GetThemeName (void) const; + + SharedBitmapDescriptor GetBitmap ( + const ::rtl::OUString& rsStyleName, + const ::rtl::OUString& rsBitmapName) const; + + SharedBitmapDescriptor GetBitmap ( + const ::rtl::OUString& rsBitmapName) const; + + ::boost::shared_ptr<PresenterBitmapContainer> GetBitmapContainer (void) const; + + SharedFontDescriptor GetFont ( + const ::rtl::OUString& rsStyleName) const; + + static SharedFontDescriptor ReadFont ( + const css::uno::Reference<css::container::XHierarchicalNameAccess>& rxNode, + const ::rtl::OUString& rsFontPath, + const SharedFontDescriptor& rDefaultFount); + + static bool ConvertToColor ( + const css::uno::Any& rColorSequence, + sal_uInt32& rColor); + + ::boost::shared_ptr<PresenterConfigurationAccess> GetNodeForViewStyle ( + const ::rtl::OUString& rsStyleName, + const PresenterConfigurationAccess::WriteMode) const; + +private: + css::uno::Reference<css::uno::XComponentContext> mxContext; + const ::rtl::OUString msThemeName; + ::boost::shared_ptr<Theme> mpTheme; + ::boost::shared_ptr<PresenterBitmapContainer> mpBitmapContainer; + css::uno::Reference<css::rendering::XCanvas> mxCanvas; + + ::boost::shared_ptr<Theme> ReadTheme (void); +}; + +} } // end of namespace ::sd::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterTimer.cxx b/sdext/source/presenter/PresenterTimer.cxx new file mode 100644 index 000000000000..f4a5618353c9 --- /dev/null +++ b/sdext/source/presenter/PresenterTimer.cxx @@ -0,0 +1,681 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterTimer.hxx" +#include <osl/doublecheckedlocking.h> +#include <osl/thread.hxx> +#include <boost/bind.hpp> +#include <boost/function.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <set> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) + +namespace sdext { namespace presenter { + +namespace { +class TimerTask +{ +public: + TimerTask ( + const PresenterTimer::Task& rTask, + const TimeValue& rDueTime, + const sal_Int64 nRepeatIntervall, + const sal_Int32 nTaskId); + ~TimerTask (void) {} + + PresenterTimer::Task maTask; + TimeValue maDueTime; + const sal_Int64 mnRepeatIntervall; + const sal_Int32 mnTaskId; + bool mbIsCanceled; +}; + +typedef ::boost::shared_ptr<TimerTask> SharedTimerTask; + + +class TimerTaskComparator +{ +public: + bool operator() (const SharedTimerTask& rpTask1, const SharedTimerTask& rpTask2) const + { + return rpTask1->maDueTime.Seconds < rpTask2->maDueTime.Seconds + || (rpTask1->maDueTime.Seconds == rpTask2->maDueTime.Seconds + && rpTask1->maDueTime.Nanosec < rpTask2->maDueTime.Nanosec); + } +}; + + + + +/** Queue all scheduled tasks and process them when their time has come. +*/ +class TimerScheduler + : public ::boost::enable_shared_from_this<TimerScheduler>, + public ::osl::Thread +{ +public: + static ::boost::shared_ptr<TimerScheduler> Instance (void); + static SharedTimerTask CreateTimerTask ( + const PresenterTimer::Task& rTask, + const TimeValue& rDueTime, + const sal_Int64 nRepeatIntervall); + + void ScheduleTask (const SharedTimerTask& rpTask); + void CancelTask (const sal_Int32 nTaskId); + + static bool GetCurrentTime (TimeValue& rCurrentTime); + static sal_Int64 GetTimeDifference ( + const TimeValue& rTargetTime, + const TimeValue& rCurrentTime); + static void ConvertToTimeValue ( + TimeValue& rTimeValue, + const sal_Int64 nTimeDifference); + static sal_Int64 ConvertFromTimeValue ( + const TimeValue& rTimeValue); + +private: + static ::boost::shared_ptr<TimerScheduler> mpInstance; + static ::osl::Mutex maInstanceMutex; + static sal_Int32 mnTaskId; + + ::osl::Mutex maTaskContainerMutex; + typedef ::std::set<SharedTimerTask,TimerTaskComparator> TaskContainer; + TaskContainer maScheduledTasks; + bool mbIsRunning; + ::osl::Mutex maCurrentTaskMutex; + SharedTimerTask mpCurrentTask; + + static void Release (void); + + TimerScheduler (void); + virtual ~TimerScheduler (void); + class Deleter {public: void operator () (TimerScheduler* pScheduler) { delete pScheduler; } }; + friend class Deleter; + + virtual void SAL_CALL run (void); + virtual void SAL_CALL onTerminated (void); +}; + + + + +bool GetDateTime (oslDateTime& rDateTime); +} // end of anonymous namespace + + +//===== PresenterTimer ======================================================== + +sal_Int32 PresenterTimer::ScheduleSingleTaskRelative ( + const Task& rTask, + const sal_Int64 nDelay) +{ + return ScheduleRepeatedTask(rTask, nDelay, 0); +} + + + + +sal_Int32 PresenterTimer::ScheduleSingleTaskAbsolute ( + const Task& rTask, + const TimeValue& rDueTime) +{ + SharedTimerTask pTask (TimerScheduler::CreateTimerTask(rTask, rDueTime, 0)); + TimerScheduler::Instance()->ScheduleTask(pTask); + return pTask->mnTaskId; +} + + + + +sal_Int32 PresenterTimer::ScheduleRepeatedTask ( + const Task& rTask, + const sal_Int64 nDelay, + const sal_Int64 nIntervall) +{ + TimeValue aCurrentTime; + if (TimerScheduler::GetCurrentTime(aCurrentTime)) + { + TimeValue aDueTime; + TimerScheduler::ConvertToTimeValue( + aDueTime, + TimerScheduler::ConvertFromTimeValue (aCurrentTime) + nDelay); + SharedTimerTask pTask (TimerScheduler::CreateTimerTask(rTask, aDueTime, nIntervall)); + TimerScheduler::Instance()->ScheduleTask(pTask); + return pTask->mnTaskId; + } + + return NotAValidTaskId; +} + + + + +void PresenterTimer::CancelTask (const sal_Int32 nTaskId) +{ + return TimerScheduler::Instance()->CancelTask(nTaskId); +} + + + + +//===== TimerScheduler ======================================================== + +::boost::shared_ptr<TimerScheduler> TimerScheduler::mpInstance; +::osl::Mutex TimerScheduler::maInstanceMutex; +sal_Int32 TimerScheduler::mnTaskId = PresenterTimer::NotAValidTaskId; + +::boost::shared_ptr<TimerScheduler> TimerScheduler::Instance (void) +{ + ::boost::shared_ptr<TimerScheduler> pInstance = mpInstance; + if (pInstance.get() == NULL) + { + ::osl::MutexGuard aGuard (maInstanceMutex); + pInstance = mpInstance; + if (pInstance.get() == NULL) + { + pInstance.reset(new TimerScheduler(), TimerScheduler::Deleter()); + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + mpInstance = pInstance; + } + } + else + { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + return pInstance; +} + + + + +void TimerScheduler::Release (void) +{ + ::osl::MutexGuard aGuard (maInstanceMutex); + mpInstance.reset(); +} + + + + +TimerScheduler::TimerScheduler (void) + : maTaskContainerMutex(), + maScheduledTasks(), + mbIsRunning(false), + maCurrentTaskMutex(), + mpCurrentTask() +{ +} + + + + +TimerScheduler::~TimerScheduler (void) +{ +} + + + +SharedTimerTask TimerScheduler::CreateTimerTask ( + const PresenterTimer::Task& rTask, + const TimeValue& rDueTime, + const sal_Int64 nRepeatIntervall) +{ + return SharedTimerTask(new TimerTask(rTask, rDueTime, nRepeatIntervall, ++mnTaskId)); +} + + + + +void TimerScheduler::ScheduleTask (const SharedTimerTask& rpTask) +{ + if (rpTask.get() == NULL) + return; + if (rpTask->mbIsCanceled) + return; + + osl::MutexGuard aGuard (maTaskContainerMutex); + maScheduledTasks.insert(rpTask); + + if ( ! mbIsRunning) + { + mbIsRunning = true; + create(); + } +} + + + + +void TimerScheduler::CancelTask (const sal_Int32 nTaskId) +{ + // Set of scheduled tasks is sorted after their due times, not their + // task ids. Therefore we have to do a linear search for the task to + // cancel. + { + ::osl::MutexGuard aGuard (maTaskContainerMutex); + TaskContainer::iterator iTask (maScheduledTasks.begin()); + TaskContainer::const_iterator iEnd (maScheduledTasks.end()); + for ( ; iTask!=iEnd; ++iTask) + { + if ((*iTask)->mnTaskId == nTaskId) + { + maScheduledTasks.erase(iTask); + break; + } + } + } + + // The task that is to be canceled may be currently about to be + // processed. Mark it with a flag that a) prevents a repeating task + // from being scheduled again and b) tries to prevent its execution. + if (mpCurrentTask.get() != NULL + && mpCurrentTask->mnTaskId == nTaskId) + { + mpCurrentTask->mbIsCanceled = true; + } + + // When the last active task was canceled then the timer can be + // stopped. + if (maScheduledTasks.size() == 0) + { + mbIsRunning = false; + resume(); + // join(); + } +} + + + + +void SAL_CALL TimerScheduler::run (void) +{ + while (mbIsRunning) + { + // Get the current time. + TimeValue aCurrentTime; + if ( ! GetCurrentTime(aCurrentTime)) + { + // We can not get the current time and thus can not schedule anything. + break; + } + + // Restrict access to the maScheduledTasks member to one, mutext + // guarded, block. + SharedTimerTask pTask; + sal_Int64 nDifference = 0; + { + ::osl::MutexGuard aGuard (maTaskContainerMutex); + + // There are no more scheduled task. Leave this loop, function and + // live of the TimerScheduler. + if (maScheduledTasks.empty()) + break; + + nDifference = GetTimeDifference( + (*maScheduledTasks.begin())->maDueTime, + aCurrentTime); + if (nDifference <= 0) + { + pTask = *maScheduledTasks.begin(); + maScheduledTasks.erase(maScheduledTasks.begin()); + } + } + + // Acquire a reference to the current task. + { + ::osl::MutexGuard aGuard (maCurrentTaskMutex); + mpCurrentTask = pTask; + } + + if (mpCurrentTask.get() == NULL) + { + // Wait until the first task becomes due. + TimeValue aTimeValue; + ConvertToTimeValue(aTimeValue, nDifference); + wait(aTimeValue); + } + else + { + // Execute task. + if ( ! mpCurrentTask->maTask.empty() + && ! mpCurrentTask->mbIsCanceled) + { + mpCurrentTask->maTask(aCurrentTime); + + // Re-schedule repeating tasks. + if (mpCurrentTask->mnRepeatIntervall > 0) + { + ConvertToTimeValue( + mpCurrentTask->maDueTime, + ConvertFromTimeValue(mpCurrentTask->maDueTime) + + mpCurrentTask->mnRepeatIntervall); + ScheduleTask(mpCurrentTask); + } + } + + } + + // Release reference to the current task. + { + ::osl::MutexGuard aGuard (maCurrentTaskMutex); + mpCurrentTask.reset(); + } + } +} + + + + +void SAL_CALL TimerScheduler::onTerminated (void) +{ + Release(); +} + + + + +bool TimerScheduler::GetCurrentTime (TimeValue& rCurrentTime) +{ + TimeValue aSystemTime; + if (osl_getSystemTime(&aSystemTime)) + return osl_getLocalTimeFromSystemTime(&aSystemTime, &rCurrentTime); + return false; +} + + + + +sal_Int64 TimerScheduler::GetTimeDifference ( + const TimeValue& rTargetTime, + const TimeValue& rCurrentTime) +{ + return ConvertFromTimeValue(rTargetTime) - ConvertFromTimeValue(rCurrentTime); +} + + + + +void TimerScheduler::ConvertToTimeValue ( + TimeValue& rTimeValue, + const sal_Int64 nTimeDifference) +{ + rTimeValue.Seconds = sal::static_int_cast<sal_Int32>(nTimeDifference / 1000000000L); + rTimeValue.Nanosec = sal::static_int_cast<sal_Int32>(nTimeDifference % 1000000000L); +} + + + + +sal_Int64 TimerScheduler::ConvertFromTimeValue ( + const TimeValue& rTimeValue) +{ + return sal_Int64(rTimeValue.Seconds) * 1000000000L + rTimeValue.Nanosec; +} + + + + +//===== TimerTask ============================================================= + +namespace { + +TimerTask::TimerTask ( + const PresenterTimer::Task& rTask, + const TimeValue& rDueTime, + const sal_Int64 nRepeatIntervall, + const sal_Int32 nTaskId) + : maTask(rTask), + maDueTime(rDueTime), + mnRepeatIntervall(nRepeatIntervall), + mnTaskId(nTaskId), + mbIsCanceled(false) +{ +} + +} // end of anonymous namespace + + + + +//===== PresenterTimer ======================================================== + + +::rtl::Reference<PresenterClockTimer> PresenterClockTimer::mpInstance; + +::rtl::Reference<PresenterClockTimer> PresenterClockTimer::Instance ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext) +{ + ::osl::MutexGuard aSolarGuard (::osl::Mutex::getGlobalMutex()); + + ::rtl::Reference<PresenterClockTimer> pTimer; + if (mpInstance.is()) + { + pTimer = mpInstance; + } + if ( ! pTimer.is()) + { + pTimer = ::rtl::Reference<PresenterClockTimer>(new PresenterClockTimer(rxContext)); + mpInstance = pTimer; + } + return pTimer; +} + + + + +PresenterClockTimer::PresenterClockTimer (const Reference<XComponentContext>& rxContext) + : PresenterClockTimerInterfaceBase(m_aMutex), + maListeners(), + maDateTime(), + mnTimerTaskId(PresenterTimer::NotAValidTaskId), + mbIsCallbackPending(false), + mxRequestCallback() +{ + Reference<lang::XMultiComponentFactory> xFactory ( + rxContext->getServiceManager(), UNO_QUERY); + if (xFactory.is()) + mxRequestCallback = Reference<awt::XRequestCallback>( + xFactory->createInstanceWithContext( + A2S("com.sun.star.awt.AsyncCallback"), + rxContext), + UNO_QUERY_THROW); +} + + + + +PresenterClockTimer::~PresenterClockTimer (void) +{ + if (mnTimerTaskId != PresenterTimer::NotAValidTaskId) + { + PresenterTimer::CancelTask(mnTimerTaskId); + mnTimerTaskId = PresenterTimer::NotAValidTaskId; + } + + Reference<lang::XComponent> xComponent (mxRequestCallback, UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + mxRequestCallback = NULL; +} + + + + +void PresenterClockTimer::AddListener (const SharedListener& rListener) +{ + osl::MutexGuard aGuard (maMutex); + + maListeners.push_back(rListener); + + // Create a timer task when the first listener is added. + if (mnTimerTaskId==PresenterTimer::NotAValidTaskId) + { + mnTimerTaskId = PresenterTimer::ScheduleRepeatedTask( + ::boost::bind(&PresenterClockTimer::CheckCurrentTime, this, _1), + 0, + 250000000 /*ns*/); + } +} + + + + +void PresenterClockTimer::RemoveListener (const SharedListener& rListener) +{ + osl::MutexGuard aGuard (maMutex); + + ListenerContainer::iterator iListener (::std::find( + maListeners.begin(), + maListeners.end(), + rListener)); + if (iListener != maListeners.end()) + maListeners.erase(iListener); + if (maListeners.size() == 0) + { + // We have no more clients and therefore are not interested in time changes. + if (mnTimerTaskId != PresenterTimer::NotAValidTaskId) + { + PresenterTimer::CancelTask(mnTimerTaskId); + mnTimerTaskId = PresenterTimer::NotAValidTaskId; + } + mpInstance = NULL; + } +} + + + + +oslDateTime PresenterClockTimer::GetCurrentTime (void) +{ + TimeValue aCurrentTime; + TimerScheduler::GetCurrentTime(aCurrentTime); + oslDateTime aDateTime; + osl_getDateTimeFromTimeValue(&aCurrentTime, &aDateTime); + return aDateTime; +} + + + + +sal_Int64 PresenterClockTimer::GetTimeDifference ( + const oslDateTime& rNow, + const oslDateTime& rThen) +{ + TimeValue aNow; + TimeValue aThen; + if (osl_getTimeValueFromDateTime(const_cast<oslDateTime*>(&rNow),&aNow) + && osl_getTimeValueFromDateTime(const_cast<oslDateTime*>(&rThen),&aThen)) + { + return TimerScheduler::GetTimeDifference(aNow, aThen); + } + else + return -1; +} + + + + +void PresenterClockTimer::CheckCurrentTime (const TimeValue& rCurrentTime) +{ + css::uno::Reference<css::awt::XRequestCallback> xRequestCallback; + css::uno::Reference<css::awt::XCallback> xCallback; + { + osl::MutexGuard aGuard (maMutex); + + TimeValue aCurrentTime (rCurrentTime); + oslDateTime aDateTime; + if (osl_getDateTimeFromTimeValue(&aCurrentTime, &aDateTime)) + { + if (aDateTime.Seconds != maDateTime.Seconds + || aDateTime.Minutes != maDateTime.Minutes + || aDateTime.Seconds != maDateTime.Seconds) + { + // The displayed part of the current time has changed. + // Prepare to call the listeners. + maDateTime = aDateTime; + + // Schedule notification of listeners. + if (mxRequestCallback.is() && ! mbIsCallbackPending) + { + mbIsCallbackPending = true; + xRequestCallback = mxRequestCallback; + xCallback = this; + } + } + } + } + if (mxRequestCallback.is() && xCallback.is()) + xRequestCallback->addCallback(xCallback, Any()); +} + + + + +//----- XCallback ------------------------------------------------------------- + +void SAL_CALL PresenterClockTimer::notify (const css::uno::Any& rUserData) + throw (css::uno::RuntimeException) +{ + (void)rUserData; + + ListenerContainer aListenerCopy (maListeners); + + { + osl::MutexGuard aGuard (maMutex); + + mbIsCallbackPending = false; + + ::std::copy( + maListeners.begin(), + maListeners.end(), + ::std::back_inserter(aListenerCopy)); + } + + if (aListenerCopy.size() > 0) + { + ListenerContainer::const_iterator iListener; + ListenerContainer::const_iterator iEnd (aListenerCopy.end()); + for (iListener=aListenerCopy.begin(); iListener!=iEnd; ++iListener) + { + (*iListener)->TimeHasChanged(maDateTime); + } + } +} + + + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterTimer.hxx b/sdext/source/presenter/PresenterTimer.hxx new file mode 100644 index 000000000000..19d9e0637258 --- /dev/null +++ b/sdext/source/presenter/PresenterTimer.hxx @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_TIMER_HXX +#define SDEXT_PRESENTER_TIMER_HXX + +#include <com/sun/star/awt/XCallback.hpp> +#include <com/sun/star/awt/XRequestCallback.hpp> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase1.hxx> +#include <osl/mutex.hxx> +#include <osl/time.h> +#include <rtl/ref.hxx> +#include <sal/types.h> +#include <boost/enable_shared_from_this.hpp> +#include <boost/function.hpp> +#include <vector> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +class PresenterClockInternalTimer; + +/** The timer allows tasks to be scheduled for execution at a specified time + in the future. +*/ +class PresenterTimer +{ +public: + /** A task is called with the current time. + */ + typedef ::boost::function<void(const TimeValue&)> Task; + + static const sal_Int32 NotAValidTaskId = 0; + + static sal_Int32 ScheduleSingleTaskRelative ( + const Task& rTask, + const sal_Int64 nDelay); + + static sal_Int32 ScheduleSingleTaskAbsolute ( + const Task& rTask, + const TimeValue& rDueTime); + + /** Schedule a task to be executed repeatedly. The task is executed the + first time after nFirst nano-seconds (1000000000 corresponds to one + second). After that task is executed in intervalls that are + nIntervall ns long until CancelTask is called. + */ + static sal_Int32 ScheduleRepeatedTask ( + const Task& rTask, + const sal_Int64 nFirst, + const sal_Int64 nIntervall); + + static void CancelTask (const sal_Int32 nTaskId); +}; + + + +typedef cppu::WeakComponentImplHelper1< + css::awt::XCallback + > PresenterClockTimerInterfaceBase; + +/** A timer that calls its listeners, typically clocks, every second to + update their current time value. +*/ +class PresenterClockTimer + : protected ::cppu::BaseMutex, + public PresenterClockTimerInterfaceBase +{ +public: + class Listener { public: + virtual void TimeHasChanged (const oslDateTime& rCurrentTime) = 0; + }; + typedef ::boost::shared_ptr<Listener> SharedListener; + + static ::rtl::Reference<PresenterClockTimer> Instance ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext); + + void AddListener (const SharedListener& rListener); + void RemoveListener (const SharedListener& rListener); + + static oslDateTime GetCurrentTime (void); + + /** Return the difference between the two different times in + nanoseconds. + */ + static sal_Int64 GetTimeDifference (const oslDateTime& rNow, const oslDateTime& rThen); + + // XCallback + + virtual void SAL_CALL notify (const css::uno::Any& rUserData) + throw (css::uno::RuntimeException); + +private: + static ::rtl::Reference<PresenterClockTimer> mpInstance; + + ::osl::Mutex maMutex; + typedef ::std::vector<SharedListener> ListenerContainer; + ListenerContainer maListeners; + oslDateTime maDateTime; + sal_Int32 mnTimerTaskId; + bool mbIsCallbackPending; + css::uno::Reference<css::awt::XRequestCallback> mxRequestCallback; + + PresenterClockTimer ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext); + ~PresenterClockTimer (void); + + void CheckCurrentTime (const TimeValue& rCurrentTime); +}; + + + + + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterToolBar.cxx b/sdext/source/presenter/PresenterToolBar.cxx new file mode 100644 index 000000000000..1eb04a8e4171 --- /dev/null +++ b/sdext/source/presenter/PresenterToolBar.cxx @@ -0,0 +1,2461 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterToolBar.hxx" + +#include "PresenterBitmapContainer.hxx" +#include "PresenterCanvasHelper.hxx" +#include "PresenterComponent.hxx" +#include "PresenterGeometryHelper.hxx" +#include "PresenterPaintManager.hxx" +#include "PresenterPaneBase.hxx" +#include "PresenterPaneFactory.hxx" +#include "PresenterTimer.hxx" +#include "PresenterWindowManager.hxx" + +#include <cppuhelper/compbase2.hxx> +#include <com/sun/star/awt/FontDescriptor.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/deployment/XPackageInformationProvider.hpp> +#include <com/sun/star/drawing/framework/XControllerManager.hpp> +#include <com/sun/star/drawing/framework/XConfigurationController.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/geometry/AffineMatrix2D.hpp> +#include <com/sun/star/lang/XServiceName.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/RenderState.hpp> +#include <com/sun/star/rendering/TextDirection.hpp> +#include <com/sun/star/rendering/ViewState.hpp> +#include <com/sun/star/rendering/XSpriteCanvas.hpp> +#include <com/sun/star/text/XTextRange.hpp> +#include <com/sun/star/util/Color.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <rtl/ustrbuf.hxx> +#include <boost/bind.hpp> +#include <boost/function.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <map> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) + +namespace sdext { namespace presenter { + +static const sal_Int32 gnGapSize (20); +static const sal_Int32 gnMinimalSeparatorSize (20); +static const sal_Int32 gnSeparatorInset (0); + +namespace { + + class Text + { + public: + Text (void); + Text (const Text& rText); + Text ( + const OUString& rsText, + const PresenterTheme::SharedFontDescriptor& rpFont); + + void SetText (const OUString& rsText); + OUString GetText (void) const; + PresenterTheme::SharedFontDescriptor GetFont (void) const; + + void Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState, + const awt::Rectangle& rBoundingBox, + const awt::Point& rOffset); + + geometry::RealRectangle2D GetBoundingBox ( + const Reference<rendering::XCanvas>& rxCanvas); + + private: + OUString msText; + PresenterTheme::SharedFontDescriptor mpFont; + }; + + class ElementMode + : private ::boost::noncopyable + { + public: + ElementMode (void); + + SharedBitmapDescriptor mpIcon; + OUString msAction; + Text maText; + + void ReadElementMode ( + const Reference<beans::XPropertySet>& rxProperties, + const ::rtl::OUString& rsModeName, + ::boost::shared_ptr<ElementMode>& rpDefaultMode, + ::sdext::presenter::PresenterToolBar::Context& rContext); + }; + typedef ::boost::shared_ptr<ElementMode> SharedElementMode; + +} // end of anonymous namespace + + +class PresenterToolBar::Context + : private ::boost::noncopyable +{ +public: + ::rtl::OUString msBasePath; + Reference<drawing::XPresenterHelper> mxPresenterHelper; + css::uno::Reference<css::rendering::XCanvas> mxCanvas; +}; + + + + +//===== PresenterToolBar::Element ============================================= + +namespace { + typedef cppu::WeakComponentImplHelper2< + css::document::XEventListener, + css::frame::XStatusListener + > ElementInterfaceBase; + + class Element + : private ::cppu::BaseMutex, + private ::boost::noncopyable, + public ElementInterfaceBase + { + public: + Element (const ::rtl::Reference<PresenterToolBar>& rpToolBar); + virtual ~Element (void); + + virtual void SAL_CALL disposing (void); + + virtual void SetModes ( + const SharedElementMode& rpNormalMode, + const SharedElementMode& rpMouseOverMode, + const SharedElementMode& rpSelectedMode, + const SharedElementMode& rpDisabledMode); + virtual void CurrentSlideHasChanged (void); + virtual void SetLocation (const awt::Point& rLocation); + virtual void SetSize (const geometry::RealSize2D& rSize); + virtual void Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState) = 0; + awt::Size GetBoundingSize ( + const Reference<rendering::XCanvas>& rxCanvas); + awt::Rectangle GetBoundingBox (void) const; + virtual bool SetState (const bool bIsOver, const bool bIsPressed); + virtual void Invalidate (const bool bSynchronous = true); + virtual bool IsOutside (const awt::Rectangle& rBox); + virtual bool IsFilling (void) const; + void UpdateState (void); + + OUString GetAction (void) const; + + // lang::XEventListener + + virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) + throw(css::uno::RuntimeException); + + // document::XEventListener + + virtual void SAL_CALL notifyEvent (const css::document::EventObject& rEvent) + throw(css::uno::RuntimeException); + + // frame::XStatusListener + + virtual void SAL_CALL statusChanged (const css::frame::FeatureStateEvent& rEvent) + throw(css::uno::RuntimeException); + + protected: + ::rtl::Reference<PresenterToolBar> mpToolBar; + awt::Point maLocation; + awt::Size maSize; + SharedElementMode mpNormal; + SharedElementMode mpMouseOver; + SharedElementMode mpSelected; + SharedElementMode mpDisabled; + SharedElementMode mpMode; + bool mbIsOver; + bool mbIsPressed; + bool mbIsSelected; + + virtual awt::Size CreateBoundingSize ( + const Reference<rendering::XCanvas>& rxCanvas) = 0; + + bool IsEnabled (void) const; + void SetEnabledState (const bool bIsEnabled); + + private: + bool mbIsEnabled; + }; + +} // end of anonymous namespace + + +class PresenterToolBar::ElementContainerPart + : public ::std::vector<rtl::Reference<Element> > +{ +}; + + + + +//===== Button ================================================================ + +namespace { + + class Button : public Element + { + public: + static ::rtl::Reference<Element> Create ( + const ::rtl::Reference<PresenterToolBar>& rpToolBar); + + virtual ~Button (void); + virtual void SAL_CALL disposing (void); + + virtual void Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState); + + // lang::XEventListener + + virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) + throw(css::uno::RuntimeException); + + protected: + virtual awt::Size CreateBoundingSize ( + const Reference<rendering::XCanvas>& rxCanvas); + + private: + bool mbIsListenerRegistered; + + Button (const ::rtl::Reference<PresenterToolBar>& rpToolBar); + void Initialize (void); + void PaintIcon ( + const Reference<rendering::XCanvas>& rxCanvas, + const sal_Int32 nTextHeight, + const rendering::ViewState& rViewState); + PresenterBitmapDescriptor::Mode GetMode (void) const; + }; + + + + +//===== Label ================================================================= + + class Label : public Element + { + public: + Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar); + + void SetText (const OUString& rsText); + virtual void Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState); + virtual bool SetState (const bool bIsOver, const bool bIsPressed); + + protected: + virtual awt::Size CreateBoundingSize ( + const Reference<rendering::XCanvas>& rxCanvas); + }; + + +// Some specialized controls. + + + class ProgressLabel : public Label + { + public: + ProgressLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar); + virtual void CurrentSlideHasChanged (void); + }; + + class TimeFormatter + { + public: + TimeFormatter (void); + OUString FormatTime (const oslDateTime& rTime); + private: + bool mbIs24HourFormat; + bool mbIsAmPmFormat; + bool mbIsShowSeconds; + }; + + class TimeLabel : public Label + { + public: + void ConnectToTimer (void); + virtual void TimeHasChanged (const oslDateTime& rCurrentTime) = 0; + protected: + TimeLabel(const ::rtl::Reference<PresenterToolBar>& rpToolBar); + using Element::disposing; + virtual void SAL_CALL disposing (void); + private: + class Listener : public PresenterClockTimer::Listener + { + public: + Listener (const ::rtl::Reference<TimeLabel>& rxLabel) + : mxLabel(rxLabel) {} + virtual ~Listener (void) {} + virtual void TimeHasChanged (const oslDateTime& rCurrentTime) + { if (mxLabel.is()) mxLabel->TimeHasChanged(rCurrentTime); } + private: + ::rtl::Reference<TimeLabel> mxLabel; + }; + ::boost::shared_ptr<PresenterClockTimer::Listener> mpListener; + }; + + class CurrentTimeLabel : public TimeLabel + { + public: + static ::rtl::Reference<Element> Create ( + const ::rtl::Reference<PresenterToolBar>& rpToolBar); + virtual void SetModes ( + const SharedElementMode& rpNormalMode, + const SharedElementMode& rpMouseOverMode, + const SharedElementMode& rpSelectedMode, + const SharedElementMode& rpDisabledMode); + private: + TimeFormatter maTimeFormatter; + CurrentTimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar); + virtual ~CurrentTimeLabel (void); + virtual void TimeHasChanged (const oslDateTime& rCurrentTime); + }; + + class PresentationTimeLabel : public TimeLabel + { + public: + static ::rtl::Reference<Element> Create ( + const ::rtl::Reference<PresenterToolBar>& rpToolBar); + virtual void SetModes ( + const SharedElementMode& rpNormalMode, + const SharedElementMode& rpMouseOverMode, + const SharedElementMode& rpSelectedMode, + const SharedElementMode& rpDisabledMode); + private: + TimeFormatter maTimeFormatter; + TimeValue maStartTimeValue; + PresentationTimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar); + virtual ~PresentationTimeLabel (void); + virtual void TimeHasChanged (const oslDateTime& rCurrentTime); + }; + + class VerticalSeparator : public Element + { + public: + explicit VerticalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar); + virtual void Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState); + virtual bool IsFilling (void) const; + + protected: + virtual awt::Size CreateBoundingSize ( + const Reference<rendering::XCanvas>& rxCanvas); + }; + + class HorizontalSeparator : public Element + { + public: + explicit HorizontalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar); + virtual void Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState); + virtual bool IsFilling (void) const; + + protected: + virtual awt::Size CreateBoundingSize ( + const Reference<rendering::XCanvas>& rxCanvas); + }; +} // end of anonymous namespace + + + +//===== PresenterToolBar ====================================================== + +PresenterToolBar::PresenterToolBar ( + const Reference<XComponentContext>& rxContext, + const css::uno::Reference<css::awt::XWindow>& rxWindow, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const Anchor eAnchor) + : PresenterToolBarInterfaceBase(m_aMutex), + mxComponentContext(rxContext), + maElementContainer(), + mpCurrentContainerPart(), + mxWindow(rxWindow), + mxCanvas(rxCanvas), + mxSlideShowController(), + mxCurrentSlide(), + mpPresenterController(rpPresenterController), + mbIsLayoutPending(false), + meAnchor(eAnchor), + maBoundingBox(), + maMinimalSize() +{ +} + + + + +void PresenterToolBar::Initialize ( + const ::rtl::OUString& rsConfigurationPath) +{ + try + { + CreateControls(rsConfigurationPath); + + if (mxWindow.is()) + { + mxWindow->addWindowListener(this); + mxWindow->addPaintListener(this); + mxWindow->addMouseListener(this); + mxWindow->addMouseMotionListener(this); + + Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY); + if (xPeer.is()) + xPeer->setBackground(util::Color(0xff000000)); + + mxWindow->setVisible(sal_True); + } + + mxSlideShowController = mpPresenterController->GetSlideShowController(); + UpdateSlideNumber(); + mbIsLayoutPending = true; + } + catch (RuntimeException&) + { + mpCurrentContainerPart.reset(); + maElementContainer.clear(); + throw; + } +} + + + + +PresenterToolBar::~PresenterToolBar (void) +{ +} + + + + +void SAL_CALL PresenterToolBar::disposing (void) +{ + if (mxWindow.is()) + { + mxWindow->removeWindowListener(this); + mxWindow->removePaintListener(this); + mxWindow->removeMouseListener(this); + mxWindow->removeMouseMotionListener(this); + mxWindow = NULL; + } + + // Dispose tool bar elements. + ElementContainer::iterator iPart (maElementContainer.begin()); + ElementContainer::const_iterator iEnd (maElementContainer.end()); + for ( ; iPart!=iEnd; ++iPart) + { + OSL_ASSERT(iPart->get()!=NULL); + ElementContainerPart::iterator iElement ((*iPart)->begin()); + ElementContainerPart::const_iterator iPartEnd ((*iPart)->end()); + for ( ; iElement!=iPartEnd; ++iElement) + { + if (iElement->get() != NULL) + { + ::rtl::Reference<Element> pElement (*iElement); + Reference<lang::XComponent> xComponent ( + static_cast<XWeak*>(pElement.get()), UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + } + } + } + + mpCurrentContainerPart.reset(); + maElementContainer.clear(); +} + + + + +void PresenterToolBar::InvalidateArea ( + const awt::Rectangle& rRepaintBox, + const bool bSynchronous) +{ + mpPresenterController->GetPaintManager()->Invalidate( + mxWindow, + rRepaintBox, + bSynchronous); +} + + + + +sal_Int32 PresenterToolBar::GetCurrentSlideIndex (void) +{ + if (mxSlideShowController.is()) + return mxSlideShowController->getCurrentSlideIndex(); + else + return -1; +} + + + + +sal_Int32 PresenterToolBar::GetSlideCount (void) +{ + if (mxSlideShowController.is()) + return mxSlideShowController->getSlideCount(); + else + return 0; +} + + + + +void PresenterToolBar::RequestLayout (void) +{ + mbIsLayoutPending = true; + + mpPresenterController->GetPaintManager()->Invalidate(mxWindow); +} + + + + +geometry::RealSize2D PresenterToolBar::GetSize (void) +{ + if (mbIsLayoutPending) + Layout(mxCanvas); + return geometry::RealSize2D( + maBoundingBox.X2 - maBoundingBox.X1, + maBoundingBox.Y2 - maBoundingBox.Y1); +} + + + + +geometry::RealSize2D PresenterToolBar::GetMinimalSize (void) +{ + if (mbIsLayoutPending) + Layout(mxCanvas); + return maMinimalSize; +} + + + + +::rtl::Reference<PresenterController> PresenterToolBar::GetPresenterController (void) const +{ + return mpPresenterController; +} + + + + +Reference<awt::XWindow> PresenterToolBar::GetWindow (void) const +{ + return mxWindow; +} + + + + +Reference<XComponentContext> PresenterToolBar::GetComponentContext (void) const +{ + return mxComponentContext; +} + + + + +//----- lang::XEventListener ------------------------------------------------- + +void SAL_CALL PresenterToolBar::disposing (const lang::EventObject& rEventObject) + throw (RuntimeException) +{ + if (rEventObject.Source == mxWindow) + mxWindow = NULL; +} + + + + +//----- XWindowListener ------------------------------------------------------- + +void SAL_CALL PresenterToolBar::windowResized (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + mbIsLayoutPending = true; +} + + + + +void SAL_CALL PresenterToolBar::windowMoved (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterToolBar::windowShown (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; + mbIsLayoutPending = true; +} + + + + +void SAL_CALL PresenterToolBar::windowHidden (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; +} + + + + +//----- XPaintListener -------------------------------------------------------- + +void SAL_CALL PresenterToolBar::windowPaint (const css::awt::PaintEvent& rEvent) + throw (RuntimeException) +{ + if ( ! mxCanvas.is()) + return; + + if ( ! mbIsPresenterViewActive) + return; + + const rendering::ViewState aViewState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + PresenterGeometryHelper::CreatePolygon(rEvent.UpdateRect, mxCanvas->getDevice())); + + if (mbIsLayoutPending) + Layout(mxCanvas); + + Paint(rEvent.UpdateRect, aViewState); + + // Make the back buffer visible. + Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); + if (xSpriteCanvas.is()) + xSpriteCanvas->updateScreen(sal_False); +} + + + + +//----- XMouseListener -------------------------------------------------------- + +void SAL_CALL PresenterToolBar::mousePressed (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + CheckMouseOver(rEvent, true, true); +} + + + + +void SAL_CALL PresenterToolBar::mouseReleased (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + CheckMouseOver(rEvent, true); +} + + + + +void SAL_CALL PresenterToolBar::mouseEntered (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + CheckMouseOver(rEvent, true); +} + + + + +void SAL_CALL PresenterToolBar::mouseExited (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + CheckMouseOver(rEvent, false); +} + + + + +//----- XMouseMotionListener -------------------------------------------------- + +void SAL_CALL PresenterToolBar::mouseMoved (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + ThrowIfDisposed(); + + CheckMouseOver(rEvent, true); +} + + + + +void SAL_CALL PresenterToolBar::mouseDragged (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException) +{ + ThrowIfDisposed(); + (void)rEvent; +} + + + + +//----- XDrawView ------------------------------------------------------------- + +void SAL_CALL PresenterToolBar::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide) + throw (RuntimeException) +{ + if (rxSlide != mxCurrentSlide) + { + mxCurrentSlide = rxSlide; + UpdateSlideNumber(); + } +} + + + + +Reference<drawing::XDrawPage> SAL_CALL PresenterToolBar::getCurrentPage (void) + throw (RuntimeException) +{ + return mxCurrentSlide; +} + + + + +//----------------------------------------------------------------------------- + +void PresenterToolBar::CreateControls ( + const ::rtl::OUString& rsConfigurationPath) +{ + if ( ! mxWindow.is()) + return; + + // Expand the macro in the bitmap file names. + PresenterConfigurationAccess aConfiguration ( + mxComponentContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.extension.PresenterScreen/")), + PresenterConfigurationAccess::READ_ONLY); + + const OUString sBasePath (PresenterComponent::GetBasePath(mxComponentContext)); + + mpCurrentContainerPart.reset(new ElementContainerPart()); + maElementContainer.clear(); + maElementContainer.push_back(mpCurrentContainerPart); + + Reference<container::XHierarchicalNameAccess> xToolBarNode ( + aConfiguration.GetConfigurationNode(rsConfigurationPath), + UNO_QUERY); + if (xToolBarNode.is()) + { + Reference<container::XNameAccess> xEntries ( + PresenterConfigurationAccess::GetConfigurationNode(xToolBarNode, A2S("Entries")), + UNO_QUERY); + Context aContext; + aContext.msBasePath = sBasePath; + aContext.mxPresenterHelper = mpPresenterController->GetPresenterHelper(); + aContext.mxCanvas = mxCanvas; + if (xEntries.is() + && aContext.mxPresenterHelper.is() + && aContext.mxCanvas.is()) + { + PresenterConfigurationAccess::ForAll( + xEntries, + ::boost::bind(&PresenterToolBar::ProcessEntry, this, _2, ::boost::ref(aContext))); + } + } +} + + + + +void PresenterToolBar::ProcessEntry ( + const Reference<beans::XPropertySet>& rxProperties, + Context& rContext) +{ + if ( ! rxProperties.is()) + return; + + // Type has to be present. + OUString sType; + if ( ! (PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Type")) >>= sType)) + return; + + OUString sName; + PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Name")) >>= sName; + + // Read mode specific values. + SharedElementMode pNormalMode (new ElementMode()); + SharedElementMode pMouseOverMode (new ElementMode()); + SharedElementMode pSelectedMode (new ElementMode()); + SharedElementMode pDisabledMode (new ElementMode()); + pNormalMode->ReadElementMode(rxProperties, A2S("Normal"), pNormalMode, rContext); + pMouseOverMode->ReadElementMode(rxProperties, A2S("MouseOver"), pNormalMode, rContext); + pSelectedMode->ReadElementMode(rxProperties, A2S("Selected"), pNormalMode, rContext); + pDisabledMode->ReadElementMode(rxProperties, A2S("Disabled"), pNormalMode, rContext); + + // Create new element. + ::rtl::Reference<Element> pElement; + if (sType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Button"))) + pElement = Button::Create(this); + else if (sType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("CurrentTimeLabel"))) + pElement = CurrentTimeLabel::Create(this); + else if (sType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("PresentationTimeLabel"))) + pElement = PresentationTimeLabel::Create(this); + else if (sType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("VerticalSeparator"))) + pElement = ::rtl::Reference<Element>(new VerticalSeparator(this)); + else if (sType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("HorizontalSeparator"))) + pElement = ::rtl::Reference<Element>(new HorizontalSeparator(this)); + else if (sType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Label"))) + pElement = ::rtl::Reference<Element>(new Label(this)); + else if (sType.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ChangeOrientation"))) + { + mpCurrentContainerPart.reset(new ElementContainerPart()); + maElementContainer.push_back(mpCurrentContainerPart); + return; + } + if (pElement.is()) + { + pElement->SetModes( pNormalMode, pMouseOverMode, pSelectedMode, pDisabledMode); + pElement->UpdateState(); + if (mpCurrentContainerPart.get() != NULL) + mpCurrentContainerPart->push_back(pElement); + } +} + + + + +void PresenterToolBar::Layout ( + const Reference<rendering::XCanvas>& rxCanvas) +{ + if (maElementContainer.size() == 0) + return; + + mbIsLayoutPending = false; + + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + ElementContainer::iterator iPart; + ElementContainer::iterator iEnd (maElementContainer.end()); + ::std::vector<geometry::RealSize2D> aPartSizes (maElementContainer.size()); + geometry::RealSize2D aTotalSize (0,0); + bool bIsHorizontal (true); + sal_Int32 nIndex; + double nTotalHorizontalGap (0); + sal_Int32 nGapCount (0); + for (iPart=maElementContainer.begin(),nIndex=0; iPart!=iEnd; ++iPart,++nIndex) + { + geometry::RealSize2D aSize (CalculatePartSize(rxCanvas, *iPart, bIsHorizontal)); + + // Remember the size of each part for later. + aPartSizes[nIndex] = aSize; + + // Add gaps between elements. + if ((*iPart)->size()>1 && bIsHorizontal) + { + nTotalHorizontalGap += ((*iPart)->size() - 1) * gnGapSize; + nGapCount += (*iPart)->size()-1; + } + + // Orientation changes for each part. + bIsHorizontal = !bIsHorizontal; + // Width is accumulated. + aTotalSize.Width += aSize.Width; + // Height is the maximum height of all parts. + aTotalSize.Height = ::std::max(aTotalSize.Height, aSize.Height); + } + // Add gaps between parts. + if (maElementContainer.size() > 1) + { + nTotalHorizontalGap += (maElementContainer.size() - 1) * gnGapSize; + nGapCount += maElementContainer.size()-1; + } + + // Calculate the minimal size so that the window size of the tool bar + // can be adapted accordingly. + maMinimalSize = aTotalSize; + maMinimalSize.Width += nTotalHorizontalGap; + + // Calculate the gaps between elements. + double nGapWidth (0); + if (nGapCount > 0) + { + if (aTotalSize.Width + nTotalHorizontalGap > aWindowBox.Width) + nTotalHorizontalGap = aWindowBox.Width - aTotalSize.Width; + nGapWidth = nTotalHorizontalGap / nGapCount; + } + + // Determine the location of the left edge. + double nX (0); + switch (meAnchor) + { + case Left : nX = 0; break; + case Center: nX = (aWindowBox.Width - aTotalSize.Width - nTotalHorizontalGap) / 2; break; + case Right: nX = aWindowBox.Width - aTotalSize.Width - nTotalHorizontalGap; break; + } + + // Place the parts. + double nY ((aWindowBox.Height - aTotalSize.Height) / 2); + bIsHorizontal = true; + + maBoundingBox.X1 = nX; + maBoundingBox.Y1 = nY; + maBoundingBox.X2 = nX + aTotalSize.Width + nTotalHorizontalGap; + maBoundingBox.Y2 = nY + aTotalSize.Height; + + for (iPart=maElementContainer.begin(), nIndex=0; iPart!=iEnd; ++iPart,++nIndex) + { + geometry::RealRectangle2D aBoundingBox( + nX, nY, + nX+aPartSizes[nIndex].Width, nY+aTotalSize.Height); + + // Add space for gaps between elements. + if ((*iPart)->size() > 1) + if (bIsHorizontal) + aBoundingBox.X2 += ((*iPart)->size()-1) * nGapWidth; + + LayoutPart(rxCanvas, *iPart, aBoundingBox, aPartSizes[nIndex], bIsHorizontal); + bIsHorizontal = !bIsHorizontal; + nX += aBoundingBox.X2 - aBoundingBox.X1 + nGapWidth; + } + + // The whole window has to be repainted. + mpPresenterController->GetPaintManager()->Invalidate(mxWindow); +} + + + + +geometry::RealSize2D PresenterToolBar::CalculatePartSize ( + const Reference<rendering::XCanvas>& rxCanvas, + const SharedElementContainerPart& rpPart, + const bool bIsHorizontal) +{ + geometry::RealSize2D aTotalSize (0,0); + + if (mxWindow.is()) + { + const awt::Rectangle aWindowBox (mxWindow->getPosSize()); + + // Calculate the summed width of all elements. + ElementContainerPart::const_iterator iElement; + for (iElement=rpPart->begin(); iElement!=rpPart->end(); ++iElement) + { + if (iElement->get() == NULL) + continue; + + const awt::Size aBSize ((*iElement)->GetBoundingSize(rxCanvas)); + if (bIsHorizontal) + { + aTotalSize.Width += aBSize.Width; + if (aBSize.Height > aTotalSize.Height) + aTotalSize.Height = aBSize.Height; + } + else + { + aTotalSize.Height += aBSize.Height; + if (aBSize.Width > aTotalSize.Width) + aTotalSize.Width = aBSize.Width; + } + } + } + return aTotalSize; +} + + + + +void PresenterToolBar::LayoutPart ( + const Reference<rendering::XCanvas>& rxCanvas, + const SharedElementContainerPart& rpPart, + const geometry::RealRectangle2D& rBoundingBox, + const geometry::RealSize2D& rPartSize, + const bool bIsHorizontal) +{ + double nGap (0); + if (rpPart->size() > 1) + { + if (bIsHorizontal) + nGap = (rBoundingBox.X2 - rBoundingBox.X1 - rPartSize.Width) / (rpPart->size()-1); + else + nGap = (rBoundingBox.Y2 - rBoundingBox.Y1 - rPartSize.Height) / (rpPart->size()-1); + } + + // Place the elements. + double nX (rBoundingBox.X1); + double nY (rBoundingBox.Y1); + + ElementContainerPart::const_iterator iElement; + ElementContainerPart::const_iterator iEnd (rpPart->end()); + for (iElement=rpPart->begin(); iElement!=iEnd; ++iElement) + { + if (iElement->get() == NULL) + continue; + + const awt::Size aElementSize ((*iElement)->GetBoundingSize(rxCanvas)); + if (bIsHorizontal) + { + if ((*iElement)->IsFilling()) + { + nY = rBoundingBox.Y1; + (*iElement)->SetSize(geometry::RealSize2D(aElementSize.Width, rBoundingBox.Y2 - rBoundingBox.Y1)); + } + else + nY = rBoundingBox.Y1 + (rBoundingBox.Y2-rBoundingBox.Y1 - aElementSize.Height) / 2; + (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY))); + nX += aElementSize.Width + nGap; + } + else + { + if ((*iElement)->IsFilling()) + { + nX = rBoundingBox.X1; + (*iElement)->SetSize(geometry::RealSize2D(rBoundingBox.X2 - rBoundingBox.X1, aElementSize.Height)); + } + else + nX = rBoundingBox.X1 + (rBoundingBox.X2-rBoundingBox.X1 - aElementSize.Width) / 2; + (*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY))); + nY += aElementSize.Height + nGap; + } + } +} + + + + +void PresenterToolBar::Paint ( + const awt::Rectangle& rUpdateBox, + const rendering::ViewState& rViewState) +{ + OSL_ASSERT(mxCanvas.is()); + + ElementContainer::iterator iPart; + ElementContainer::const_iterator iEnd (maElementContainer.end()); + for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart) + { + ElementContainerPart::iterator iElement; + ElementContainerPart::const_iterator iPartEnd ((*iPart)->end()); + for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement) + { + if (iElement->get() != NULL) + { + if ( ! (*iElement)->IsOutside(rUpdateBox)) + (*iElement)->Paint(mxCanvas, rViewState); + } + } + } +} + + + + +void PresenterToolBar::UpdateSlideNumber (void) +{ + if( mxSlideShowController.is() ) + { + ElementContainer::iterator iPart; + ElementContainer::const_iterator iEnd (maElementContainer.end()); + for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart) + { + ElementContainerPart::iterator iElement; + ElementContainerPart::const_iterator iPartEnd ((*iPart)->end()); + for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement) + { + if (iElement->get() != NULL) + (*iElement)->CurrentSlideHasChanged(); + } + } + } +} + + + + +void PresenterToolBar::CheckMouseOver ( + const css::awt::MouseEvent& rEvent, + const bool bOverWindow, + const bool bMouseDown) +{ + ElementContainer::iterator iPart; + ElementContainer::const_iterator iEnd (maElementContainer.end()); + for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart) + { + ElementContainerPart::iterator iElement; + ElementContainerPart::const_iterator iPartEnd ((*iPart)->end()); + for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement) + { + if (iElement->get() == NULL) + continue; + + awt::Rectangle aBox ((*iElement)->GetBoundingBox()); + const bool bIsOver = bOverWindow + && aBox.X <= rEvent.X + && aBox.Width+aBox.X-1 >= rEvent.X + && aBox.Y <= rEvent.Y + && aBox.Height+aBox.Y-1 >= rEvent.Y; + (*iElement)->SetState( + bIsOver, + bIsOver && rEvent.Buttons!=0 && bMouseDown && rEvent.ClickCount>0); + } + } +} + + + + +void PresenterToolBar::ThrowIfDisposed (void) const + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterToolBar has already been disposed")), + const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + } +} + + + + +//===== PresenterToolBarView ================================================== + +PresenterToolBarView::PresenterToolBarView ( + const Reference<XComponentContext>& rxContext, + const Reference<XResourceId>& rxViewId, + const Reference<frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterToolBarViewInterfaceBase(m_aMutex), + mxPane(), + mxViewId(rxViewId), + mxWindow(), + mxCanvas(), + mpPresenterController(rpPresenterController), + mxSlideShowController(rpPresenterController->GetSlideShowController()), + mpToolBar() +{ + try + { + Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW); + Reference<XConfigurationController> xCC(xCM->getConfigurationController(),UNO_QUERY_THROW); + mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW); + + mxWindow = mxPane->getWindow(); + mxCanvas = mxPane->getCanvas(); + + mpToolBar = new PresenterToolBar( + rxContext, + mxWindow, + mxCanvas, + rpPresenterController, + PresenterToolBar::Center); + mpToolBar->Initialize(A2S("PresenterScreenSettings/ToolBars/ToolBar")); + + if (mxWindow.is()) + { + mxWindow->addPaintListener(this); + + Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY); + if (xPeer.is()) + xPeer->setBackground(util::Color(0xff000000)); + + mxWindow->setVisible(sal_True); + } + } + catch (RuntimeException&) + { + mxViewId = NULL; + throw; + } +} + + + + +PresenterToolBarView::~PresenterToolBarView (void) +{ +} + + + + +void SAL_CALL PresenterToolBarView::disposing (void) +{ + Reference<lang::XComponent> xComponent (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY); + mpToolBar = NULL; + if (xComponent.is()) + xComponent->dispose(); + + if (mxWindow.is()) + { + mxWindow->removePaintListener(this); + mxWindow = NULL; + } + mxCanvas = NULL; + mxViewId = NULL; + mxPane = NULL; + mpPresenterController = NULL; + mxSlideShowController = NULL; + +} + + + + +::rtl::Reference<PresenterToolBar> PresenterToolBarView::GetPresenterToolBar (void) const +{ + return mpToolBar; +} + + + + +//----- XPaintListener -------------------------------------------------------- + +void SAL_CALL PresenterToolBarView::windowPaint (const css::awt::PaintEvent& rEvent) + throw (RuntimeException) +{ + awt::Rectangle aWindowBox (mxWindow->getPosSize()); + mpPresenterController->GetCanvasHelper()->Paint( + mpPresenterController->GetViewBackground(mxViewId->getResourceURL()), + mxCanvas, + rEvent.UpdateRect, + awt::Rectangle(0,0,aWindowBox.Width, aWindowBox.Height), + awt::Rectangle()); +} + + + + +//----- lang::XEventListener ------------------------------------------------- + +void SAL_CALL PresenterToolBarView::disposing (const lang::EventObject& rEventObject) + throw (RuntimeException) +{ + if (rEventObject.Source == mxWindow) + mxWindow = NULL; +} + + + + +//----- XResourceId ----------------------------------------------------------- + +Reference<XResourceId> SAL_CALL PresenterToolBarView::getResourceId (void) + throw (RuntimeException) +{ + return mxViewId; +} + + + + +sal_Bool SAL_CALL PresenterToolBarView::isAnchorOnly (void) + throw (RuntimeException) +{ + return false; +} + + + + +//----- XDrawView ------------------------------------------------------------- + +void SAL_CALL PresenterToolBarView::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide) + throw (RuntimeException) +{ + Reference<drawing::XDrawView> xToolBar (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY); + if (xToolBar.is()) + xToolBar->setCurrentPage(rxSlide); +} + + + + +Reference<drawing::XDrawPage> SAL_CALL PresenterToolBarView::getCurrentPage (void) + throw (RuntimeException) +{ + return NULL; +} + + + + +//----------------------------------------------------------------------------- + +void PresenterToolBarView::ThrowIfDisposed (void) const + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterToolBarView has already been disposed")), + const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + } +} + + + + +//===== PresenterToolBar::Element ============================================= + +namespace { + +Element::Element ( + const ::rtl::Reference<PresenterToolBar>& rpToolBar) + : ElementInterfaceBase(m_aMutex), + mpToolBar(rpToolBar), + maLocation(), + maSize(), + mpNormal(), + mpMouseOver(), + mpSelected(), + mpDisabled(), + mpMode(), + mbIsOver(false), + mbIsPressed(false), + mbIsSelected(false), + mbIsEnabled(true) +{ + if (mpToolBar.get() != NULL) + { + OSL_ASSERT(mpToolBar->GetPresenterController().is()); + OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is()); + } +} + + + + +Element::~Element (void) +{ +} + + + + +void Element::SetModes ( + const SharedElementMode& rpNormalMode, + const SharedElementMode& rpMouseOverMode, + const SharedElementMode& rpSelectedMode, + const SharedElementMode& rpDisabledMode) +{ + mpNormal = rpNormalMode; + mpMouseOver = rpMouseOverMode; + mpSelected = rpSelectedMode; + mpDisabled = rpDisabledMode; + mpMode = rpNormalMode; +} + + + + +void Element::disposing (void) +{ +} + + + + +awt::Size Element::GetBoundingSize ( + const Reference<rendering::XCanvas>& rxCanvas) +{ + maSize = CreateBoundingSize(rxCanvas); + return maSize; +} + + + + +awt::Rectangle Element::GetBoundingBox (void) const +{ + return awt::Rectangle(maLocation.X,maLocation.Y, maSize.Width, maSize.Height); +} + + + + +void Element::CurrentSlideHasChanged (void) +{ + UpdateState(); +} + + + + +void Element::SetLocation (const awt::Point& rLocation) +{ + maLocation = rLocation; +} + + + +void Element::SetSize (const geometry::RealSize2D& rSize) +{ + maSize = awt::Size(sal_Int32(0.5+rSize.Width), sal_Int32(0.5+rSize.Height)); +} + + + + +bool Element::SetState ( + const bool bIsOver, + const bool bIsPressed) +{ + bool bModified (mbIsOver != bIsOver || mbIsPressed != bIsPressed); + bool bClicked (mbIsPressed && bIsOver && ! bIsPressed); + + mbIsOver = bIsOver; + mbIsPressed = bIsPressed; + + // When the element is disabled then ignore mouse over or selection. + // When the element is selected then ignore mouse over. + if ( ! mbIsEnabled) + mpMode = mpDisabled; + else if (mbIsSelected) + mpMode = mpSelected; + else if (mbIsOver) + mpMode = mpMouseOver; + else + mpMode = mpNormal; + + if (bClicked && mbIsEnabled) + { + if (mpMode.get() != NULL) + { + do + { + if (mpMode->msAction.getLength() <= 0) + break; + + if (mpToolBar.get() == NULL) + break; + + if (mpToolBar->GetPresenterController().get() == NULL) + break; + + mpToolBar->GetPresenterController()->DispatchUnoCommand(mpMode->msAction); + mpToolBar->RequestLayout(); + } + while (false); + } + + } + else if (bModified) + { + Invalidate(); + } + + return bModified; +} + + + + +void Element::Invalidate (const bool bSynchronous) +{ + OSL_ASSERT(mpToolBar.is()); + mpToolBar->InvalidateArea(GetBoundingBox(), bSynchronous); +} + + + + +bool Element::IsOutside (const awt::Rectangle& rBox) +{ + if (rBox.X >= maLocation.X+maSize.Width) + return true; + else if (rBox.Y >= maLocation.Y+maSize.Height) + return true; + else if (maLocation.X >= rBox.X+rBox.Width) + return true; + else if (maLocation.Y >= rBox.Y+rBox.Height) + return true; + else + return false; +} + + + +bool Element::IsEnabled (void) const +{ + return mbIsEnabled; +} + + + + +void Element::SetEnabledState (const bool bIsEnabled) +{ + mbIsEnabled = bIsEnabled; +} + + + + +bool Element::IsFilling (void) const +{ + return false; +} + + + + +void Element::UpdateState (void) +{ + OSL_ASSERT(mpToolBar.get() != NULL); + OSL_ASSERT(mpToolBar->GetPresenterController().get() != NULL); + + if (mpMode.get() == NULL) + return; + + util::URL aURL (mpToolBar->GetPresenterController()->CreateURLFromString(mpMode->msAction)); + Reference<frame::XDispatch> xDispatch (mpToolBar->GetPresenterController()->GetDispatch(aURL)); + if (xDispatch.is()) + { + xDispatch->addStatusListener(this, aURL); + xDispatch->removeStatusListener(this, aURL); + } +} + + + + +//----- lang::XEventListener -------------------------------------------------- + +void SAL_CALL Element::disposing (const css::lang::EventObject& rEvent) + throw(css::uno::RuntimeException) +{ + (void)rEvent; +} + + + + +//----- document::XEventListener ---------------------------------------------- + +void SAL_CALL Element::notifyEvent (const css::document::EventObject& rEvent) + throw(css::uno::RuntimeException) +{ + (void)rEvent; + UpdateState(); +} + + + + +//----- frame::XStatusListener ------------------------------------------------ + +void SAL_CALL Element::statusChanged (const css::frame::FeatureStateEvent& rEvent) + throw(css::uno::RuntimeException) +{ + bool bIsSelected (mbIsSelected); + bool bIsEnabled (rEvent.IsEnabled); + rEvent.State >>= bIsSelected; + + if (bIsSelected != mbIsSelected || bIsEnabled != mbIsEnabled) + { + mbIsEnabled = bIsEnabled; + mbIsSelected = bIsSelected; + SetState(mbIsOver, mbIsPressed); + mpToolBar->RequestLayout(); + } +} + +} // end of anonymous namespace + + + + +//===== ElementMode =========================================================== + +namespace { + +ElementMode::ElementMode (void) + : mpIcon(), + msAction(), + maText() +{ +} + + + + +void ElementMode::ReadElementMode ( + const Reference<beans::XPropertySet>& rxElementProperties, + const OUString& rsModeName, + ::boost::shared_ptr<ElementMode>& rpDefaultMode, + ::sdext::presenter::PresenterToolBar::Context& rContext) +{ + try + { + Reference<container::XHierarchicalNameAccess> xNode ( + PresenterConfigurationAccess::GetProperty(rxElementProperties, rsModeName), + UNO_QUERY); + Reference<beans::XPropertySet> xProperties ( + PresenterConfigurationAccess::GetNodeProperties(xNode, OUString())); + if ( ! xProperties.is() && rpDefaultMode.get()!=NULL) + { + // The mode is not specified. Use the given, possibly empty, + // default mode instead. + mpIcon = rpDefaultMode->mpIcon; + msAction = rpDefaultMode->msAction; + maText = rpDefaultMode->maText; + } + + // Read action. + if ( ! (PresenterConfigurationAccess::GetProperty(xProperties, A2S("Action")) >>= msAction)) + if (rpDefaultMode.get()!=NULL) + msAction = rpDefaultMode->msAction; + + // Read text and font + OUString sText (rpDefaultMode.get()!=NULL ? rpDefaultMode->maText.GetText() : OUString()); + PresenterConfigurationAccess::GetProperty(xProperties, A2S("Text")) >>= sText; + Reference<container::XHierarchicalNameAccess> xFontNode ( + PresenterConfigurationAccess::GetProperty(xProperties, A2S("Font")), UNO_QUERY); + PresenterTheme::SharedFontDescriptor pFont (PresenterTheme::ReadFont( + xFontNode, + A2S(""), + rpDefaultMode.get()!=NULL + ? rpDefaultMode->maText.GetFont() + : PresenterTheme::SharedFontDescriptor())); + maText = Text(sText,pFont); + + // Read bitmaps to display as icons. + Reference<container::XHierarchicalNameAccess> xIconNode ( + PresenterConfigurationAccess::GetProperty(xProperties, A2S("Icon")), UNO_QUERY); + mpIcon = PresenterBitmapContainer::LoadBitmap( + xIconNode, + A2S(""), + rContext.mxPresenterHelper, + rContext.msBasePath, + rContext.mxCanvas, + rpDefaultMode.get()!=NULL ? rpDefaultMode->mpIcon : SharedBitmapDescriptor()); + } + catch(Exception&) + { + OSL_ASSERT(false); + } +} + +} // end of anonymous namespace + + + + +//===== Button ================================================================ + +namespace { + +::rtl::Reference<Element> Button::Create ( + const ::rtl::Reference<PresenterToolBar>& rpToolBar) +{ + ::rtl::Reference<Button> pElement (new Button(rpToolBar)); + pElement->Initialize(); + return ::rtl::Reference<Element>(pElement.get()); +} + + + + +Button::Button ( + const ::rtl::Reference<PresenterToolBar>& rpToolBar) + : Element(rpToolBar), + mbIsListenerRegistered(false) +{ + OSL_ASSERT(mpToolBar.get() != NULL); + OSL_ASSERT(mpToolBar->GetPresenterController().is()); + OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is()); +} + + + + +Button::~Button (void) +{ +} + + + + +void Button::Initialize (void) +{ + mpToolBar->GetPresenterController()->GetWindowManager()->AddLayoutListener(this); + mbIsListenerRegistered = true; +} + + + + +void Button::disposing (void) +{ + OSL_ASSERT(mpToolBar.get() != NULL); + if (mpToolBar.get() != NULL + && mbIsListenerRegistered) + { + OSL_ASSERT(mpToolBar->GetPresenterController().is()); + OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is()); + + mbIsListenerRegistered = false; + mpToolBar->GetPresenterController()->GetWindowManager()->RemoveLayoutListener(this); + } + Element::disposing(); +} + + + + +void Button::Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState) +{ + OSL_ASSERT(rxCanvas.is()); + + if (mpMode.get() == NULL) + return; + + if (mpMode->mpIcon.get() == NULL) + return; + + geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas)); + sal_Int32 nTextHeight (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1)); + + PaintIcon(rxCanvas, nTextHeight, rViewState); + awt::Point aOffset(0,0); + if ( ! IsEnabled()) + if (mpMode->mpIcon.get() != NULL) + { + Reference<rendering::XBitmap> xBitmap (mpMode->mpIcon->GetNormalBitmap()); + if (xBitmap.is()) + aOffset.Y = xBitmap->getSize().Height; + } + mpMode->maText.Paint(rxCanvas, rViewState, GetBoundingBox(), aOffset); +} + + + + +awt::Size Button::CreateBoundingSize ( + const Reference<rendering::XCanvas>& rxCanvas) +{ + if (mpMode.get() == NULL) + return awt::Size(); + + geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas)); + const sal_Int32 nGap (5); + sal_Int32 nTextHeight (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1)); + sal_Int32 nTextWidth (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.X2 - aTextBBox.X1)); + Reference<rendering::XBitmap> xBitmap; + if (mpMode->mpIcon.get() != NULL) + xBitmap = mpMode->mpIcon->GetNormalBitmap(); + if (xBitmap.is()) + { + geometry::IntegerSize2D aSize (xBitmap->getSize()); + return awt::Size( + ::std::max(aSize.Width, sal_Int32(0.5 + aTextBBox.X2 - aTextBBox.X1)), + aSize.Height+ nGap + nTextHeight); + } + else + return awt::Size(nTextWidth,nTextHeight); +} + + + + +void Button::PaintIcon ( + const Reference<rendering::XCanvas>& rxCanvas, + const sal_Int32 nTextHeight, + const rendering::ViewState& rViewState) +{ + if (mpMode.get() == NULL) + return; + + Reference<rendering::XBitmap> xBitmap (mpMode->mpIcon->GetBitmap(GetMode())); + if (xBitmap.is()) + { + const sal_Int32 nX (maLocation.X + + (maSize.Width-xBitmap->getSize().Width) / 2); + const sal_Int32 nY (maLocation.Y + + (maSize.Height - nTextHeight - xBitmap->getSize().Height) / 2); + const rendering::RenderState aRenderState( + geometry::AffineMatrix2D(1,0,nX, 0,1,nY), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::OVER); + rxCanvas->drawBitmap(xBitmap, rViewState, aRenderState); + } +} + + + + +PresenterBitmapDescriptor::Mode Button::GetMode (void) const +{ + if ( ! IsEnabled()) + return PresenterBitmapDescriptor::Disabled; + else if (mbIsPressed) + return PresenterBitmapDescriptor::ButtonDown; + else if (mbIsOver) + return PresenterBitmapDescriptor::MouseOver; + else + return PresenterBitmapDescriptor::Normal; +} + + + + +//----- lang::XEventListener -------------------------------------------------- + +void SAL_CALL Button::disposing (const css::lang::EventObject& rEvent) + throw(css::uno::RuntimeException) +{ + (void)rEvent; + mbIsListenerRegistered = false; + Element::disposing(rEvent); +} + +} // end of anonymous namespace + + + + +//===== PresenterToolBar::Label =============================================== + +namespace { + +Label::Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar) + : Element(rpToolBar) +{ +} + + + + +awt::Size Label::CreateBoundingSize ( + const Reference<rendering::XCanvas>& rxCanvas) +{ + if (mpMode.get() == NULL) + return awt::Size(0,0); + + geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas)); + return awt::Size( + sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.X2 - aTextBBox.X1), + sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1)); +} + + + + + +void Label::SetText (const OUString& rsText) +{ + OSL_ASSERT(mpToolBar.get() != NULL); + if (mpMode.get() == NULL) + return; + + const bool bRequestLayout (mpMode->maText.GetText().getLength() != rsText.getLength()); + + mpMode->maText.SetText(rsText); + // Just use the character count for determing whether a layout is + // necessary. This is an optimization to avoid layouts every time a new + // time value is set on some labels. + if (bRequestLayout) + mpToolBar->RequestLayout(); + else + Invalidate(false); +} + + + + +void Label::Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState) +{ + OSL_ASSERT(rxCanvas.is()); + if (mpMode.get() == NULL) + return; + + mpMode->maText.Paint(rxCanvas, rViewState, GetBoundingBox(), awt::Point(0,0)); +} + + + + +bool Label::SetState (const bool bIsOver, const bool bIsPressed) +{ + // For labels there is no mouse over effect. + (void)bIsOver; + (void)bIsPressed; + return Element::SetState(false, false); +} + +} // end of anonymous namespace + + + + +//===== Text ================================================================== + +namespace { + +Text::Text (void) + : msText(), + mpFont() +{ +} + + + + +Text::Text (const Text& rText) + : msText(rText.msText), + mpFont(rText.mpFont) +{ +} + + + + +Text::Text ( + const OUString& rsText, + const PresenterTheme::SharedFontDescriptor& rpFont) + : msText(rsText), + mpFont(rpFont) +{ +} + + + + +void Text::SetText (const OUString& rsText) +{ + msText = rsText; +} + + + + +OUString Text::GetText (void) const +{ + return msText; +} + + + + +PresenterTheme::SharedFontDescriptor Text::GetFont (void) const +{ + return mpFont; +} + + + + +void Text::Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState, + const awt::Rectangle& rBoundingBox, + const awt::Point& rOffset) +{ + (void)rOffset; + OSL_ASSERT(rxCanvas.is()); + + if (msText.getLength() <= 0) + return; + if (mpFont.get() == NULL) + return; + + if ( ! mpFont->mxFont.is()) + mpFont->PrepareFont(rxCanvas); + if ( ! mpFont->mxFont.is()) + return; + + rendering::StringContext aContext (msText, 0, msText.getLength()); + + Reference<rendering::XTextLayout> xLayout ( + mpFont->mxFont->createTextLayout( + aContext, + rendering::TextDirection::WEAK_LEFT_TO_RIGHT, + 0)); + + geometry::RealRectangle2D aBox (xLayout->queryTextBounds()); + const double nTextWidth = aBox.X2 - aBox.X1; + const double nY = rBoundingBox.Y + rBoundingBox.Height - aBox.Y2; + const double nX = rBoundingBox.X + (rBoundingBox.Width - nTextWidth)/2; + + rendering::RenderState aRenderState( + geometry::AffineMatrix2D(1,0,nX, 0,1,nY), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor); + + rxCanvas->drawText( + aContext, + mpFont->mxFont, + rViewState, + aRenderState, + rendering::TextDirection::WEAK_LEFT_TO_RIGHT); +} + + + + +geometry::RealRectangle2D Text::GetBoundingBox (const Reference<rendering::XCanvas>& rxCanvas) +{ + if (mpFont.get() != NULL && msText.getLength() > 0) + { + if ( ! mpFont->mxFont.is()) + mpFont->PrepareFont(rxCanvas); + if (mpFont->mxFont.is()) + { + rendering::StringContext aContext (msText, 0, msText.getLength()); + Reference<rendering::XTextLayout> xLayout ( + mpFont->mxFont->createTextLayout( + aContext, + rendering::TextDirection::WEAK_LEFT_TO_RIGHT, + 0)); + return xLayout->queryTextBounds(); + } + } + return geometry::RealRectangle2D(0,0,0,0); +} + + + + +//===== ProgressLabel ========================================================= + +ProgressLabel::ProgressLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar) + : Label(rpToolBar) +{ + SetText(A2S("-/-")); +} + + + + +void ProgressLabel::CurrentSlideHasChanged (void) +{ + Label::CurrentSlideHasChanged(); + OSL_ASSERT(mpToolBar.is()); + try + { + const sal_Int32 nCurrentSlideIndex (mpToolBar->GetCurrentSlideIndex() + 1); + const sal_Int32 nSlideCount (mpToolBar->GetSlideCount()); + if (nCurrentSlideIndex >= 0 && nSlideCount > 0) + SetText( + OUString::valueOf(nCurrentSlideIndex) + + OUString(RTL_CONSTASCII_USTRINGPARAM(" / ")) + + OUString::valueOf(nSlideCount)); + else + SetText(A2S("")); + Invalidate(); + } + catch (RuntimeException&) + { + } +} + + + + +//===== TimeFormatter ========================================================= + +TimeFormatter::TimeFormatter (void) + : mbIs24HourFormat(true), + mbIsAmPmFormat(false), + mbIsShowSeconds(true) +{ +} + + + + +OUString TimeFormatter::FormatTime (const oslDateTime& rTime) +{ + ::rtl::OUStringBuffer sText; + + const sal_Int32 nHours (sal::static_int_cast<sal_Int32>(rTime.Hours)); + const sal_Int32 nMinutes (sal::static_int_cast<sal_Int32>(rTime.Minutes)); + const sal_Int32 nSeconds(sal::static_int_cast<sal_Int32>(rTime.Seconds)); + + // Hours + if (mbIs24HourFormat) + sText.append(OUString::valueOf(nHours)); + else + sText.append(OUString::valueOf( + sal::static_int_cast<sal_Int32>(nHours>12 ? nHours-12 : nHours))); + + sText.append(A2S(":")); + + // Minutes + const OUString sMinutes (OUString::valueOf(nMinutes)); + if (sMinutes.getLength() == 1) + sText.append(A2S("0")); + sText.append(sMinutes); + + // Seconds + if (mbIsShowSeconds) + { + sText.append(A2S(":")); + const OUString sSeconds (OUString::valueOf(nSeconds)); + if (sSeconds.getLength() == 1) + sText.append(A2S("0")); + sText.append(sSeconds); + } + + if (mbIsAmPmFormat) + { + if (rTime.Hours < 12) + sText.append(A2S("am")); + else + sText.append(A2S("pm")); + } + return sText.makeStringAndClear(); +} + + + + +//===== TimeLabel ============================================================= + +TimeLabel::TimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar) + : Label(rpToolBar), + mpListener() +{ +} + + + + +void SAL_CALL TimeLabel::disposing (void) +{ + PresenterClockTimer::Instance(mpToolBar->GetComponentContext())->RemoveListener(mpListener); + mpListener.reset(); +} + + + + +void TimeLabel::ConnectToTimer (void) +{ + mpListener.reset(new Listener(this)); + PresenterClockTimer::Instance(mpToolBar->GetComponentContext())->AddListener(mpListener); +} + + + + +//===== CurrentTimeLabel ====================================================== + +::rtl::Reference<Element> CurrentTimeLabel::Create ( + const ::rtl::Reference<PresenterToolBar>& rpToolBar) +{ + ::rtl::Reference<TimeLabel> pElement(new CurrentTimeLabel(rpToolBar)); + pElement->ConnectToTimer(); + return ::rtl::Reference<Element>(pElement.get()); +} + + + + +CurrentTimeLabel::~CurrentTimeLabel (void) +{ +} + + + + +CurrentTimeLabel::CurrentTimeLabel ( + const ::rtl::Reference<PresenterToolBar>& rpToolBar) + : TimeLabel(rpToolBar), + maTimeFormatter() +{ +} + + + + +void CurrentTimeLabel::TimeHasChanged (const oslDateTime& rCurrentTime) +{ + SetText(maTimeFormatter.FormatTime(rCurrentTime)); + Invalidate(false); +} + + + + +void CurrentTimeLabel::SetModes ( + const SharedElementMode& rpNormalMode, + const SharedElementMode& rpMouseOverMode, + const SharedElementMode& rpSelectedMode, + const SharedElementMode& rpDisabledMode) +{ + TimeLabel::SetModes(rpNormalMode, rpMouseOverMode, rpSelectedMode, rpDisabledMode); + SetText(maTimeFormatter.FormatTime(PresenterClockTimer::GetCurrentTime())); +} + + + + +//===== PresentationTimeLabel ================================================= + +::rtl::Reference<Element> PresentationTimeLabel::Create ( + const ::rtl::Reference<PresenterToolBar>& rpToolBar) +{ + ::rtl::Reference<TimeLabel> pElement(new PresentationTimeLabel(rpToolBar)); + pElement->ConnectToTimer(); + return ::rtl::Reference<Element>(pElement.get()); +} + + + + +PresentationTimeLabel::~PresentationTimeLabel (void) +{ +} + + + + +PresentationTimeLabel::PresentationTimeLabel ( + const ::rtl::Reference<PresenterToolBar>& rpToolBar) + : TimeLabel(rpToolBar), + maTimeFormatter(), + maStartTimeValue() +{ + maStartTimeValue.Seconds = 0; + maStartTimeValue.Nanosec = 0; +} + + + + +void PresentationTimeLabel::TimeHasChanged (const oslDateTime& rCurrentTime) +{ + TimeValue aCurrentTimeValue; + if (osl_getTimeValueFromDateTime(const_cast<oslDateTime*>(&rCurrentTime), &aCurrentTimeValue)) + { + if (maStartTimeValue.Seconds==0 && maStartTimeValue.Nanosec==0) + { + // This method is called for the first time. Initialize the + // start time. The start time is rounded to nearest second to + // keep the time updates synchronized with the current time label. + maStartTimeValue = aCurrentTimeValue; + if (maStartTimeValue.Nanosec >= 500000000) + maStartTimeValue.Seconds += 1; + maStartTimeValue.Nanosec = 0; + } + + TimeValue aElapsedTimeValue; + aElapsedTimeValue.Seconds = aCurrentTimeValue.Seconds - maStartTimeValue.Seconds; + aElapsedTimeValue.Nanosec = aCurrentTimeValue.Nanosec - maStartTimeValue.Nanosec; + + oslDateTime aElapsedDateTime; + if (osl_getDateTimeFromTimeValue(&aElapsedTimeValue, &aElapsedDateTime)) + { + SetText(maTimeFormatter.FormatTime(aElapsedDateTime)); + Invalidate(false); + } + } +} + + + +void PresentationTimeLabel::SetModes ( + const SharedElementMode& rpNormalMode, + const SharedElementMode& rpMouseOverMode, + const SharedElementMode& rpSelectedMode, + const SharedElementMode& rpDisabledMode) +{ + TimeLabel::SetModes(rpNormalMode, rpMouseOverMode, rpSelectedMode, rpDisabledMode); + + oslDateTime aStartDateTime; + if (osl_getDateTimeFromTimeValue(&maStartTimeValue, &aStartDateTime)) + { + SetText(maTimeFormatter.FormatTime(aStartDateTime)); + } +} + + + + +//===== VerticalSeparator ===================================================== + +VerticalSeparator::VerticalSeparator ( + const ::rtl::Reference<PresenterToolBar>& rpToolBar) + : Element(rpToolBar) +{ +} + + + + +void VerticalSeparator::Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState) +{ + OSL_ASSERT(rxCanvas.is()); + + awt::Rectangle aBBox (GetBoundingBox()); + + rendering::RenderState aRenderState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::OVER); + if (mpMode.get() != NULL) + { + PresenterTheme::SharedFontDescriptor pFont (mpMode->maText.GetFont()); + if (pFont.get() != NULL) + PresenterCanvasHelper::SetDeviceColor(aRenderState, pFont->mnColor); + } + + if (aBBox.Height >= gnMinimalSeparatorSize + 2*gnSeparatorInset) + { + aBBox.Height -= 2*gnSeparatorInset; + aBBox.Y += gnSeparatorInset; + } + rxCanvas->fillPolyPolygon( + PresenterGeometryHelper::CreatePolygon(aBBox, rxCanvas->getDevice()), + rViewState, + aRenderState); +} + + + + +awt::Size VerticalSeparator::CreateBoundingSize ( + const Reference<rendering::XCanvas>& rxCanvas) +{ + (void)rxCanvas; + return awt::Size(1,20); +} + + + + +bool VerticalSeparator::IsFilling (void) const +{ + return true; +} + + + + +//===== HorizontalSeparator =================================================== + +HorizontalSeparator::HorizontalSeparator ( + const ::rtl::Reference<PresenterToolBar>& rpToolBar) + : Element(rpToolBar) +{ +} + + + + +void HorizontalSeparator::Paint ( + const Reference<rendering::XCanvas>& rxCanvas, + const rendering::ViewState& rViewState) +{ + OSL_ASSERT(rxCanvas.is()); + + awt::Rectangle aBBox (GetBoundingBox()); + + rendering::RenderState aRenderState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::OVER); + if (mpMode.get() != NULL) + { + PresenterTheme::SharedFontDescriptor pFont (mpMode->maText.GetFont()); + if (pFont.get() != NULL) + PresenterCanvasHelper::SetDeviceColor(aRenderState, pFont->mnColor); + } + + if (aBBox.Width >= gnMinimalSeparatorSize+2*gnSeparatorInset) + { + aBBox.Width -= 2*gnSeparatorInset; + aBBox.X += gnSeparatorInset; + } + rxCanvas->fillPolyPolygon( + PresenterGeometryHelper::CreatePolygon(aBBox, rxCanvas->getDevice()), + rViewState, + aRenderState); +} + + + + +awt::Size HorizontalSeparator::CreateBoundingSize ( + const Reference<rendering::XCanvas>& rxCanvas) +{ + (void)rxCanvas; + return awt::Size(20,1); +} + + + + +bool HorizontalSeparator::IsFilling (void) const +{ + return true; +} + + + + +} // end of anonymous namespace + + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterToolBar.hxx b/sdext/source/presenter/PresenterToolBar.hxx new file mode 100644 index 000000000000..d4dbf2ac1048 --- /dev/null +++ b/sdext/source/presenter/PresenterToolBar.hxx @@ -0,0 +1,318 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_TOOL_BAR_HXX +#define SDEXT_PRESENTER_TOOL_BAR_HXX + +#include "PresenterController.hxx" +#include "PresenterViewFactory.hxx" + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase3.hxx> +#include <cppuhelper/compbase5.hxx> +#include <com/sun/star/awt/ActionEvent.hpp> +#include <com/sun/star/awt/XActionListener.hpp> +#include <com/sun/star/awt/XButton.hpp> +#include <com/sun/star/awt/XControl.hpp> +#include <com/sun/star/awt/XControlContainer.hpp> +#include <com/sun/star/awt/XFixedText.hpp> +#include <com/sun/star/awt/XMouseListener.hpp> +#include <com/sun/star/awt/XMouseMotionListener.hpp> +#include <com/sun/star/awt/XPaintListener.hpp> +#include <com/sun/star/awt/XWindowListener.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/drawing/XDrawView.hpp> +#include <com/sun/star/drawing/XPresenterHelper.hpp> +#include <com/sun/star/drawing/framework/XView.hpp> +#include <com/sun/star/drawing/framework/XResourceId.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <map> +#include <boost/scoped_ptr.hpp> +#include <boost/function.hpp> +#include <boost/noncopyable.hpp> + +namespace css = ::com::sun::star; + +namespace { + typedef cppu::WeakComponentImplHelper5< + css::awt::XWindowListener, + css::awt::XPaintListener, + css::awt::XMouseListener, + css::awt::XMouseMotionListener, + css::drawing::XDrawView + > PresenterToolBarInterfaceBase; + + typedef cppu::WeakComponentImplHelper3< + css::awt::XPaintListener, + css::drawing::framework::XView, + css::drawing::XDrawView + > PresenterToolBarViewInterfaceBase; +} + +namespace sdext { namespace presenter { + +/** A simple tool bar that can display bitmapped buttons and labels. At the + moment there are buttons for moving to the next and previous slide and + to the next effect. A label displayes the index of the current slide + and the total number of slides. +*/ +class PresenterToolBar + : private ::cppu::BaseMutex, + private ::boost::noncopyable, + public PresenterToolBarInterfaceBase, + public CachablePresenterView +{ +public: + typedef ::boost::function<void(void)> Action; + + enum Anchor { Left, Center, Right }; + + PresenterToolBar ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::awt::XWindow>& rxWindow, + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const ::rtl::Reference<PresenterController>& rpPresenterController, + const Anchor eAnchor); + virtual ~PresenterToolBar (void); + + void Initialize ( + const ::rtl::OUString& rsConfigurationPath); + + virtual void SAL_CALL disposing (void); + + void InvalidateArea ( + const css::awt::Rectangle& rRepaintBox, + const bool bSynchronous); + sal_Int32 GetSlideCount (void); + sal_Int32 GetCurrentSlideIndex (void); + void RequestLayout (void); + css::geometry::RealSize2D GetSize (void); + css::geometry::RealSize2D GetMinimalSize (void); + ::rtl::Reference<PresenterController> GetPresenterController (void) const; + css::uno::Reference<css::awt::XWindow> GetWindow (void) const; + css::uno::Reference<css::uno::XComponentContext> GetComponentContext (void) const; + + // lang::XEventListener + + virtual void SAL_CALL + disposing (const css::lang::EventObject& rEventObject) + throw (css::uno::RuntimeException); + + + // XWindowListener + + virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // XPaintListener + + virtual void SAL_CALL windowPaint (const css::awt::PaintEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XMouseListener + + virtual void SAL_CALL mousePressed (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseReleased (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseEntered (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseExited (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XMouseMotionListener + + virtual void SAL_CALL mouseMoved (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL mouseDragged (const css::awt::MouseEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XDrawView + + virtual void SAL_CALL setCurrentPage ( + const css::uno::Reference<css::drawing::XDrawPage>& rxSlide) + throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::drawing::XDrawPage> SAL_CALL getCurrentPage (void) + throw (css::uno::RuntimeException); + + class Context; + +private: + css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + + class ElementContainerPart; + typedef ::boost::shared_ptr<ElementContainerPart> SharedElementContainerPart; + typedef ::std::vector<SharedElementContainerPart> ElementContainer; + ElementContainer maElementContainer; + SharedElementContainerPart mpCurrentContainerPart; + css::uno::Reference<css::awt::XWindow> mxWindow; + css::uno::Reference<css::rendering::XCanvas> mxCanvas; + css::uno::Reference<css::presentation::XSlideShowController> mxSlideShowController; + css::uno::Reference<css::drawing::XDrawPage> mxCurrentSlide; + ::rtl::Reference<PresenterController> mpPresenterController; + bool mbIsLayoutPending; + const Anchor meAnchor; + css::geometry::RealRectangle2D maBoundingBox; + /** The minimal size that is necessary to display all elements without + overlap and with minimal gaps between them. + */ + css::geometry::RealSize2D maMinimalSize; + + void CreateControls ( + const ::rtl::OUString& rsConfigurationPath); + void Layout (const css::uno::Reference<css::rendering::XCanvas>& rxCanvas); + css::geometry::RealSize2D CalculatePartSize ( + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const SharedElementContainerPart& rpPart, + const bool bIsHorizontal); + void LayoutPart ( + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const SharedElementContainerPart& rpPart, + const css::geometry::RealRectangle2D& rBoundingBox, + const css::geometry::RealSize2D& rPartSize, + const bool bIsHorizontal); + void Clear ( + const css::awt::Rectangle& rUpdateBox, + const css::rendering::ViewState& rViewState); + void Paint ( + const css::awt::Rectangle& rUpdateBox, + const css::rendering::ViewState& rViewState); + + void UpdateSlideNumber (void); + + void CheckMouseOver ( + const css::awt::MouseEvent& rEvent, + const bool bOverWindow, + const bool bMouseDown=false); + + void ProcessEntry ( + const ::css::uno::Reference<css::beans::XPropertySet>& rProperties, + Context& rContext); + + /** This method throws a DisposedException when the object has already been + disposed. + */ + void ThrowIfDisposed (void) const + throw (css::lang::DisposedException); +}; + + + + +/** View for the PresenterToolBar. +*/ +class PresenterToolBarView + : private ::cppu::BaseMutex, + private ::boost::noncopyable, + public PresenterToolBarViewInterfaceBase +{ +public: + explicit PresenterToolBarView ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId, + const css::uno::Reference<css::frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~PresenterToolBarView (void); + + virtual void SAL_CALL disposing (void); + + ::rtl::Reference<PresenterToolBar> GetPresenterToolBar (void) const; + + + // XPaintListener + + virtual void SAL_CALL windowPaint (const css::awt::PaintEvent& rEvent) + throw (css::uno::RuntimeException); + + + // lang::XEventListener + + virtual void SAL_CALL + disposing (const css::lang::EventObject& rEventObject) + throw (css::uno::RuntimeException); + + + // XResourceId + + virtual css::uno::Reference<css::drawing::framework::XResourceId> SAL_CALL getResourceId (void) + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isAnchorOnly (void) + throw (com::sun::star::uno::RuntimeException); + + + // XDrawView + + virtual void SAL_CALL setCurrentPage ( + const css::uno::Reference<css::drawing::XDrawPage>& rxSlide) + throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::drawing::XDrawPage> SAL_CALL getCurrentPage (void) + throw (css::uno::RuntimeException); + +private: + // css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + css::uno::Reference<css::drawing::framework::XPane> mxPane; + css::uno::Reference<css::drawing::framework::XResourceId> mxViewId; + css::uno::Reference<css::awt::XWindow> mxWindow; + css::uno::Reference<css::rendering::XCanvas> mxCanvas; + ::rtl::Reference<PresenterController> mpPresenterController; + css::uno::Reference<css::presentation::XSlideShowController> mxSlideShowController; + ::rtl::Reference<PresenterToolBar> mpToolBar; + + /** This method throws a DisposedException when the object has already been + disposed. + */ + void ThrowIfDisposed (void) const + throw (css::lang::DisposedException); +}; + +} } // end of namespace ::sdext::presenter + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterUIPainter.cxx b/sdext/source/presenter/PresenterUIPainter.cxx new file mode 100644 index 000000000000..d5a5066989d8 --- /dev/null +++ b/sdext/source/presenter/PresenterUIPainter.cxx @@ -0,0 +1,259 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterUIPainter.hxx" + +#include "PresenterCanvasHelper.hxx" +#include "PresenterGeometryHelper.hxx" +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/XPolyPolygon2D.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace sdext { namespace presenter { + + +void PresenterUIPainter::PaintHorizontalBitmapComposite ( + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRepaintBox, + const css::awt::Rectangle& rBoundingBox, + const css::uno::Reference<css::rendering::XBitmap>& rxLeftBitmap, + const css::uno::Reference<css::rendering::XBitmap>& rxRepeatableCenterBitmap, + const css::uno::Reference<css::rendering::XBitmap>& rxRightBitmap) +{ + if (PresenterGeometryHelper::AreRectanglesDisjoint(rRepaintBox, rBoundingBox)) + { + // The bounding box lies completly outside the repaint area. + // Nothing has to be repainted. + return; + } + + // Get bitmap sizes. + geometry::IntegerSize2D aLeftBitmapSize; + if (rxLeftBitmap.is()) + aLeftBitmapSize = rxLeftBitmap->getSize(); + geometry::IntegerSize2D aCenterBitmapSize; + if (rxRepeatableCenterBitmap.is()) + aCenterBitmapSize = rxRepeatableCenterBitmap->getSize(); + geometry::IntegerSize2D aRightBitmapSize; + if (rxRightBitmap.is()) + aRightBitmapSize = rxRightBitmap->getSize(); + + // Prepare painting. + rendering::ViewState aViewState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL); + + rendering::RenderState aRenderState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + + // Paint the left bitmap once. + if (rxLeftBitmap.is()) + { + const awt::Rectangle aLeftBoundingBox ( + rBoundingBox.X, + rBoundingBox.Y, + ::std::min(aLeftBitmapSize.Width, rBoundingBox.Width), + rBoundingBox.Height); + aViewState.Clip = Reference<rendering::XPolyPolygon2D>( + PresenterGeometryHelper::CreatePolygon( + PresenterGeometryHelper::Intersection(rRepaintBox, aLeftBoundingBox), + rxCanvas->getDevice())); + aRenderState.AffineTransform.m02 = aLeftBoundingBox.X; + aRenderState.AffineTransform.m12 + = aLeftBoundingBox.Y + (aLeftBoundingBox.Height - aLeftBitmapSize.Height) / 2; + rxCanvas->drawBitmap(rxLeftBitmap, aViewState, aRenderState); + } + + // Paint the right bitmap once. + if (rxRightBitmap.is()) + { + const awt::Rectangle aRightBoundingBox ( + rBoundingBox.X + rBoundingBox.Width - aRightBitmapSize.Width, + rBoundingBox.Y, + ::std::min(aRightBitmapSize.Width, rBoundingBox.Width), + rBoundingBox.Height); + aViewState.Clip = Reference<rendering::XPolyPolygon2D>( + PresenterGeometryHelper::CreatePolygon( + PresenterGeometryHelper::Intersection(rRepaintBox, aRightBoundingBox), + rxCanvas->getDevice())); + aRenderState.AffineTransform.m02 + = aRightBoundingBox.X + aRightBoundingBox.Width - aRightBitmapSize.Width; + aRenderState.AffineTransform.m12 + = aRightBoundingBox.Y + (aRightBoundingBox.Height - aRightBitmapSize.Height) / 2; + rxCanvas->drawBitmap(rxRightBitmap, aViewState, aRenderState); + } + + // Paint the center bitmap to fill the remaining space. + if (rxRepeatableCenterBitmap.is()) + { + const awt::Rectangle aCenterBoundingBox ( + rBoundingBox.X + aLeftBitmapSize.Width, + rBoundingBox.Y, + rBoundingBox.Width - aLeftBitmapSize.Width - aRightBitmapSize.Width, + rBoundingBox.Height); + if (aCenterBoundingBox.Width > 0) + { + aViewState.Clip = Reference<rendering::XPolyPolygon2D>( + PresenterGeometryHelper::CreatePolygon( + PresenterGeometryHelper::Intersection(rRepaintBox, aCenterBoundingBox), + rxCanvas->getDevice())); + sal_Int32 nX (aCenterBoundingBox.X); + const sal_Int32 nRight (aCenterBoundingBox.X + aCenterBoundingBox.Width - 1); + aRenderState.AffineTransform.m12 + = aCenterBoundingBox.Y + (aCenterBoundingBox.Height-aCenterBitmapSize.Height) / 2; + while(nX <= nRight) + { + aRenderState.AffineTransform.m02 = nX; + rxCanvas->drawBitmap(rxRepeatableCenterBitmap, aViewState, aRenderState); + nX += aCenterBitmapSize.Width; + } + } + } +} + + + + +void PresenterUIPainter::PaintVerticalBitmapComposite ( + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRepaintBox, + const css::awt::Rectangle& rBoundingBox, + const css::uno::Reference<css::rendering::XBitmap>& rxTopBitmap, + const css::uno::Reference<css::rendering::XBitmap>& rxRepeatableCenterBitmap, + const css::uno::Reference<css::rendering::XBitmap>& rxBottomBitmap) +{ + if (PresenterGeometryHelper::AreRectanglesDisjoint(rRepaintBox, rBoundingBox)) + { + // The bounding box lies completly outside the repaint area. + // Nothing has to be repainted. + return; + } + + // Get bitmap sizes. + geometry::IntegerSize2D aTopBitmapSize; + if (rxTopBitmap.is()) + aTopBitmapSize = rxTopBitmap->getSize(); + geometry::IntegerSize2D aCenterBitmapSize; + if (rxRepeatableCenterBitmap.is()) + aCenterBitmapSize = rxRepeatableCenterBitmap->getSize(); + geometry::IntegerSize2D aBottomBitmapSize; + if (rxBottomBitmap.is()) + aBottomBitmapSize = rxBottomBitmap->getSize(); + + // Prepare painting. + rendering::ViewState aViewState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL); + + rendering::RenderState aRenderState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + + // Paint the top bitmap once. + if (rxTopBitmap.is()) + { + const awt::Rectangle aTopBoundingBox ( + rBoundingBox.X, + rBoundingBox.Y, + rBoundingBox.Width, + ::std::min(aTopBitmapSize.Height, rBoundingBox.Height)); + aViewState.Clip = Reference<rendering::XPolyPolygon2D>( + PresenterGeometryHelper::CreatePolygon( + PresenterGeometryHelper::Intersection(rRepaintBox, aTopBoundingBox), + rxCanvas->getDevice())); + aRenderState.AffineTransform.m02 + = aTopBoundingBox.X + (aTopBoundingBox.Width - aTopBitmapSize.Width) / 2; + aRenderState.AffineTransform.m12 = aTopBoundingBox.Y; + rxCanvas->drawBitmap(rxTopBitmap, aViewState, aRenderState); + } + + // Paint the bottom bitmap once. + if (rxBottomBitmap.is()) + { + const sal_Int32 nBBoxHeight (::std::min(aBottomBitmapSize.Height, rBoundingBox.Height)); + const awt::Rectangle aBottomBoundingBox ( + rBoundingBox.X, + rBoundingBox.Y + rBoundingBox.Height - nBBoxHeight, + rBoundingBox.Width, + nBBoxHeight); + aViewState.Clip = Reference<rendering::XPolyPolygon2D>( + PresenterGeometryHelper::CreatePolygon( + PresenterGeometryHelper::Intersection(rRepaintBox, aBottomBoundingBox), + rxCanvas->getDevice())); + aRenderState.AffineTransform.m02 + = aBottomBoundingBox.X + (aBottomBoundingBox.Width - aBottomBitmapSize.Width) / 2; + aRenderState.AffineTransform.m12 + = aBottomBoundingBox.Y + aBottomBoundingBox.Height - aBottomBitmapSize.Height; + rxCanvas->drawBitmap(rxBottomBitmap, aViewState, aRenderState); + } + + // Paint the center bitmap to fill the remaining space. + if (rxRepeatableCenterBitmap.is()) + { + const awt::Rectangle aCenterBoundingBox ( + rBoundingBox.X, + rBoundingBox.Y + aTopBitmapSize.Height, + rBoundingBox.Width, + rBoundingBox.Height - aTopBitmapSize.Height - aBottomBitmapSize.Height); + if (aCenterBoundingBox.Height > 0) + { + aViewState.Clip = Reference<rendering::XPolyPolygon2D>( + PresenterGeometryHelper::CreatePolygon( + PresenterGeometryHelper::Intersection(rRepaintBox, aCenterBoundingBox), + rxCanvas->getDevice())); + sal_Int32 nY (aCenterBoundingBox.Y); + const sal_Int32 nBottom (aCenterBoundingBox.Y + aCenterBoundingBox.Height - 1); + aRenderState.AffineTransform.m02 + = aCenterBoundingBox.X + (aCenterBoundingBox.Width-aCenterBitmapSize.Width) / 2; + while(nY <= nBottom) + { + aRenderState.AffineTransform.m12 = nY; + rxCanvas->drawBitmap(rxRepeatableCenterBitmap, aViewState, aRenderState); + nY += aCenterBitmapSize.Height; + } + } + } +} + + + + + +} } // end of namespace sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterUIPainter.hxx b/sdext/source/presenter/PresenterUIPainter.hxx new file mode 100644 index 000000000000..52cdd5d2f4ea --- /dev/null +++ b/sdext/source/presenter/PresenterUIPainter.hxx @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_UI_PAINTER_HXX +#define SDEXT_PRESENTER_PRESENTER_UI_PAINTER_HXX + +#include "PresenterTheme.hxx" +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/rendering/XCanvas.hpp> +#include <com/sun/star/rendering/XBitmap.hpp> +#include <boost/noncopyable.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + + +/** Functions for painting UI elements. +*/ +class PresenterUIPainter + : ::boost::noncopyable +{ +public: + PresenterUIPainter (void); + ~PresenterUIPainter (void); + + static void PaintHorizontalBitmapComposite ( + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRepaintBox, + const css::awt::Rectangle& rBoundingBox, + const css::uno::Reference<css::rendering::XBitmap>& rxLeftBitmap, + const css::uno::Reference<css::rendering::XBitmap>& rxRepeatableCenterBitmap, + const css::uno::Reference<css::rendering::XBitmap>& rxRightBitmap); + + static void PaintVerticalBitmapComposite ( + const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, + const css::awt::Rectangle& rRepaintBox, + const css::awt::Rectangle& rBoundingBox, + const css::uno::Reference<css::rendering::XBitmap>& rxTopBitmap, + const css::uno::Reference<css::rendering::XBitmap>& rxRepeatableCenterBitmap, + const css::uno::Reference<css::rendering::XBitmap>& rxBottomBitmap); +}; + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterViewFactory.cxx b/sdext/source/presenter/PresenterViewFactory.cxx new file mode 100644 index 000000000000..2a33a4230254 --- /dev/null +++ b/sdext/source/presenter/PresenterViewFactory.cxx @@ -0,0 +1,656 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "PresenterViewFactory.hxx" +#include "PresenterPaneContainer.hxx" +#include "PresenterHelper.hxx" +#include "PresenterHelpView.hxx" +#include "PresenterNotesView.hxx" +#include "PresenterSlideShowView.hxx" +#include "PresenterSlidePreview.hxx" +#include "PresenterSlideSorter.hxx" +#include "PresenterToolBar.hxx" +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/drawing/framework/ResourceId.hpp> +#include <com/sun/star/drawing/framework/XControllerManager.hpp> +#include <com/sun/star/drawing/framework/XConfigurationController.hpp> +#include <com/sun/star/drawing/XDrawPages.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/XSlideSorterBase.hpp> +#include <com/sun/star/presentation/XSlideShow.hpp> +#include <com/sun/star/presentation/XSlideShowView.hpp> +#include <cppuhelper/compbase1.hxx> +#include <boost/bind.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) + +namespace sdext { namespace presenter { + +const ::rtl::OUString PresenterViewFactory::msCurrentSlidePreviewViewURL( + A2S("private:resource/view/Presenter/CurrentSlidePreview")); +const ::rtl::OUString PresenterViewFactory::msNextSlidePreviewViewURL( + A2S("private:resource/view/Presenter/NextSlidePreview")); +const ::rtl::OUString PresenterViewFactory::msNotesViewURL( + A2S("private:resource/view/Presenter/Notes")); +const ::rtl::OUString PresenterViewFactory::msToolBarViewURL( + A2S("private:resource/view/Presenter/ToolBar")); +const ::rtl::OUString PresenterViewFactory::msSlideSorterURL( + A2S("private:resource/view/Presenter/SlideSorter")); +const ::rtl::OUString PresenterViewFactory::msHelpViewURL( + A2S("private:resource/view/Presenter/Help")); + + + +//===== SimpleView ============================================================ + +namespace { + +typedef ::cppu::WeakComponentImplHelper1 <XView> SimpleViewInterfaceBase; + +class SimpleView + : private ::cppu::BaseMutex, + public SimpleViewInterfaceBase +{ +public: + SimpleView (const Reference<XResourceId>& rxViewId) + : SimpleViewInterfaceBase(m_aMutex),mxResourceId(rxViewId) {}; + virtual ~SimpleView (void) {}; + + // XView + + virtual Reference<XResourceId> SAL_CALL getResourceId (void) throw (RuntimeException) + { return mxResourceId; }; + +private: + Reference<XResourceId> mxResourceId; +}; + + + +/** By default the PresenterSlidePreview shows the preview of the current + slide. This adapter class makes it display the preview of the next + slide. +*/ +class NextSlidePreview : public PresenterSlidePreview +{ +public: + NextSlidePreview ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId, + const css::uno::Reference<css::drawing::framework::XPane>& rxAnchorPane, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterSlidePreview(rxContext, rxViewId, rxAnchorPane, rpPresenterController) + { + } + virtual ~NextSlidePreview (void) {} + virtual void SAL_CALL setCurrentPage ( + const css::uno::Reference<css::drawing::XDrawPage>& rxSlide) + throw (css::uno::RuntimeException) + { + Reference<presentation::XSlideShowController> xSlideShowController ( + mpPresenterController->GetSlideShowController()); + Reference<drawing::XDrawPage> xSlide; + if (xSlideShowController.is()) + { + const sal_Int32 nCount (xSlideShowController->getSlideCount()); + sal_Int32 nNextSlideIndex (-1); + if (xSlideShowController->getCurrentSlide() == rxSlide) + { + nNextSlideIndex = xSlideShowController->getNextSlideIndex(); + } + else + { + for (sal_Int32 nIndex=0; nIndex<nCount; ++nIndex) + { + if (rxSlide == Reference<drawing::XDrawPage>( + xSlideShowController->getSlideByIndex(nIndex), UNO_QUERY)) + { + nNextSlideIndex = nIndex + 1; + } + } + } + if (nNextSlideIndex >= 0) + { + if (nNextSlideIndex < nCount) + { + xSlide = Reference<drawing::XDrawPage>( + xSlideShowController->getSlideByIndex(nNextSlideIndex), + UNO_QUERY); + } + } + } + PresenterSlidePreview::setCurrentPage(xSlide); + } +}; + +} // end of anonymous namespace + + + + +//===== PresenterViewFactory ============================================== + +PresenterViewFactory::PresenterViewFactory ( + const Reference<uno::XComponentContext>& rxContext, + const Reference<frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterViewFactoryInterfaceBase(m_aMutex), + mxComponentContext(rxContext), + mxConfigurationController(), + mxControllerWeak(rxController), + mpPresenterController(rpPresenterController), + mpResourceCache() +{ +} + + + + +Reference<drawing::framework::XResourceFactory> PresenterViewFactory::Create ( + const Reference<uno::XComponentContext>& rxContext, + const Reference<frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController) +{ + rtl::Reference<PresenterViewFactory> pFactory ( + new PresenterViewFactory(rxContext,rxController,rpPresenterController)); + pFactory->Register(rxController); + return Reference<drawing::framework::XResourceFactory>( + static_cast<XWeak*>(pFactory.get()), UNO_QUERY); +} + + + + +void PresenterViewFactory::Register (const Reference<frame::XController>& rxController) +{ + try + { + // Get the configuration controller. + Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW); + mxConfigurationController = xCM->getConfigurationController(); + if ( ! mxConfigurationController.is()) + { + throw RuntimeException(); + } + else + { + mxConfigurationController->addResourceFactory(msCurrentSlidePreviewViewURL, this); + mxConfigurationController->addResourceFactory(msNextSlidePreviewViewURL, this); + mxConfigurationController->addResourceFactory(msNotesViewURL, this); + mxConfigurationController->addResourceFactory(msToolBarViewURL, this); + mxConfigurationController->addResourceFactory(msSlideSorterURL, this); + mxConfigurationController->addResourceFactory(msHelpViewURL, this); + } + } + catch (RuntimeException&) + { + OSL_ASSERT(false); + if (mxConfigurationController.is()) + mxConfigurationController->removeResourceFactoryForReference(this); + mxConfigurationController = NULL; + + throw; + } +} + + + + +PresenterViewFactory::~PresenterViewFactory (void) +{ +} + + + + +void SAL_CALL PresenterViewFactory::disposing (void) + throw (RuntimeException) +{ + if (mxConfigurationController.is()) + mxConfigurationController->removeResourceFactoryForReference(this); + mxConfigurationController = NULL; + + if (mpResourceCache.get() != NULL) + { + // Dispose all views in the cache. + ResourceContainer::const_iterator iView (mpResourceCache->begin()); + ResourceContainer::const_iterator iEnd (mpResourceCache->end()); + for ( ; iView!=iEnd; ++iView) + { + try + { + Reference<lang::XComponent> xComponent (iView->second.first, UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + } + catch (lang::DisposedException&) + { + } + } + mpResourceCache.reset(); + } +} + + + + +//----- XViewFactory ---------------------------------------------------------- + +Reference<XResource> SAL_CALL PresenterViewFactory::createResource ( + const Reference<XResourceId>& rxViewId) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + Reference<XResource> xView; + + if (rxViewId.is()) + { + Reference<XPane> xAnchorPane ( + mxConfigurationController->getResource(rxViewId->getAnchor()), + UNO_QUERY_THROW); + xView = GetViewFromCache(rxViewId, xAnchorPane); + if (xView == NULL) + xView = CreateView(rxViewId, xAnchorPane); + + // Activate the view. + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPresenterController->GetPaneContainer()->FindPaneId(rxViewId->getAnchor())); + if (pDescriptor.get() != NULL) + pDescriptor->SetActivationState(true); + } + + return xView; +} + + + + +void SAL_CALL PresenterViewFactory::releaseResource (const Reference<XResource>& rxView) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + if ( ! rxView.is()) + return; + + // Deactivate the view. + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPresenterController->GetPaneContainer()->FindPaneId( + rxView->getResourceId()->getAnchor())); + if (pDescriptor.get() != NULL) + pDescriptor->SetActivationState(false); + + // Dispose only views that we can not put into the cache. + CachablePresenterView* pView = dynamic_cast<CachablePresenterView*>(rxView.get()); + if (pView == NULL || mpResourceCache.get()==NULL) + { + try + { + if (pView != NULL) + pView->ReleaseView(); + Reference<lang::XComponent> xComponent (rxView, UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + } + catch (lang::DisposedException&) + { + // Do not let disposed exceptions get out. It might be interpreted + // as coming from the factory, which would then be removed from the + // drawing framework. + } + } + else + { + // Put cachable views in the cache. + Reference<XResourceId> xViewId (rxView->getResourceId()); + if (xViewId.is()) + { + Reference<XPane> xAnchorPane ( + mxConfigurationController->getResource(xViewId->getAnchor()), + UNO_QUERY_THROW); + (*mpResourceCache)[xViewId->getResourceURL()] + = ViewResourceDescriptor(Reference<XView>(rxView, UNO_QUERY), xAnchorPane); + pView->DeactivatePresenterView(); + } + } +} + + + + +//----------------------------------------------------------------------------- + +Reference<XResource> PresenterViewFactory::GetViewFromCache( + const Reference<XResourceId>& rxViewId, + const Reference<XPane>& rxAnchorPane) const +{ + if (mpResourceCache.get() == NULL) + return NULL; + + try + { + const OUString sResourceURL (rxViewId->getResourceURL()); + + // Can we use a view from the cache? + ResourceContainer::const_iterator iView (mpResourceCache->find(sResourceURL)); + if (iView != mpResourceCache->end()) + { + // The view is in the container but it can only be used if + // the anchor pane is the same now as it was at creation of + // the view. + if (iView->second.second == rxAnchorPane) + { + CachablePresenterView* pView + = dynamic_cast<CachablePresenterView*>(iView->second.first.get()); + if (pView != NULL) + pView->ActivatePresenterView(); + return Reference<XResource>(iView->second.first, UNO_QUERY); + } + + // Right view, wrong pane. Create a new view. + } + } + catch (RuntimeException&) + { + } + return NULL; +} + + + + +Reference<XResource> PresenterViewFactory::CreateView( + const Reference<XResourceId>& rxViewId, + const Reference<XPane>& rxAnchorPane) +{ + Reference<XView> xView; + + try + { + const OUString sResourceURL (rxViewId->getResourceURL()); + + if (sResourceURL.equals(msCurrentSlidePreviewViewURL)) + { + xView = CreateSlideShowView(rxViewId); + } + else if (sResourceURL.equals(msNotesViewURL)) + { + xView = CreateNotesView(rxViewId, rxAnchorPane); + } + else if (sResourceURL.equals(msNextSlidePreviewViewURL)) + { + xView = CreateSlidePreviewView(rxViewId, rxAnchorPane); + } + else if (sResourceURL.equals(msToolBarViewURL)) + { + xView = CreateToolBarView(rxViewId); + } + else if (sResourceURL.equals(msSlideSorterURL)) + { + xView = CreateSlideSorterView(rxViewId); + } + else if (sResourceURL.equals(msHelpViewURL)) + { + xView = CreateHelpView(rxViewId); + } + + // Activate it. + CachablePresenterView* pView = dynamic_cast<CachablePresenterView*>(xView.get()); + if (pView != NULL) + pView->ActivatePresenterView(); + } + catch (RuntimeException&) + { + xView = NULL; + } + + return Reference<XResource>(xView, UNO_QUERY); +} + + + + +Reference<XView> PresenterViewFactory::CreateSlideShowView( + const Reference<XResourceId>& rxViewId) const +{ + Reference<XView> xView; + + if ( ! mxConfigurationController.is()) + return xView; + if ( ! mxComponentContext.is()) + return xView; + + try + { + rtl::Reference<PresenterSlideShowView> pShowView ( + new PresenterSlideShowView( + mxComponentContext, + rxViewId, + Reference<frame::XController>(mxControllerWeak), + mpPresenterController)); + pShowView->LateInit(); + xView = Reference<XView>(pShowView.get()); + } + catch (RuntimeException&) + { + xView = NULL; + } + + return xView; +} + + + + +Reference<XView> PresenterViewFactory::CreateSlidePreviewView( + const Reference<XResourceId>& rxViewId, + const Reference<XPane>& rxAnchorPane) const +{ + Reference<XView> xView; + + if ( ! mxConfigurationController.is()) + return xView; + if ( ! mxComponentContext.is()) + return xView; + + try + { + xView = Reference<XView>( + static_cast<XWeak*>(new NextSlidePreview( + mxComponentContext, + rxViewId, + rxAnchorPane, + mpPresenterController)), + UNO_QUERY_THROW); + } + catch (RuntimeException&) + { + xView = NULL; + } + + return xView; +} + + + + +Reference<XView> PresenterViewFactory::CreateToolBarView( + const Reference<XResourceId>& rxViewId) const +{ + return new PresenterToolBarView( + mxComponentContext, + rxViewId, + Reference<frame::XController>(mxControllerWeak), + mpPresenterController); +} + + + + +Reference<XView> PresenterViewFactory::CreateNotesView( + const Reference<XResourceId>& rxViewId, + const Reference<XPane>& rxAnchorPane) const +{ + (void)rxAnchorPane; + Reference<XView> xView; + + if ( ! mxConfigurationController.is()) + return xView; + if ( ! mxComponentContext.is()) + return xView; + + try + { + xView = Reference<XView>(static_cast<XWeak*>( + new PresenterNotesView( + mxComponentContext, + rxViewId, + Reference<frame::XController>(mxControllerWeak), + mpPresenterController)), + UNO_QUERY_THROW); + } + catch (RuntimeException&) + { + xView = NULL; + } + + return xView; +} + + + + +Reference<XView> PresenterViewFactory::CreateSlideSorterView( + const Reference<XResourceId>& rxViewId) const +{ + Reference<XView> xView; + + if ( ! mxConfigurationController.is()) + return xView; + if ( ! mxComponentContext.is()) + return xView; + + try + { + rtl::Reference<PresenterSlideSorter> pView ( + new PresenterSlideSorter( + mxComponentContext, + rxViewId, + Reference<frame::XController>(mxControllerWeak), + mpPresenterController)); + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPresenterController->GetPaneContainer()->FindPaneId(rxViewId->getAnchor())); + if (pDescriptor.get() != NULL) + pDescriptor->maActivator = ::boost::bind( + &PresenterSlideSorter::SetActiveState, pView.get(), _1); + xView = pView.get(); + } + catch (RuntimeException&) + { + xView = NULL; + } + + return xView; +} + + + + +Reference<XView> PresenterViewFactory::CreateHelpView( + const Reference<XResourceId>& rxViewId) const +{ + return Reference<XView>(new PresenterHelpView( + mxComponentContext, + rxViewId, + Reference<frame::XController>(mxControllerWeak), + mpPresenterController)); +} + + + + + +void PresenterViewFactory::ThrowIfDisposed (void) const + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterViewFactory object has already been disposed")), + const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + } +} + + + + +//===== CachablePresenterView ================================================= + +CachablePresenterView::CachablePresenterView (void) + : mbIsPresenterViewActive(true) +{ +} + + + + +void CachablePresenterView::ActivatePresenterView (void) +{ + mbIsPresenterViewActive = true; +} + + + + +void CachablePresenterView::DeactivatePresenterView (void) +{ + mbIsPresenterViewActive = false; +} + + + + +void CachablePresenterView::ReleaseView (void) +{ +} + + + +} } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterViewFactory.hxx b/sdext/source/presenter/PresenterViewFactory.hxx new file mode 100644 index 000000000000..5fab682dae8a --- /dev/null +++ b/sdext/source/presenter/PresenterViewFactory.hxx @@ -0,0 +1,189 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_VIEW_FACTORY_HXX +#define SDEXT_PRESENTER_VIEW_FACTORY_HXX + +#include "PresenterController.hxx" +#include <cppuhelper/compbase1.hxx> +#include <cppuhelper/basemutex.hxx> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/drawing/framework/XConfigurationController.hpp> +#include <com/sun/star/drawing/framework/XResourceFactory.hpp> +#include <com/sun/star/drawing/framework/XView.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <rtl/ref.hxx> +#include <boost/scoped_ptr.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +class PresenterPaneContainer; + +namespace { + typedef ::cppu::WeakComponentImplHelper1 < + css::drawing::framework::XResourceFactory + > PresenterViewFactoryInterfaceBase; +} + +/** Base class for presenter views that allows the view factory to store + them in a cache and reuse deactivated views. +*/ +class CachablePresenterView +{ +public: + virtual void ActivatePresenterView (void); + + /** Called when the view is put into a cache. The view must not paint + itself while being deactive. + */ + virtual void DeactivatePresenterView (void); + + /** Called before the view is disposed. This gives the view the + oportunity to trigger actions that may lead to (synchronous) + callbacks that do not result in DisposedExceptions. + */ + virtual void ReleaseView (void); + +protected: + bool mbIsPresenterViewActive; + + CachablePresenterView (void); +}; + + + + +/** Factory of the presenter screen specific views. The supported set of + views includes: + a life view of the current slide, + a static preview of the next slide, + the notes of the current slide, + a tool bar +*/ +class PresenterViewFactory + : public ::cppu::BaseMutex, + public PresenterViewFactoryInterfaceBase +{ +public: + static const ::rtl::OUString msCurrentSlidePreviewViewURL; + static const ::rtl::OUString msNextSlidePreviewViewURL; + static const ::rtl::OUString msNotesViewURL; + static const ::rtl::OUString msToolBarViewURL; + static const ::rtl::OUString msSlideSorterURL; + static const ::rtl::OUString msHelpViewURL; + + /** Create a new instance of this class and register it as resource + factory in the drawing framework of the given controller. + This registration keeps it alive. When the drawing framework is + shut down and releases its reference to the factory then the factory + is destroyed. + */ + static css::uno::Reference<css::drawing::framework::XResourceFactory> Create ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~PresenterViewFactory (void); + + static ::rtl::OUString getImplementationName_static (void); + static css::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static (void); + static css::uno::Reference<css::uno::XInterface> Create( + const css::uno::Reference<css::uno::XComponentContext>& rxContext) + SAL_THROW((css::uno::Exception)); + + virtual void SAL_CALL disposing (void) + throw (css::uno::RuntimeException); + + + // XResourceFactory + + virtual css::uno::Reference<css::drawing::framework::XResource> + SAL_CALL createResource ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL + releaseResource ( + const css::uno::Reference<css::drawing::framework::XResource>& rxPane) + throw (css::uno::RuntimeException); + +private: + css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + css::uno::Reference<css::drawing::framework::XConfigurationController> + mxConfigurationController; + css::uno::WeakReference<css::frame::XController> mxControllerWeak; + ::rtl::Reference<PresenterController> mpPresenterController; + typedef ::std::pair<css::uno::Reference<css::drawing::framework::XView>, + css::uno::Reference<css::drawing::framework::XPane> > ViewResourceDescriptor; + typedef ::std::map<rtl::OUString, ViewResourceDescriptor> ResourceContainer; + ::boost::scoped_ptr<ResourceContainer> mpResourceCache; + + PresenterViewFactory ( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::frame::XController>& rxController, + const ::rtl::Reference<PresenterController>& rpPresenterController); + + void Register (const css::uno::Reference<css::frame::XController>& rxController); + + css::uno::Reference<css::drawing::framework::XView> CreateSlideShowView( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId) const; + + css::uno::Reference<css::drawing::framework::XView> CreateSlidePreviewView( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId, + const css::uno::Reference<css::drawing::framework::XPane>& rxPane) const; + + css::uno::Reference<css::drawing::framework::XView> CreateToolBarView( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId) const; + + css::uno::Reference<css::drawing::framework::XView> CreateNotesView( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId, + const css::uno::Reference<css::drawing::framework::XPane>& rxPane) const; + + css::uno::Reference<css::drawing::framework::XView> CreateSlideSorterView( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId) const; + + css::uno::Reference<css::drawing::framework::XView> CreateHelpView( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId) const; + + css::uno::Reference<css::drawing::framework::XResource> GetViewFromCache ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId, + const css::uno::Reference<css::drawing::framework::XPane>& rxAnchorPane) const; + css::uno::Reference<css::drawing::framework::XResource> CreateView( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxViewId, + const css::uno::Reference<css::drawing::framework::XPane>& rxAnchorPane); + + void ThrowIfDisposed (void) const throw (::com::sun::star::lang::DisposedException); +}; + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterWindowManager.cxx b/sdext/source/presenter/PresenterWindowManager.cxx new file mode 100644 index 000000000000..466e3fe9ca25 --- /dev/null +++ b/sdext/source/presenter/PresenterWindowManager.cxx @@ -0,0 +1,1644 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#undef ENABLE_PANE_RESIZING +//#define ENABLE_PANE_RESIZING + +#include "PresenterWindowManager.hxx" +#include "PresenterAnimation.hxx" +#include "PresenterAnimator.hxx" +#include "PresenterController.hxx" +#include "PresenterGeometryHelper.hxx" +#include "PresenterHelper.hxx" +#include "PresenterPaintManager.hxx" +#include "PresenterPaneBase.hxx" +#include "PresenterPaneBorderManager.hxx" +#include "PresenterPaneBorderPainter.hxx" +#include "PresenterPaneContainer.hxx" +#include "PresenterPaneFactory.hxx" +#include "PresenterSprite.hxx" +#include "PresenterToolBar.hxx" +#include "PresenterViewFactory.hxx" +#include "PresenterTheme.hxx" +#include <com/sun/star/awt/InvalidateStyle.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/awt/SystemPointer.hpp> +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/awt/XWindow2.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/awt/WindowAttribute.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/drawing/framework/ResourceId.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/FillRule.hpp> +#include <com/sun/star/rendering/PathCapType.hpp> +#include <com/sun/star/rendering/PathJoinType.hpp> +#include <com/sun/star/rendering/Texture.hpp> +#include <com/sun/star/rendering/TexturingMode.hpp> +#include <com/sun/star/rendering/XSpriteCanvas.hpp> +#include <boost/bind.hpp> +#include <boost/bind/protect.hpp> +#include <math.h> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using ::rtl::OUString; + +#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) + +namespace sdext { namespace presenter { + +namespace { + + typedef ::cppu::WeakComponentImplHelper1< + css::drawing::framework::XConfigurationChangeListener + > ModeChangeAnimationStarterInterfaceBase; + + class ModeChangeAnimationStarter + : protected ::cppu::BaseMutex, + public ModeChangeAnimationStarterInterfaceBase + { + public: + ModeChangeAnimationStarter ( + const Reference<drawing::framework::XConfigurationController>& rxConfigurationController, + const Reference<awt::XWindow>& rxWindow, + const Reference<rendering::XSpriteCanvas>& rxCanvas, + const ::boost::shared_ptr<PresenterAnimator>& rpAnimator); + virtual ~ModeChangeAnimationStarter (void); + virtual void SAL_CALL disposing (void); + + // XConfigurationChangeListener + + virtual void SAL_CALL notifyConfigurationChange ( + const com::sun::star::drawing::framework::ConfigurationChangeEvent& rEvent) + throw (com::sun::star::uno::RuntimeException); + + + // XEventListener + + virtual void SAL_CALL disposing ( + const com::sun::star::lang::EventObject& rEvent) + throw (com::sun::star::uno::RuntimeException); + + private: + Reference<drawing::framework::XConfigurationController> mxConfigurationController; + ::boost::shared_ptr<PresenterAnimator> mpAnimator; + ::boost::shared_ptr<PresenterSprite> mpSprite; + Reference<rendering::XSpriteCanvas> mxCanvas; + }; + +} + + + + +//===== PresenterWindowManager ================================================ + +PresenterWindowManager::PresenterWindowManager ( + const Reference<XComponentContext>& rxContext, + const ::rtl::Reference<PresenterPaneContainer>& rpPaneContainer, + const ::rtl::Reference<PresenterController>& rpPresenterController) + : PresenterWindowManagerInterfaceBase(m_aMutex), + mxComponentContext(rxContext), + mpPresenterController(rpPresenterController), + mxParentWindow(), + mxParentCanvas(), + mxPaneBorderManager(), + mpPaneBorderPainter(), + mpPaneContainer(rpPaneContainer), + mbIsLayoutPending(true), + mbIsLayouting(false), + mpTheme(), + mpBackgroundBitmap(), + mxScaledBackgroundBitmap(), + maPaneBackgroundColor(), + mxClipPolygon(), + meLayoutMode(LM_Generic), + mbIsSlideSorterActive(false), + mbIsHelpViewActive(false), + maLayoutListeners(), + mbIsMouseClickPending(false) +{ + UpdateWindowList(); +} + + + + +PresenterWindowManager::~PresenterWindowManager (void) +{ +} + + + + +void SAL_CALL PresenterWindowManager::disposing (void) +{ + NotifyDisposing(); + + SetParentPane(NULL); + + Reference<lang::XComponent> xComponent (mxPaneBorderManager, UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + mxPaneBorderManager = NULL; + + PresenterPaneContainer::PaneList::const_iterator iPane; + PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end()); + for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane) + { + if ((*iPane)->mxBorderWindow.is()) + { + (*iPane)->mxBorderWindow->removeWindowListener(this); + (*iPane)->mxBorderWindow->removeFocusListener(this); +#ifndef ENABLE_PANE_RESIZING + (*iPane)->mxBorderWindow->removeMouseListener(this); +#endif + } + } +} + + + + +void PresenterWindowManager::SetParentPane ( + const Reference<drawing::framework::XPane>& rxPane) +{ + if (mxParentWindow.is()) + { + mxParentWindow->removeWindowListener(this); + mxParentWindow->removePaintListener(this); + mxParentWindow->removeMouseListener(this); + mxParentWindow->removeFocusListener(this); + } + mxParentWindow = NULL; + mxParentCanvas = NULL; + + if (rxPane.is()) + { + mxParentWindow = rxPane->getWindow(); + mxParentCanvas = rxPane->getCanvas(); + } + else + { + mxParentWindow = NULL; + } + + if (mxParentWindow.is()) + { + mxParentWindow->addWindowListener(this); + mxParentWindow->addPaintListener(this); + mxParentWindow->addMouseListener(this); + mxParentWindow->addFocusListener(this); + + // We paint our own background, make that of the parent window transparent. + Reference<awt::XWindowPeer> xPeer (mxParentWindow, UNO_QUERY); + if (xPeer.is()) + xPeer->setBackground(util::Color(0xff000000)); + } +} + + + + +void PresenterWindowManager::SetTheme (const ::boost::shared_ptr<PresenterTheme>& rpTheme) +{ + mpTheme = rpTheme; + + // Get background bitmap or background color from the theme. + + if (mpTheme.get() != NULL) + { + mpBackgroundBitmap = mpTheme->GetBitmap(OUString(), A2S("Background")); + } +} + + + + +void PresenterWindowManager::NotifyPaneCreation ( + const PresenterPaneContainer::SharedPaneDescriptor& rpDescriptor) +{ + if (rpDescriptor.get()==NULL) + { + OSL_ASSERT(rpDescriptor.get()!=NULL); + return; + } + if ( ! rpDescriptor->mxContentWindow.is()) + { + OSL_ASSERT(rpDescriptor->mxContentWindow.is()); + return; + } + + mbIsLayoutPending = true; + + Reference<awt::XWindow> xBorderWindow (rpDescriptor->mxBorderWindow); + OSL_ASSERT(xBorderWindow.is()); + if (xBorderWindow.is() && ! rpDescriptor->mbIsSprite) + { + Invalidate(); + + xBorderWindow->addWindowListener(this); + xBorderWindow->addFocusListener(this); +#ifndef ENABLE_PANE_RESIZING + xBorderWindow->addMouseListener(this); +#endif + } + + UpdateWindowList(); + Layout(); +} + + + + +void PresenterWindowManager::NotifyViewCreation (const Reference<XView>& rxView) +{ + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPaneContainer->FindPaneId(rxView->getResourceId()->getAnchor())); + OSL_ASSERT(pDescriptor.get() != NULL); + if (pDescriptor.get() != NULL) + { + Layout(); + + mpPresenterController->GetPaintManager()->Invalidate( + pDescriptor->mxContentWindow, + (sal_Int16)(awt::InvalidateStyle::TRANSPARENT + | awt::InvalidateStyle::CHILDREN)); + } +} + + + + +void PresenterWindowManager::SetPanePosSizeRelative ( + const Reference<XResourceId>& rxPaneId, + const double nRelativeX, + const double nRelativeY, + const double nRelativeWidth, + const double nRelativeHeight) +{ + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPaneContainer->FindPaneId(rxPaneId)); + if (pDescriptor.get() != NULL) + { + pDescriptor->mnLeft = nRelativeX; + pDescriptor->mnTop = nRelativeY; + pDescriptor->mnRight = nRelativeX + nRelativeWidth; + pDescriptor->mnBottom = nRelativeY + nRelativeHeight; + + mpPaneContainer->ToTop(pDescriptor); + } +} + + + + +void PresenterWindowManager::SetPanePosSizeAbsolute ( + const OUString& rsPaneURL, + const double nX, + const double nY, + const double nWidth, + const double nHeight) +{ + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPaneContainer->FindPaneURL(rsPaneURL)); + if (pDescriptor.get() != NULL) + { + awt::Rectangle aParentBox = mxParentWindow->getPosSize(); + if (aParentBox.Width > 0 && aParentBox.Height > 0) + { + pDescriptor->mnLeft = nX / aParentBox.Width; + pDescriptor->mnTop = nY / aParentBox.Height; + pDescriptor->mnRight = (nX + nWidth) / aParentBox.Width; + pDescriptor->mnBottom = (nY + nHeight) / aParentBox.Height; + } + if (pDescriptor->mxBorderWindow.is()) + pDescriptor->mxBorderWindow->setPosSize( + ::sal::static_int_cast<sal_Int32>(nX), + ::sal::static_int_cast<sal_Int32>(nY), + ::sal::static_int_cast<sal_Int32>(nWidth), + ::sal::static_int_cast<sal_Int32>(nHeight), + awt::PosSize::POSSIZE); + } +} + + + + +void PresenterWindowManager::SetPaneBorderPainter ( + const ::rtl::Reference<PresenterPaneBorderPainter>& rPainter) +{ + mpPaneBorderPainter = rPainter; +} + + + + +//----- XWindowListener ------------------------------------------------------- + +void SAL_CALL PresenterWindowManager::windowResized (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + ThrowIfDisposed(); + if (rEvent.Source == mxParentWindow) + { + Layout(); + } + else + { + Reference<awt::XWindow> xWindow (rEvent.Source,UNO_QUERY); + if (xWindow.is()) + { + UpdateWindowSize(xWindow); + + // Make sure the background of a transparent window is painted. + mpPresenterController->GetPaintManager()->Invalidate(mxParentWindow); + } + } +} + + + + +void SAL_CALL PresenterWindowManager::windowMoved (const awt::WindowEvent& rEvent) + throw (RuntimeException) +{ + ThrowIfDisposed(); + if (rEvent.Source != mxParentWindow) + { + Reference<awt::XWindow> xWindow (rEvent.Source,UNO_QUERY); + UpdateWindowSize(xWindow); + + // Make sure the background of a transparent window is painted. + mpPresenterController->GetPaintManager()->Invalidate(xWindow); + } +} + + + + +void SAL_CALL PresenterWindowManager::windowShown (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; +} + + + + +void SAL_CALL PresenterWindowManager::windowHidden (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + (void)rEvent; +} + + + + +//----- XPaintListener -------------------------------------------------------- + +void SAL_CALL PresenterWindowManager::windowPaint (const awt::PaintEvent& rEvent) + throw (RuntimeException) +{ + ThrowIfDisposed(); + + if ( ! mxParentWindow.is()) + return; + if ( ! mxParentCanvas.is()) + return; + + if (mpTheme.get()!=NULL) + { + try + { + if (mbIsLayoutPending) + Layout(); + PaintBackground(rEvent.UpdateRect); + if ( ! PaintChildren(rEvent)) + { + Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxParentCanvas, UNO_QUERY); + // if (xSpriteCanvas.is()) + // xSpriteCanvas->updateScreen(sal_False); + } + } + catch (RuntimeException&) + { + OSL_FAIL("paint failed!"); + } + } +} + + + + +//----- XMouseListener -------------------------------------------------------- + +void SAL_CALL PresenterWindowManager::mousePressed (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + (void)rEvent; + mbIsMouseClickPending = true; +} + + + + +void SAL_CALL PresenterWindowManager::mouseReleased (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ +#ifndef ENABLE_PANE_RESIZING + if (mbIsMouseClickPending) + { + mbIsMouseClickPending = false; + mpPresenterController->HandleMouseClick(rEvent); + } +#else + (void)rEvent; +#endif +} + + + + +void SAL_CALL PresenterWindowManager::mouseEntered (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + (void)rEvent; + mbIsMouseClickPending = false; +} + + + + +void SAL_CALL PresenterWindowManager::mouseExited (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException) +{ + (void)rEvent; + mbIsMouseClickPending = false; +} + + + + +//----- XFocusListener -------------------------------------------------------- + +void SAL_CALL PresenterWindowManager::focusGained (const css::awt::FocusEvent& rEvent) + throw (css::uno::RuntimeException) +{ + ThrowIfDisposed(); + (void)rEvent; + OSL_TRACE("PresenterWindowManager::focusGained window %x\n", + rEvent.Source.get()); +} + + + + +void SAL_CALL PresenterWindowManager::focusLost (const css::awt::FocusEvent& rEvent) + throw (css::uno::RuntimeException) +{ + ThrowIfDisposed(); + (void)rEvent; +} + + + + +//----- XEventListener -------------------------------------------------------- + +void SAL_CALL PresenterWindowManager::disposing (const lang::EventObject& rEvent) + throw (RuntimeException) +{ + if (rEvent.Source == mxParentWindow) + mxParentWindow = NULL; + else + { + Reference<awt::XWindow> xWindow (rEvent.Source, UNO_QUERY); + } +} + + + + +//----------------------------------------------------------------------------- + +bool PresenterWindowManager::PaintChildren (const awt::PaintEvent& rEvent) const +{ + bool bChildInvalidated (false); + + // Call windowPaint on all children that lie in or touch the + // update rectangle. + PresenterPaneContainer::PaneList::const_iterator iPane; + PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end()); + for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane) + { + try + { + // Make sure that the pane shall and can be painted. + if ( ! (*iPane)->mbIsActive) + continue; + if ((*iPane)->mbIsSprite) + continue; + if ( ! (*iPane)->mxPane.is()) + continue; + if ( ! (*iPane)->mxBorderWindow.is()) + continue; + Reference<awt::XWindow> xBorderWindow ((*iPane)->mxBorderWindow); + if ( ! xBorderWindow.is()) + continue; + + // Get the area in which the border of the pane has to be painted. + const awt::Rectangle aBorderBox (xBorderWindow->getPosSize()); + const awt::Rectangle aBorderUpdateBox( + PresenterGeometryHelper::Intersection( + rEvent.UpdateRect, + aBorderBox)); + if (aBorderUpdateBox.Width<=0 || aBorderUpdateBox.Height<=0) + continue; + + const awt::Rectangle aLocalBorderUpdateBox( + PresenterGeometryHelper::TranslateRectangle( + aBorderUpdateBox, + -aBorderBox.X, + -aBorderBox.Y)); + + // Invalidate the area of the content window. + mpPresenterController->GetPaintManager()->Invalidate( + xBorderWindow, + aLocalBorderUpdateBox, + sal_Int16(awt::InvalidateStyle::CHILDREN + | awt::InvalidateStyle::NOTRANSPARENT)); + } + catch (RuntimeException&) + { + OSL_FAIL("paint children failed!"); + } + } + + return bChildInvalidated; +} + + + + +void PresenterWindowManager::SetLayoutMode (const LayoutMode eMode) +{ + OSL_ASSERT(mpPresenterController.get() != NULL); + + if (meLayoutMode != eMode + || mbIsSlideSorterActive + || mbIsHelpViewActive) + { + meLayoutMode = eMode; + mbIsSlideSorterActive = false; + mbIsHelpViewActive = false; + + mpPresenterController->RequestViews( + mbIsSlideSorterActive, + meLayoutMode==LM_Notes, + mbIsHelpViewActive); + Layout(); + NotifyLayoutModeChange(); + } +} + + + + +PresenterWindowManager::LayoutMode PresenterWindowManager::GetLayoutMode (void) const +{ + return meLayoutMode; +} + + + + +void PresenterWindowManager::SetSlideSorterState (bool bIsActive) +{ + if (mbIsSlideSorterActive != bIsActive) + { + mbIsSlideSorterActive = bIsActive; + if (mbIsSlideSorterActive) + mbIsHelpViewActive = false; + StoreViewMode(GetViewMode()); + + mpPresenterController->RequestViews( + mbIsSlideSorterActive, + meLayoutMode==LM_Notes, + mbIsHelpViewActive); + Layout(); + NotifyLayoutModeChange(); + } +} + + + + +bool PresenterWindowManager::IsSlideSorterActive (void) const +{ + return mbIsSlideSorterActive; +} + + + + +void PresenterWindowManager::SetHelpViewState (bool bIsActive) +{ + if (mbIsHelpViewActive != bIsActive) + { + mbIsHelpViewActive = bIsActive; + if (mbIsHelpViewActive) + mbIsSlideSorterActive = false; + StoreViewMode(GetViewMode()); + + mpPresenterController->RequestViews( + mbIsSlideSorterActive, + meLayoutMode==LM_Notes, + mbIsHelpViewActive); + Layout(); + NotifyLayoutModeChange(); + } +} + + + + +bool PresenterWindowManager::IsHelpViewActive (void) const +{ + return mbIsHelpViewActive; +} + + + + +void PresenterWindowManager::SetViewMode (const ViewMode eMode) +{ + switch (eMode) + { + case VM_Standard: + SetSlideSorterState(false); + SetHelpViewState(false); + SetLayoutMode(LM_Standard); + break; + + case VM_Notes: + SetSlideSorterState(false); + SetHelpViewState(false); + SetLayoutMode(LM_Notes); + break; + + case VM_SlideOverview: + SetHelpViewState(false); + SetSlideSorterState(true); + break; + + case VM_Help: + SetHelpViewState(true); + SetSlideSorterState(false); + break; + } + + StoreViewMode(eMode); +} + + + + +PresenterWindowManager::ViewMode PresenterWindowManager::GetViewMode (void) const +{ + if (mbIsHelpViewActive) + return VM_Help; + else if (mbIsSlideSorterActive) + return VM_SlideOverview; + else if (meLayoutMode == LM_Notes) + return VM_Notes; + else + return VM_Standard; +} + + + + +void PresenterWindowManager::RestoreViewMode (void) +{ + sal_Int32 nMode (0); + PresenterConfigurationAccess aConfiguration ( + mxComponentContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.extension.PresenterScreen/")), + PresenterConfigurationAccess::READ_ONLY); + aConfiguration.GetConfigurationNode(A2S("Presenter/InitialViewMode")) >>= nMode; + switch (nMode) + { + default: + case 0: + SetViewMode(VM_Standard); + break; + + case 1: + SetViewMode(VM_Notes); + break; + + case 2: + SetViewMode(VM_SlideOverview); + break; + } +} + + + + +void PresenterWindowManager::StoreViewMode (const ViewMode eViewMode) +{ + try + { + PresenterConfigurationAccess aConfiguration ( + mxComponentContext, + OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.extension.PresenterScreen/")), + PresenterConfigurationAccess::READ_WRITE); + aConfiguration.GoToChild(A2S("Presenter")); + Any aValue; + switch (eViewMode) + { + default: + case VM_Standard: + aValue = Any(sal_Int32(0)); + break; + + case VM_Notes: + aValue = Any(sal_Int32(1)); + break; + + case VM_SlideOverview: + aValue = Any(sal_Int32(2)); + break; + } + + aConfiguration.SetProperty (A2S("InitialViewMode"), aValue); + aConfiguration.CommitChanges(); + } + catch (Exception&) + { + } +} + + + + +void PresenterWindowManager::AddLayoutListener ( + const Reference<document::XEventListener>& rxListener) +{ + maLayoutListeners.push_back(rxListener); +} + + + + +void PresenterWindowManager::RemoveLayoutListener ( + const Reference<document::XEventListener>& rxListener) +{ + LayoutListenerContainer::iterator iListener (maLayoutListeners.begin()); + LayoutListenerContainer::iterator iEnd (maLayoutListeners.end()); + for ( ; iListener!=iEnd; ++iListener) + { + if (*iListener == rxListener) + { + maLayoutListeners.erase(iListener); + // Assume that there are no multiple entries. + break; + } + } +} + + + + +void PresenterWindowManager::Layout (void) +{ + if (mxParentWindow.is() && ! mbIsLayouting) + { + mbIsLayoutPending = false; + mbIsLayouting = true; + mxScaledBackgroundBitmap = NULL; + mxClipPolygon = NULL; + + try + { + if (mbIsSlideSorterActive) + LayoutSlideSorterMode(); + else if (mbIsHelpViewActive) + LayoutHelpMode(); + else + switch (meLayoutMode) + { + case LM_Standard: + default: + LayoutStandardMode(); + break; + + case LM_Notes: + LayoutNotesMode(); + break; + } + } + catch (Exception&) + { + OSL_ASSERT(false); + throw; + } + + mbIsLayouting = false; + } +} + + + + +void PresenterWindowManager::LayoutStandardMode (void) +{ + awt::Rectangle aBox = mxParentWindow->getPosSize(); + + const double nGoldenRatio ((1 + sqrt(5.0)) / 2); + const double nGap (20); + const double nHorizontalSlideDivide (aBox.Width / nGoldenRatio); + double nSlidePreviewTop (0); + + // For the current slide view calculate the outer height from the outer + // width. This takes into acount the slide aspect ratio and thus has to + // go over the inner pane size. + PresenterPaneContainer::SharedPaneDescriptor pPane ( + mpPaneContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL)); + if (pPane.get() != NULL) + { + const awt::Size aCurrentSlideOuterBox(CalculatePaneSize( + nHorizontalSlideDivide - 1.5*nGap, + PresenterPaneFactory::msCurrentSlidePreviewPaneURL)); + nSlidePreviewTop = (aBox.Height - aCurrentSlideOuterBox.Height) / 2; + SetPanePosSizeAbsolute ( + PresenterPaneFactory::msCurrentSlidePreviewPaneURL, + nGap, + nSlidePreviewTop, + aCurrentSlideOuterBox.Width, + aCurrentSlideOuterBox.Height); + } + + + // For the next slide view calculate the outer height from the outer + // width. This takes into acount the slide aspect ratio and thus has to + // go over the inner pane size. + pPane = mpPaneContainer->FindPaneURL(PresenterPaneFactory::msNextSlidePreviewPaneURL); + if (pPane.get() != NULL) + { + const awt::Size aNextSlideOuterBox (CalculatePaneSize( + aBox.Width - nHorizontalSlideDivide - 1.5*nGap, + PresenterPaneFactory::msNextSlidePreviewPaneURL)); + SetPanePosSizeAbsolute ( + PresenterPaneFactory::msNextSlidePreviewPaneURL, + aBox.Width - aNextSlideOuterBox.Width - nGap, + nSlidePreviewTop, + aNextSlideOuterBox.Width, + aNextSlideOuterBox.Height); + } + + LayoutToolBar(); +} + + + + +void PresenterWindowManager::LayoutNotesMode (void) +{ + awt::Rectangle aBox = mxParentWindow->getPosSize(); + + const geometry::RealRectangle2D aToolBarBox (LayoutToolBar()); + + const double nGoldenRatio ((1 + sqrt(5.0)) / 2); + const double nGap (20); + const double nPrimaryWidth (aBox.Width / nGoldenRatio); + const double nSecondaryWidth (aBox.Width - nPrimaryWidth); + const double nTertiaryWidth (nSecondaryWidth / nGoldenRatio); + double nSlidePreviewTop (0); + double nNotesViewBottom (aToolBarBox.Y1 - nGap); + + // The notes view has no fixed aspect ratio. + PresenterPaneContainer::SharedPaneDescriptor pPane ( + mpPaneContainer->FindPaneURL(PresenterPaneFactory::msNotesPaneURL)); + if (pPane.get() != NULL) + { + const geometry::RealSize2D aNotesViewOuterSize( + nPrimaryWidth - 1.5*nGap + 0.5, + nNotesViewBottom); + nSlidePreviewTop = (aBox.Height + - aToolBarBox.Y2 + aToolBarBox.Y1 - aNotesViewOuterSize.Height) / 2; + SetPanePosSizeAbsolute ( + PresenterPaneFactory::msNotesPaneURL, + aBox.Width - aNotesViewOuterSize.Width - nGap, + nSlidePreviewTop, + aNotesViewOuterSize.Width, + aNotesViewOuterSize.Height); + nNotesViewBottom = nSlidePreviewTop + aNotesViewOuterSize.Height; + } + + // For the current slide view calculate the outer height from the outer + // width. This takes into acount the slide aspect ratio and thus has to + // go over the inner pane size. + pPane = mpPaneContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL); + if (pPane.get() != NULL) + { + const awt::Size aCurrentSlideOuterBox(CalculatePaneSize( + nSecondaryWidth - 1.5*nGap, + PresenterPaneFactory::msCurrentSlidePreviewPaneURL)); + SetPanePosSizeAbsolute ( + PresenterPaneFactory::msCurrentSlidePreviewPaneURL, + nGap, + nSlidePreviewTop, + aCurrentSlideOuterBox.Width, + aCurrentSlideOuterBox.Height); + } + + + // For the next slide view calculate the outer height from the outer + // width. This takes into acount the slide aspect ratio and thus has to + // go over the inner pane size. + pPane = mpPaneContainer->FindPaneURL(PresenterPaneFactory::msNextSlidePreviewPaneURL); + if (pPane.get() != NULL) + { + const awt::Size aNextSlideOuterBox (CalculatePaneSize( + nTertiaryWidth, + PresenterPaneFactory::msNextSlidePreviewPaneURL)); + SetPanePosSizeAbsolute ( + PresenterPaneFactory::msNextSlidePreviewPaneURL, + nGap, + nNotesViewBottom - aNextSlideOuterBox.Height, + aNextSlideOuterBox.Width, + aNextSlideOuterBox.Height); + } +} + + + + +void PresenterWindowManager::LayoutSlideSorterMode (void) +{ + const geometry::RealRectangle2D aToolBarBox (LayoutToolBar()); + + awt::Rectangle aWindowBox = mxParentWindow->getPosSize(); + const double nGap (20); + SetPanePosSizeAbsolute( + mpPaneContainer->GetPaneURLForViewURL(PresenterViewFactory::msSlideSorterURL), + nGap, + nGap, + aWindowBox.Width - 2*nGap, + aToolBarBox.Y1 - 2*nGap); +} + + + + +void PresenterWindowManager::LayoutHelpMode (void) +{ + const geometry::RealRectangle2D aToolBarBox (LayoutToolBar()); + + awt::Rectangle aWindowBox = mxParentWindow->getPosSize(); + const double nGap (20); + const double nGoldenRatio ((1 + sqrt(5.0)) / 2); + const double nWidth = ::std::min(aWindowBox.Width - 2*nGap, aWindowBox.Width/nGoldenRatio); + SetPanePosSizeAbsolute( + mpPaneContainer->GetPaneURLForViewURL(PresenterViewFactory::msHelpViewURL), + (aWindowBox.Width - nWidth)/2, + nGap, + nWidth, + aToolBarBox.Y1 - 2*nGap); +} + + + + +geometry::RealRectangle2D PresenterWindowManager::LayoutToolBar (void) +{ + double nToolBarWidth (400); + double nToolBarHeight (80); + + // Get access to the tool bar. + PresenterPaneContainer::SharedPaneDescriptor pDescriptor( + mpPaneContainer->FindPaneURL(PresenterPaneFactory::msToolBarPaneURL)); + if (pDescriptor.get() != NULL) + { + PresenterToolBarView* pToolBarView + = dynamic_cast<PresenterToolBarView*>(pDescriptor->mxView.get()); + if (pToolBarView != NULL && pToolBarView->GetPresenterToolBar().is()) + { + geometry::RealSize2D aSize (pToolBarView->GetPresenterToolBar()->GetMinimalSize()); + + if (mpPaneBorderPainter.is()) + { + const awt::Rectangle aBox (mpPaneBorderPainter->addBorder ( + PresenterPaneFactory::msToolBarPaneURL, + awt::Rectangle( + 0, + 0, + PresenterGeometryHelper::Round(aSize.Width), + PresenterGeometryHelper::Round(aSize.Height)), + css::drawing::framework::BorderType_TOTAL_BORDER)); + + nToolBarWidth = aBox.Width; + nToolBarHeight = aBox.Height; + } + else + { + nToolBarWidth = aSize.Width + 20; + nToolBarHeight = aSize.Height + 10; + } + } + } + + const awt::Rectangle aBox = mxParentWindow->getPosSize(); + const double nToolBarX ((aBox.Width - nToolBarWidth) / 2); + const double nToolBarY (aBox.Height - nToolBarHeight); + SetPanePosSizeAbsolute( + PresenterPaneFactory::msToolBarPaneURL, + nToolBarX, + nToolBarY, + nToolBarWidth, + nToolBarHeight); + + return geometry::RealRectangle2D( + nToolBarX, + nToolBarY, + nToolBarX + nToolBarWidth - 1, + nToolBarY + nToolBarHeight - 1); +} + + + + +awt::Size PresenterWindowManager::CalculatePaneSize ( + const double nOuterWidth, + const OUString& rsPaneURL) +{ + // Calculate the inner width by removing the pane border. + awt::Rectangle aInnerBox (mpPaneBorderPainter->RemoveBorder ( + rsPaneURL, + awt::Rectangle(0,0, + sal_Int32(nOuterWidth+0.5),sal_Int32(nOuterWidth)), + drawing::framework::BorderType_TOTAL_BORDER)); + + // Calculate the inner height with the help of the slide aspect ratio. + const double nCurrentSlideInnerHeight ( + aInnerBox.Width / mpPresenterController->GetSlideAspectRatio()); + + // Add the pane border to get the outer box. + awt::Rectangle aOuterBox (mpPaneBorderPainter->AddBorder ( + rsPaneURL, + awt::Rectangle(0,0, + aInnerBox.Width,sal_Int32(nCurrentSlideInnerHeight+0.5)), + drawing::framework::BorderType_TOTAL_BORDER)); + + return awt::Size(aOuterBox.Width, aOuterBox.Height); +} + + + + +void PresenterWindowManager::NotifyLayoutModeChange (void) +{ + document::EventObject aEvent; + aEvent.Source = Reference<XInterface>(static_cast<XWeak*>(this)); + + LayoutListenerContainer aContainerCopy (maLayoutListeners); + LayoutListenerContainer::iterator iListener (aContainerCopy.begin()); + LayoutListenerContainer::iterator iEnd (aContainerCopy.end()); + for ( ; iListener!=iEnd; ++iListener) + { + if (iListener->is()) + { + try + { + (*iListener)->notifyEvent(aEvent); + } + catch (lang::DisposedException&) + { + RemoveLayoutListener(*iListener); + } + catch (RuntimeException&) + { + } + } + } +} + + + + +void PresenterWindowManager::NotifyDisposing (void) +{ + lang::EventObject aEvent; + aEvent.Source = static_cast<XWeak*>(this); + + LayoutListenerContainer aContainer; + aContainer.swap(maLayoutListeners); + LayoutListenerContainer::iterator iListener (aContainer.begin()); + LayoutListenerContainer::iterator iEnd (aContainer.end()); + for ( ; iListener!=iEnd; ++iListener) + { + if (iListener->is()) + { + try + { + (*iListener)->disposing(aEvent); + } + catch (lang::DisposedException&) + { + } + catch (RuntimeException&) + { + } + } + } +} + + + + +void PresenterWindowManager::LayoutUnknownMode (void) +{ + awt::Rectangle aBox = mxParentWindow->getPosSize(); + + PresenterPaneContainer::PaneList::const_iterator iPane; + PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end()); + for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane) + { + const PresenterPaneContainer::SharedPaneDescriptor& pDescriptor (*iPane); + if ( ! pDescriptor->mxBorderWindow.is()) + continue; + + // Layout the border window. + const sal_Int32 nX = (sal_Int32)(pDescriptor->mnLeft * aBox.Width); + const sal_Int32 nY = (sal_Int32)(pDescriptor->mnTop * aBox.Height); + const sal_Int32 nWidth = (sal_Int32)(pDescriptor->mnRight * aBox.Width) - nX; + const sal_Int32 nHeight = (sal_Int32)(pDescriptor->mnBottom * aBox.Height) - nY; + + pDescriptor->mxBorderWindow->setPosSize( + nX,nY,nWidth,nHeight, + awt::PosSize::POSSIZE); + } +} + + + + +void PresenterWindowManager::UpdateWindowSize (const Reference<awt::XWindow>& rxBorderWindow) +{ + PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( + mpPaneContainer->FindBorderWindow(rxBorderWindow)); + if (pDescriptor.get() != NULL) + { + mxClipPolygon = NULL; + + awt::Rectangle aParentBox = mxParentWindow->getPosSize(); + awt::Rectangle aBorderBox (pDescriptor->mxBorderWindow->getPosSize()); + + if ( ! mbIsLayouting) + { + const double nWidth (aParentBox.Width); + const double nHeight (aParentBox.Height); + pDescriptor->mnLeft = double(aBorderBox.X) / nWidth; + pDescriptor->mnTop = double(aBorderBox.Y) / nHeight; + pDescriptor->mnRight = double(aBorderBox.X + aBorderBox.Width) / nWidth; + pDescriptor->mnBottom = double(aBorderBox.Y + aBorderBox.Height) / nHeight; + } + else + { + // This update of the window size was initiated by + // Layout(). Therefore the window size does not have to be + // updated. + } + + // ToTop is called last because it may invalidate the iterator. + if ( ! mbIsLayouting) + mpPaneContainer->ToTop(pDescriptor); + } +} + + + + +void PresenterWindowManager::PaintBackground (const awt::Rectangle& rUpdateBox) +{ + (void)rUpdateBox; + if ( ! mxParentWindow.is()) + return; + + Reference<rendering::XGraphicDevice> xDevice (mxParentCanvas->getDevice()); + if ( ! xDevice.is()) + return; + + // Create a polygon for the background and for clipping. + Reference<rendering::XPolyPolygon2D> xBackgroundPolygon ( + PresenterGeometryHelper::CreatePolygon(mxParentWindow->getPosSize(), xDevice)); + if ( ! mxClipPolygon.is()) + mxClipPolygon = CreateClipPolyPolygon(); + + // Create View- and RenderState structs. + const rendering::ViewState aViewState( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + PresenterGeometryHelper::CreatePolygon(rUpdateBox, xDevice)); + rendering::RenderState aRenderState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + mxClipPolygon, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + + // Paint the background. + if (mpBackgroundBitmap.get() != NULL) + { + ProvideBackgroundBitmap(); + + if (mxScaledBackgroundBitmap.is()) + { + Sequence<rendering::Texture> aTextures (1); + const geometry::IntegerSize2D aBitmapSize(mxScaledBackgroundBitmap->getSize()); + aTextures[0] = rendering::Texture ( + geometry::AffineMatrix2D( + aBitmapSize.Width,0,0, + 0,aBitmapSize.Height,0), + 1, + 0, + mxScaledBackgroundBitmap, + NULL, + NULL, + rendering::StrokeAttributes(), + rendering::TexturingMode::REPEAT, + rendering::TexturingMode::REPEAT); + + mxParentCanvas->fillTexturedPolyPolygon( + xBackgroundPolygon, + aViewState, + aRenderState, + aTextures); + } + else + { + const util::Color aBackgroundColor (mpBackgroundBitmap->maReplacementColor); + aRenderState.DeviceColor[0] = ((aBackgroundColor >> 16) & 0x0ff) / 255.0; + aRenderState.DeviceColor[1] = ((aBackgroundColor >> 8) & 0x0ff) / 255.0; + aRenderState.DeviceColor[2] = ((aBackgroundColor >> 0) & 0x0ff) / 255.0; + aRenderState.DeviceColor[3] = ((aBackgroundColor >> 24) & 0x0ff) / 255.0; + mxParentCanvas->fillPolyPolygon( + xBackgroundPolygon, + aViewState, + aRenderState); + } + } +} + + + + +void PresenterWindowManager::ProvideBackgroundBitmap (void) +{ + if ( ! mxScaledBackgroundBitmap.is()) + { + Reference<rendering::XBitmap> xBitmap (mpBackgroundBitmap->GetNormalBitmap()); + if (xBitmap.is()) + { + const bool bStretchVertical (mpBackgroundBitmap->meVerticalTexturingMode + == PresenterBitmapDescriptor::Stretch); + const bool bStretchHorizontal (mpBackgroundBitmap->meHorizontalTexturingMode + == PresenterBitmapDescriptor::Stretch); + if (bStretchHorizontal || bStretchVertical) + { + geometry::RealSize2D aSize; + if (bStretchVertical) + aSize.Height = mxParentWindow->getPosSize().Height; + else + aSize.Height = xBitmap->getSize().Height; + if (bStretchHorizontal) + aSize.Width = mxParentWindow->getPosSize().Width; + else + aSize.Width = xBitmap->getSize().Width; + mxScaledBackgroundBitmap = xBitmap->getScaledBitmap(aSize, sal_False); + } + else + { + mxScaledBackgroundBitmap + = Reference<rendering::XBitmap>(xBitmap, UNO_QUERY); + } + } + } +} + + + + +Reference<rendering::XPolyPolygon2D> PresenterWindowManager::CreateClipPolyPolygon (void) const +{ + // Create a clip polygon that includes the whole update area but has the + // content windows as holes. + const sal_Int32 nPaneCount (mpPaneContainer->maPanes.size()); + ::std::vector<awt::Rectangle> aRectangles; + aRectangles.reserve(1+nPaneCount); + aRectangles.push_back(mxParentWindow->getPosSize()); + PresenterPaneContainer::PaneList::const_iterator iPane; + PresenterPaneContainer::PaneList::const_iterator iEnd (mpPaneContainer->maPanes.end()); + for (iPane=mpPaneContainer->maPanes.begin(); iPane!=iEnd; ++iPane) + { + PresenterPaneContainer::SharedPaneDescriptor pDescriptor (*iPane); + if ( ! pDescriptor->mbIsActive) + continue; + if ( ! pDescriptor->mbIsOpaque) + continue; + if ( ! pDescriptor->mxBorderWindow.is() || ! pDescriptor->mxContentWindow.is()) + continue; + Reference<awt::XWindow2> xWindow (pDescriptor->mxBorderWindow, UNO_QUERY); + if (xWindow.is() && ! xWindow->isVisible()) + continue; + + const awt::Rectangle aOuterBorderBox (pDescriptor->mxBorderWindow->getPosSize()); + awt::Rectangle aInnerBorderBox (pDescriptor->mxContentWindow->getPosSize()); + aInnerBorderBox.X += aOuterBorderBox.X; + aInnerBorderBox.Y += aOuterBorderBox.Y; + aRectangles.push_back(aInnerBorderBox); + } + Reference<rendering::XPolyPolygon2D> xPolyPolygon ( + PresenterGeometryHelper::CreatePolygon( + aRectangles, + mxParentCanvas->getDevice())); + if (xPolyPolygon.is()) + xPolyPolygon->setFillRule(rendering::FillRule_EVEN_ODD); + return xPolyPolygon; +} + + + + +void PresenterWindowManager::UpdateWindowList (void) +{ +#ifdef ENABLE_PANE_RESIZING + try + { + OSL_ASSERT(mxComponentContext.is()); + + Reference<lang::XComponent> xComponent (mxPaneBorderManager, UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + + Reference<lang::XMultiComponentFactory> xFactory (mxComponentContext->getServiceManager()); + if (xFactory.is()) + { + Sequence<Any> aArguments (1 + mpPaneContainer->maPanes.size()*2); + sal_Int32 nIndex (0); + aArguments[nIndex++] = Any(mxParentWindow); + for (sal_uInt32 nPaneIndex=0; nPaneIndex<mpPaneContainer->maPanes.size(); ++nPaneIndex) + { + if ( ! mpPaneContainer->maPanes[nPaneIndex]->mbIsActive) + continue; + + const Reference<awt::XWindow> xBorderWindow ( + mpPaneContainer->maPanes[nPaneIndex]->mxBorderWindow); + const Reference<awt::XWindow> xContentWindow ( + mpPaneContainer->maPanes[nPaneIndex]->mxContentWindow); + const Reference<awt::XWindow2> xBorderWindow2(xBorderWindow, UNO_QUERY); + if (xBorderWindow.is() + && xContentWindow.is() + && ( ! xBorderWindow2.is() || xBorderWindow2->isVisible())) + { + aArguments[nIndex++] = Any(xBorderWindow); + aArguments[nIndex++] = Any(xContentWindow); + } + } + + aArguments.realloc(nIndex); + rtl::Reference<PresenterPaneBorderManager> pManager ( + new PresenterPaneBorderManager ( + mxComponentContext, + mpPresenterController)); + pManager->initialize(aArguments); + mxPaneBorderManager = Reference<XInterface>(static_cast<XWeak*>(pManager.get())); + } + } + catch (RuntimeException&) + { + } +#endif +} + + + + +void PresenterWindowManager::Invalidate (void) +{ + mpPresenterController->GetPaintManager()->Invalidate(mxParentWindow); +} + + + + +Reference<awt::XWindow> PresenterWindowManager::GetParentWindow (void) const +{ + return mxParentWindow; +} + + + + +Reference<rendering::XCanvas> PresenterWindowManager::GetParentCanvas (void) const +{ + return mxParentCanvas; +} + + + + +void PresenterWindowManager::Update (void) +{ + mxClipPolygon = NULL; + mbIsLayoutPending = true; + + UpdateWindowList(); + Invalidate(); +} + + + + +void PresenterWindowManager::ThrowIfDisposed (void) const + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "PresenterWindowManager has already been disposed")), + const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); + } +} + + + +namespace { + +//===== ModeChangeAnimation =================================================== + +class ModeChangeAnimation : public PresenterAnimation +{ +public: + ModeChangeAnimation ( + const ::boost::shared_ptr<PresenterSprite>& rpSprite, + const Reference<rendering::XSpriteCanvas>& rxCanvas) + : PresenterAnimation (0, 1000, 20), + mpSprite(rpSprite), + mxCanvas(rxCanvas) + { + } + + virtual void Run (const double nProgress, const sal_uInt64 nCurrentTime) + { + (void)nCurrentTime; + mpSprite->SetAlpha(1.0 - nProgress); + mxCanvas->updateScreen(sal_False); + } + +private: + ::boost::shared_ptr<PresenterSprite> mpSprite; + Reference<rendering::XSpriteCanvas> mxCanvas; +}; + + + + +ModeChangeAnimationStarter::ModeChangeAnimationStarter ( + const Reference<drawing::framework::XConfigurationController>& rxConfigurationController, + const Reference<awt::XWindow>& rxWindow, + const Reference<rendering::XSpriteCanvas>& rxCanvas, + const ::boost::shared_ptr<PresenterAnimator>& rpAnimator) + : ModeChangeAnimationStarterInterfaceBase(m_aMutex), + mxConfigurationController(rxConfigurationController), + mpAnimator(rpAnimator), + mpSprite(new PresenterSprite()), + mxCanvas(rxCanvas) +{ + OSL_ASSERT(rxWindow.is()); + OSL_ASSERT(rxCanvas.is()); + + // Get the bitmap of the background. + Reference<rendering::XBitmap> xBackgroundBitmap (rxCanvas, UNO_QUERY); + if ( ! xBackgroundBitmap.is()) + return; + + // Create the sprite. + const awt::Rectangle aWindowSize (rxWindow->getPosSize()); + mpSprite->SetFactory(rxCanvas); + mpSprite->Resize(geometry::RealSize2D(aWindowSize.Width, aWindowSize.Height)); + mpSprite->SetPriority(10); + + // Fill it with the background inside the bounding box. + const rendering::ViewState aViewState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL); + const rendering::RenderState aRenderState ( + geometry::AffineMatrix2D(1,0,0, 0,1,0), + NULL, + Sequence<double>(4), + rendering::CompositeOperation::SOURCE); + Reference<rendering::XCanvas> xSpriteCanvas (mpSprite->GetCanvas()); + if (xSpriteCanvas.is()) + { + xSpriteCanvas->drawBitmap(xBackgroundBitmap, aViewState, aRenderState); + mpSprite->Show(); + } + + // Register as listener to be notified when the new panes are visible + // and the sprite can be faded out. + mxConfigurationController->addConfigurationChangeListener( + this, + A2S("ConfigurationUpdateEnd"), + Any()); +} + + + + +ModeChangeAnimationStarter::~ModeChangeAnimationStarter (void) +{ +} + + + + +void SAL_CALL ModeChangeAnimationStarter::disposing (void) +{ + mxConfigurationController = NULL; + mpAnimator.reset(); + mpSprite.reset(); +} + + + + +// XConfigurationChangeListener + +void SAL_CALL ModeChangeAnimationStarter::notifyConfigurationChange ( + const com::sun::star::drawing::framework::ConfigurationChangeEvent& rEvent) + throw (com::sun::star::uno::RuntimeException) +{ + (void)rEvent; + + // Start the actual animation. + mpAnimator->AddAnimation(SharedPresenterAnimation(new ModeChangeAnimation( + mpSprite, + mxCanvas))); + + mxConfigurationController->removeConfigurationChangeListener(this); +} + + + + +// XEventListener + +void SAL_CALL ModeChangeAnimationStarter::disposing ( + const com::sun::star::lang::EventObject& rEvent) + throw (com::sun::star::uno::RuntimeException) +{ + if (rEvent.Source == mxConfigurationController) + mxConfigurationController = NULL; +} + + + +} // end of anonymous namespace + + +} } // end of namespace ::sdext::presenter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/PresenterWindowManager.hxx b/sdext/source/presenter/PresenterWindowManager.hxx new file mode 100644 index 000000000000..997565bf0a8c --- /dev/null +++ b/sdext/source/presenter/PresenterWindowManager.hxx @@ -0,0 +1,262 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SDEXT_PRESENTER_PRESENTER_WINDOW_MANAGER_HXX +#define SDEXT_PRESENTER_PRESENTER_WINDOW_MANAGER_HXX + +#include "PresenterPaneContainer.hxx" +#include "PresenterTheme.hxx" +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/XFocusListener.hpp> +#include <com/sun/star/awt/XGraphics.hpp> +#include <com/sun/star/awt/XMouseMotionListener.hpp> +#include <com/sun/star/awt/XPaintListener.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/XWindowListener.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/document/XEventListener.hpp> +#include <com/sun/star/drawing/framework/XPane.hpp> +#include <com/sun/star/rendering/XBitmap.hpp> +#include <com/sun/star/rendering/XSprite.hpp> +#include <com/sun/star/rendering/XSpriteCanvas.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase4.hxx> +#include <tools/gen.hxx> +#include <rtl/ref.hxx> +#include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> + +namespace css = ::com::sun::star; + +namespace sdext { namespace presenter { + +class PresenterController; +class PresenterPaneBorderPainter; +class PresenterTheme; + +namespace { + typedef ::cppu::WeakComponentImplHelper4< + css::awt::XWindowListener, + css::awt::XPaintListener, + css::awt::XMouseListener, + css::awt::XFocusListener + > PresenterWindowManagerInterfaceBase; +} + + +/** A simple manager of the positions of the panes of the presenter screen. + Uses relative coordinates of the four sides of each pane. Allows panes + to be moved or resized with the mouse. +*/ +class PresenterWindowManager + : private ::boost::noncopyable, + protected ::cppu::BaseMutex, + public PresenterWindowManagerInterfaceBase +{ +public: + PresenterWindowManager ( + const ::css::uno::Reference<css::uno::XComponentContext>& rxContext, + const ::rtl::Reference<PresenterPaneContainer>& rpPaneContainer, + const ::rtl::Reference<PresenterController>& rpPresenterController); + virtual ~PresenterWindowManager (void); + + void SAL_CALL disposing (void); + + void SetParentPane (const css::uno::Reference<css::drawing::framework::XPane>& rxPane); + void SetTheme (const ::boost::shared_ptr<PresenterTheme>& rpTheme); + void NotifyPaneCreation (const PresenterPaneContainer::SharedPaneDescriptor& rpDescriptor); + void NotifyViewCreation (const css::uno::Reference<css::drawing::framework::XView>& rxView); + void SetPanePosSizeRelative ( + const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId, + const double nRelativeX, + const double nRelativeY, + const double nRelativeWidth, + const double nRelativeHeight); + void SetPanePosSizeAbsolute ( + const ::rtl::OUString& rsPaneURL, + const double nX, + const double nY, + const double nWidth, + const double nHeight); + void SetPaneBorderPainter (const ::rtl::Reference<PresenterPaneBorderPainter>& rPainter); + css::uno::Reference<css::awt::XWindow> GetParentWindow (void) const; + css::uno::Reference<css::rendering::XCanvas> GetParentCanvas (void) const; + void Update (void); + void Layout (void); + + void SetSlideSorterState (bool bIsActive); + void SetHelpViewState (bool bIsActive); + + enum LayoutMode { LM_Standard, LM_Notes, LM_Generic }; +private: + void SetLayoutMode (const LayoutMode eMode); + LayoutMode GetLayoutMode (void) const; + + bool IsSlideSorterActive (void) const; + bool IsHelpViewActive (void) const; +public: + enum ViewMode { VM_Standard, VM_Notes, VM_SlideOverview, VM_Help }; + /** The high-level method to switch the view mode. Use this instead of + SetLayoutMode and Set(Help|SlideSorter)State when possible. + */ + void SetViewMode (const ViewMode eMode); + + ViewMode GetViewMode (void) const; + + /** Restore the layout mode (or slide sorter state) from the + configuration. + */ + void RestoreViewMode (void); + + void AddLayoutListener ( + const css::uno::Reference<css::document::XEventListener>& rxListener); + void RemoveLayoutListener ( + const css::uno::Reference<css::document::XEventListener>& rxListener); + + // XWindowListener + + virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) + throw (css::uno::RuntimeException); + + + // XPaintListener + + virtual void SAL_CALL windowPaint (const css::awt::PaintEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XMouseListener + + virtual void SAL_CALL mousePressed (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL mouseReleased (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL mouseEntered (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + virtual void SAL_CALL mouseExited (const css::awt::MouseEvent& rEvent) + throw(css::uno::RuntimeException); + + + // XFocusListener + + virtual void SAL_CALL focusGained (const css::awt::FocusEvent& rEvent) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL focusLost (const css::awt::FocusEvent& rEvent) + throw (css::uno::RuntimeException); + + + // XEventListener + + virtual void SAL_CALL disposing ( + const com::sun::star::lang::EventObject& rEvent) + throw (com::sun::star::uno::RuntimeException); + +private: + css::uno::Reference<css::uno::XComponentContext> mxComponentContext; + ::rtl::Reference<PresenterController> mpPresenterController; + css::uno::Reference<css::awt::XWindow> mxParentWindow; + css::uno::Reference<css::rendering::XCanvas> mxParentCanvas; + css::uno::Reference<css::uno::XInterface> mxPaneBorderManager; + ::rtl::Reference<PresenterPaneBorderPainter> mpPaneBorderPainter; + ::rtl::Reference<PresenterPaneContainer> mpPaneContainer; + bool mbIsLayoutPending; + /** This flag is set to <TRUE/> while the Layout() method is being + executed. Prevents windowMoved() and windowResized() from changing + the window sizes. + */ + bool mbIsLayouting; + ::boost::shared_ptr<PresenterTheme> mpTheme; + SharedBitmapDescriptor mpBackgroundBitmap; + css::uno::Reference<css::rendering::XBitmap> mxScaledBackgroundBitmap; + css::util::Color maPaneBackgroundColor; + css::uno::Reference<css::rendering::XPolyPolygon2D> mxClipPolygon; + LayoutMode meLayoutMode; + bool mbIsSlideSorterActive; + bool mbIsHelpViewActive; + typedef ::std::vector<css::uno::Reference<css::document::XEventListener> > + LayoutListenerContainer; + LayoutListenerContainer maLayoutListeners; + bool mbIsMouseClickPending; + + bool PaintChildren (const css::awt::PaintEvent& rEvent) const; + void UpdateWindowSize (const css::uno::Reference<css::awt::XWindow>& rxBorderWindow); + void PaintBackground (const css::awt::Rectangle& rUpdateBox); + void ProvideBackgroundBitmap (void); + css::uno::Reference<css::rendering::XPolyPolygon2D> CreateClipPolyPolygon (void) const; + void ToTop (); + + void UpdateWindowList (void); + bool ChildNeedsRepaint ( + const css::uno::Reference<css::drawing::framework::XPane>& rxPane) const; + + void Invalidate (void); + + void StoreViewMode (const ViewMode eViewMode); + + void LayoutStandardMode (void); + void LayoutNotesMode (void); + void LayoutUnknownMode (void); + void LayoutSlideSorterMode (void); + void LayoutHelpMode (void); + + /** Layout the tool bar and return its outer bounding box. + */ + css::geometry::RealRectangle2D LayoutToolBar (void); + + css::awt::Size CalculatePaneSize ( + const double nOuterWidth, + const ::rtl::OUString& rsPaneURL); + + /** Notify changes of the layout mode and of the slide sorter state. + */ + void NotifyLayoutModeChange (void); + + void NotifyDisposing (void); + + void ThrowIfDisposed (void) const throw (::com::sun::star::lang::DisposedException); +}; + +} } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sdext/source/presenter/bitmaps/Background.png b/sdext/source/presenter/bitmaps/Background.png Binary files differnew file mode 100644 index 000000000000..7b32e4ab974b --- /dev/null +++ b/sdext/source/presenter/bitmaps/Background.png diff --git a/sdext/source/presenter/bitmaps/BorderActiveBottom.png b/sdext/source/presenter/bitmaps/BorderActiveBottom.png Binary files differnew file mode 100644 index 000000000000..8314c9efd092 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderActiveBottom.png diff --git a/sdext/source/presenter/bitmaps/BorderActiveBottomCallout.png b/sdext/source/presenter/bitmaps/BorderActiveBottomCallout.png Binary files differnew file mode 100644 index 000000000000..b7c33223a33c --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderActiveBottomCallout.png diff --git a/sdext/source/presenter/bitmaps/BorderActiveBottomLeft.png b/sdext/source/presenter/bitmaps/BorderActiveBottomLeft.png Binary files differnew file mode 100644 index 000000000000..8d573e864942 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderActiveBottomLeft.png diff --git a/sdext/source/presenter/bitmaps/BorderActiveBottomRight.png b/sdext/source/presenter/bitmaps/BorderActiveBottomRight.png Binary files differnew file mode 100644 index 000000000000..35ef8e9213db --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderActiveBottomRight.png diff --git a/sdext/source/presenter/bitmaps/BorderActiveLeft.png b/sdext/source/presenter/bitmaps/BorderActiveLeft.png Binary files differnew file mode 100644 index 000000000000..57d4a3dbbcd3 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderActiveLeft.png diff --git a/sdext/source/presenter/bitmaps/BorderActiveRight.png b/sdext/source/presenter/bitmaps/BorderActiveRight.png Binary files differnew file mode 100644 index 000000000000..9a9857190b9d --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderActiveRight.png diff --git a/sdext/source/presenter/bitmaps/BorderActiveTop.png b/sdext/source/presenter/bitmaps/BorderActiveTop.png Binary files differnew file mode 100644 index 000000000000..e0bea9d55448 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderActiveTop.png diff --git a/sdext/source/presenter/bitmaps/BorderActiveTopLeft.png b/sdext/source/presenter/bitmaps/BorderActiveTopLeft.png Binary files differnew file mode 100644 index 000000000000..62d63271fe21 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderActiveTopLeft.png diff --git a/sdext/source/presenter/bitmaps/BorderActiveTopRight.png b/sdext/source/presenter/bitmaps/BorderActiveTopRight.png Binary files differnew file mode 100644 index 000000000000..450c8e0cc5e7 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderActiveTopRight.png diff --git a/sdext/source/presenter/bitmaps/BorderBottom.png b/sdext/source/presenter/bitmaps/BorderBottom.png Binary files differnew file mode 100644 index 000000000000..7ad2fd6c2a03 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderBottom.png diff --git a/sdext/source/presenter/bitmaps/BorderBottomLeft.png b/sdext/source/presenter/bitmaps/BorderBottomLeft.png Binary files differnew file mode 100644 index 000000000000..019de149b3af --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderBottomLeft.png diff --git a/sdext/source/presenter/bitmaps/BorderBottomRight.png b/sdext/source/presenter/bitmaps/BorderBottomRight.png Binary files differnew file mode 100644 index 000000000000..82de5791c1cd --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderBottomRight.png diff --git a/sdext/source/presenter/bitmaps/BorderCurrentSlideBottom.png b/sdext/source/presenter/bitmaps/BorderCurrentSlideBottom.png Binary files differnew file mode 100644 index 000000000000..7000bc22f6c4 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderCurrentSlideBottom.png diff --git a/sdext/source/presenter/bitmaps/BorderCurrentSlideBottomLeft.png b/sdext/source/presenter/bitmaps/BorderCurrentSlideBottomLeft.png Binary files differnew file mode 100644 index 000000000000..7571c8d94b1f --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderCurrentSlideBottomLeft.png diff --git a/sdext/source/presenter/bitmaps/BorderCurrentSlideBottomRight.png b/sdext/source/presenter/bitmaps/BorderCurrentSlideBottomRight.png Binary files differnew file mode 100644 index 000000000000..c0af63ff58b8 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderCurrentSlideBottomRight.png diff --git a/sdext/source/presenter/bitmaps/BorderCurrentSlideLeft.png b/sdext/source/presenter/bitmaps/BorderCurrentSlideLeft.png Binary files differnew file mode 100644 index 000000000000..7000bc22f6c4 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderCurrentSlideLeft.png diff --git a/sdext/source/presenter/bitmaps/BorderCurrentSlideRight.png b/sdext/source/presenter/bitmaps/BorderCurrentSlideRight.png Binary files differnew file mode 100644 index 000000000000..7000bc22f6c4 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderCurrentSlideRight.png diff --git a/sdext/source/presenter/bitmaps/BorderCurrentSlideTop.png b/sdext/source/presenter/bitmaps/BorderCurrentSlideTop.png Binary files differnew file mode 100644 index 000000000000..7000bc22f6c4 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderCurrentSlideTop.png diff --git a/sdext/source/presenter/bitmaps/BorderCurrentSlideTopLeft.png b/sdext/source/presenter/bitmaps/BorderCurrentSlideTopLeft.png Binary files differnew file mode 100644 index 000000000000..fdfabd42ae9f --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderCurrentSlideTopLeft.png diff --git a/sdext/source/presenter/bitmaps/BorderCurrentSlideTopRight.png b/sdext/source/presenter/bitmaps/BorderCurrentSlideTopRight.png Binary files differnew file mode 100644 index 000000000000..5b4b642e9f34 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderCurrentSlideTopRight.png diff --git a/sdext/source/presenter/bitmaps/BorderLeft.png b/sdext/source/presenter/bitmaps/BorderLeft.png Binary files differnew file mode 100644 index 000000000000..cbdb267b8789 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderLeft.png diff --git a/sdext/source/presenter/bitmaps/BorderRight.png b/sdext/source/presenter/bitmaps/BorderRight.png Binary files differnew file mode 100644 index 000000000000..333073328ddd --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderRight.png diff --git a/sdext/source/presenter/bitmaps/BorderToolbarBottom.png b/sdext/source/presenter/bitmaps/BorderToolbarBottom.png Binary files differnew file mode 100644 index 000000000000..23a3bc3595aa --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderToolbarBottom.png diff --git a/sdext/source/presenter/bitmaps/BorderToolbarLeft.png b/sdext/source/presenter/bitmaps/BorderToolbarLeft.png Binary files differnew file mode 100644 index 000000000000..839ab5091a8e --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderToolbarLeft.png diff --git a/sdext/source/presenter/bitmaps/BorderToolbarRight.png b/sdext/source/presenter/bitmaps/BorderToolbarRight.png Binary files differnew file mode 100644 index 000000000000..e5c4b9d25a16 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderToolbarRight.png diff --git a/sdext/source/presenter/bitmaps/BorderToolbarTop.png b/sdext/source/presenter/bitmaps/BorderToolbarTop.png Binary files differnew file mode 100644 index 000000000000..c45b97c434cd --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderToolbarTop.png diff --git a/sdext/source/presenter/bitmaps/BorderToolbarTopLeft.png b/sdext/source/presenter/bitmaps/BorderToolbarTopLeft.png Binary files differnew file mode 100644 index 000000000000..978e98a9bbc4 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderToolbarTopLeft.png diff --git a/sdext/source/presenter/bitmaps/BorderToolbarTopRight.png b/sdext/source/presenter/bitmaps/BorderToolbarTopRight.png Binary files differnew file mode 100644 index 000000000000..7dc3d98860ea --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderToolbarTopRight.png diff --git a/sdext/source/presenter/bitmaps/BorderTop.png b/sdext/source/presenter/bitmaps/BorderTop.png Binary files differnew file mode 100644 index 000000000000..dee68e828147 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderTop.png diff --git a/sdext/source/presenter/bitmaps/BorderTopLeft.png b/sdext/source/presenter/bitmaps/BorderTopLeft.png Binary files differnew file mode 100644 index 000000000000..bbec4e42be42 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderTopLeft.png diff --git a/sdext/source/presenter/bitmaps/BorderTopRight.png b/sdext/source/presenter/bitmaps/BorderTopRight.png Binary files differnew file mode 100644 index 000000000000..3416b16c9e91 --- /dev/null +++ b/sdext/source/presenter/bitmaps/BorderTopRight.png diff --git a/sdext/source/presenter/bitmaps/ButtonEffectNextDisabled.png b/sdext/source/presenter/bitmaps/ButtonEffectNextDisabled.png Binary files differnew file mode 100644 index 000000000000..5417cf72c928 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonEffectNextDisabled.png diff --git a/sdext/source/presenter/bitmaps/ButtonEffectNextMouseOver.png b/sdext/source/presenter/bitmaps/ButtonEffectNextMouseOver.png Binary files differnew file mode 100644 index 000000000000..96805e392176 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonEffectNextMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ButtonEffectNextNormal.png b/sdext/source/presenter/bitmaps/ButtonEffectNextNormal.png Binary files differnew file mode 100644 index 000000000000..6dbd732e0977 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonEffectNextNormal.png diff --git a/sdext/source/presenter/bitmaps/ButtonEffectNextSelected.png b/sdext/source/presenter/bitmaps/ButtonEffectNextSelected.png Binary files differnew file mode 100644 index 000000000000..eb6e6d45bb23 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonEffectNextSelected.png diff --git a/sdext/source/presenter/bitmaps/ButtonFrameCenterMouseOver.png b/sdext/source/presenter/bitmaps/ButtonFrameCenterMouseOver.png Binary files differnew file mode 100644 index 000000000000..b97799f1f314 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonFrameCenterMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ButtonFrameCenterNormal.png b/sdext/source/presenter/bitmaps/ButtonFrameCenterNormal.png Binary files differnew file mode 100644 index 000000000000..4cf7218f3b52 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonFrameCenterNormal.png diff --git a/sdext/source/presenter/bitmaps/ButtonFrameLeftMouseOver.png b/sdext/source/presenter/bitmaps/ButtonFrameLeftMouseOver.png Binary files differnew file mode 100644 index 000000000000..1f2ab6a00cab --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonFrameLeftMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ButtonFrameLeftNormal.png b/sdext/source/presenter/bitmaps/ButtonFrameLeftNormal.png Binary files differnew file mode 100644 index 000000000000..0e92cb37d7d8 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonFrameLeftNormal.png diff --git a/sdext/source/presenter/bitmaps/ButtonFrameRightMouseOver.png b/sdext/source/presenter/bitmaps/ButtonFrameRightMouseOver.png Binary files differnew file mode 100644 index 000000000000..0f49ad4f7e61 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonFrameRightMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ButtonFrameRightNormal.png b/sdext/source/presenter/bitmaps/ButtonFrameRightNormal.png Binary files differnew file mode 100644 index 000000000000..4ca69670e513 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonFrameRightNormal.png diff --git a/sdext/source/presenter/bitmaps/ButtonHelpDisabled.png b/sdext/source/presenter/bitmaps/ButtonHelpDisabled.png Binary files differnew file mode 100644 index 000000000000..12f4903b6cf8 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonHelpDisabled.png diff --git a/sdext/source/presenter/bitmaps/ButtonHelpMouseOver.png b/sdext/source/presenter/bitmaps/ButtonHelpMouseOver.png Binary files differnew file mode 100644 index 000000000000..7bddef561f11 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonHelpMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ButtonHelpNormal.png b/sdext/source/presenter/bitmaps/ButtonHelpNormal.png Binary files differnew file mode 100644 index 000000000000..99c693215ba9 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonHelpNormal.png diff --git a/sdext/source/presenter/bitmaps/ButtonHelpSelected.png b/sdext/source/presenter/bitmaps/ButtonHelpSelected.png Binary files differnew file mode 100644 index 000000000000..f162db27650e --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonHelpSelected.png diff --git a/sdext/source/presenter/bitmaps/ButtonMinusDisabled.png b/sdext/source/presenter/bitmaps/ButtonMinusDisabled.png Binary files differnew file mode 100644 index 000000000000..ff61106eb7ec --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonMinusDisabled.png diff --git a/sdext/source/presenter/bitmaps/ButtonMinusMouseOver.png b/sdext/source/presenter/bitmaps/ButtonMinusMouseOver.png Binary files differnew file mode 100644 index 000000000000..787249912b9c --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonMinusMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ButtonMinusNormal.png b/sdext/source/presenter/bitmaps/ButtonMinusNormal.png Binary files differnew file mode 100644 index 000000000000..e2d993384fef --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonMinusNormal.png diff --git a/sdext/source/presenter/bitmaps/ButtonMinusSelected.png b/sdext/source/presenter/bitmaps/ButtonMinusSelected.png Binary files differnew file mode 100644 index 000000000000..5d15de3b916f --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonMinusSelected.png diff --git a/sdext/source/presenter/bitmaps/ButtonNotesDisabled.png b/sdext/source/presenter/bitmaps/ButtonNotesDisabled.png Binary files differnew file mode 100644 index 000000000000..09e31d26c649 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonNotesDisabled.png diff --git a/sdext/source/presenter/bitmaps/ButtonNotesMouseOver.png b/sdext/source/presenter/bitmaps/ButtonNotesMouseOver.png Binary files differnew file mode 100644 index 000000000000..099d6bf0f2b1 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonNotesMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ButtonNotesNormal.png b/sdext/source/presenter/bitmaps/ButtonNotesNormal.png Binary files differnew file mode 100644 index 000000000000..551392622506 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonNotesNormal.png diff --git a/sdext/source/presenter/bitmaps/ButtonNotesSelected.png b/sdext/source/presenter/bitmaps/ButtonNotesSelected.png Binary files differnew file mode 100644 index 000000000000..f5494fb1c678 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonNotesSelected.png diff --git a/sdext/source/presenter/bitmaps/ButtonPlusDisabled.png b/sdext/source/presenter/bitmaps/ButtonPlusDisabled.png Binary files differnew file mode 100644 index 000000000000..e6ba3f3e78a7 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonPlusDisabled.png diff --git a/sdext/source/presenter/bitmaps/ButtonPlusMouseOver.png b/sdext/source/presenter/bitmaps/ButtonPlusMouseOver.png Binary files differnew file mode 100644 index 000000000000..9d21dc40a6eb --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonPlusMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ButtonPlusNormal.png b/sdext/source/presenter/bitmaps/ButtonPlusNormal.png Binary files differnew file mode 100644 index 000000000000..2e075c2a3a87 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonPlusNormal.png diff --git a/sdext/source/presenter/bitmaps/ButtonPlusSelected.png b/sdext/source/presenter/bitmaps/ButtonPlusSelected.png Binary files differnew file mode 100644 index 000000000000..b9d6fe1ed929 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonPlusSelected.png diff --git a/sdext/source/presenter/bitmaps/ButtonSlideNextDisabled.png b/sdext/source/presenter/bitmaps/ButtonSlideNextDisabled.png Binary files differnew file mode 100644 index 000000000000..7f3bce058f4c --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonSlideNextDisabled.png diff --git a/sdext/source/presenter/bitmaps/ButtonSlideNextMouseOver.png b/sdext/source/presenter/bitmaps/ButtonSlideNextMouseOver.png Binary files differnew file mode 100644 index 000000000000..4dc13655965b --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonSlideNextMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ButtonSlideNextNormal.png b/sdext/source/presenter/bitmaps/ButtonSlideNextNormal.png Binary files differnew file mode 100644 index 000000000000..711b8ca8caf6 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonSlideNextNormal.png diff --git a/sdext/source/presenter/bitmaps/ButtonSlidePreviousDisabled.png b/sdext/source/presenter/bitmaps/ButtonSlidePreviousDisabled.png Binary files differnew file mode 100644 index 000000000000..383780eab2cf --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonSlidePreviousDisabled.png diff --git a/sdext/source/presenter/bitmaps/ButtonSlidePreviousMouseOver.png b/sdext/source/presenter/bitmaps/ButtonSlidePreviousMouseOver.png Binary files differnew file mode 100644 index 000000000000..dc35c62deaf2 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonSlidePreviousMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ButtonSlidePreviousNormal.png b/sdext/source/presenter/bitmaps/ButtonSlidePreviousNormal.png Binary files differnew file mode 100644 index 000000000000..26262b4568d7 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonSlidePreviousNormal.png diff --git a/sdext/source/presenter/bitmaps/ButtonSlidePreviousSelected.png b/sdext/source/presenter/bitmaps/ButtonSlidePreviousSelected.png Binary files differnew file mode 100644 index 000000000000..7274263a43f5 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonSlidePreviousSelected.png diff --git a/sdext/source/presenter/bitmaps/ButtonSlideSorterDisabled.png b/sdext/source/presenter/bitmaps/ButtonSlideSorterDisabled.png Binary files differnew file mode 100644 index 000000000000..ce7d4ad51514 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonSlideSorterDisabled.png diff --git a/sdext/source/presenter/bitmaps/ButtonSlideSorterMouseOver.png b/sdext/source/presenter/bitmaps/ButtonSlideSorterMouseOver.png Binary files differnew file mode 100644 index 000000000000..2e7f518ac9e3 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonSlideSorterMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ButtonSlideSorterNormal.png b/sdext/source/presenter/bitmaps/ButtonSlideSorterNormal.png Binary files differnew file mode 100644 index 000000000000..7aa914f41c01 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonSlideSorterNormal.png diff --git a/sdext/source/presenter/bitmaps/ButtonSlideSorterSelected.png b/sdext/source/presenter/bitmaps/ButtonSlideSorterSelected.png Binary files differnew file mode 100644 index 000000000000..143f995a004c --- /dev/null +++ b/sdext/source/presenter/bitmaps/ButtonSlideSorterSelected.png diff --git a/sdext/source/presenter/bitmaps/LabelMouseOverCenter.png b/sdext/source/presenter/bitmaps/LabelMouseOverCenter.png Binary files differnew file mode 100644 index 000000000000..6eb75d386f46 --- /dev/null +++ b/sdext/source/presenter/bitmaps/LabelMouseOverCenter.png diff --git a/sdext/source/presenter/bitmaps/LabelMouseOverLeft.png b/sdext/source/presenter/bitmaps/LabelMouseOverLeft.png Binary files differnew file mode 100644 index 000000000000..9455246332cf --- /dev/null +++ b/sdext/source/presenter/bitmaps/LabelMouseOverLeft.png diff --git a/sdext/source/presenter/bitmaps/LabelMouseOverRight.png b/sdext/source/presenter/bitmaps/LabelMouseOverRight.png Binary files differnew file mode 100644 index 000000000000..1f972d0cebea --- /dev/null +++ b/sdext/source/presenter/bitmaps/LabelMouseOverRight.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarArrowDownDisabled.png b/sdext/source/presenter/bitmaps/ScrollbarArrowDownDisabled.png Binary files differnew file mode 100644 index 000000000000..4dd16272fad7 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarArrowDownDisabled.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarArrowDownMouseOver.png b/sdext/source/presenter/bitmaps/ScrollbarArrowDownMouseOver.png Binary files differnew file mode 100644 index 000000000000..d1980a2a1a05 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarArrowDownMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarArrowDownNormal.png b/sdext/source/presenter/bitmaps/ScrollbarArrowDownNormal.png Binary files differnew file mode 100644 index 000000000000..166f10057c11 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarArrowDownNormal.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarArrowDownSelected.png b/sdext/source/presenter/bitmaps/ScrollbarArrowDownSelected.png Binary files differnew file mode 100644 index 000000000000..21d42945ce98 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarArrowDownSelected.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarArrowUpDisabled.png b/sdext/source/presenter/bitmaps/ScrollbarArrowUpDisabled.png Binary files differnew file mode 100644 index 000000000000..44f60683bc59 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarArrowUpDisabled.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarArrowUpMouseOver.png b/sdext/source/presenter/bitmaps/ScrollbarArrowUpMouseOver.png Binary files differnew file mode 100644 index 000000000000..9795885632dc --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarArrowUpMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarArrowUpNormal.png b/sdext/source/presenter/bitmaps/ScrollbarArrowUpNormal.png Binary files differnew file mode 100644 index 000000000000..804ced846065 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarArrowUpNormal.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarArrowUpSelected.png b/sdext/source/presenter/bitmaps/ScrollbarArrowUpSelected.png Binary files differnew file mode 100644 index 000000000000..d7be4f324f86 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarArrowUpSelected.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarPagerMiddleMouseOver.png b/sdext/source/presenter/bitmaps/ScrollbarPagerMiddleMouseOver.png Binary files differnew file mode 100644 index 000000000000..84b781af9fb8 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarPagerMiddleMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarPagerMiddleNormal.png b/sdext/source/presenter/bitmaps/ScrollbarPagerMiddleNormal.png Binary files differnew file mode 100644 index 000000000000..a06ba667f118 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarPagerMiddleNormal.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarThumbBottomMouseOver.png b/sdext/source/presenter/bitmaps/ScrollbarThumbBottomMouseOver.png Binary files differnew file mode 100644 index 000000000000..482f13638755 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarThumbBottomMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarThumbBottomNormal.png b/sdext/source/presenter/bitmaps/ScrollbarThumbBottomNormal.png Binary files differnew file mode 100644 index 000000000000..ec46e172c134 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarThumbBottomNormal.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarThumbMiddleMouseOver.png b/sdext/source/presenter/bitmaps/ScrollbarThumbMiddleMouseOver.png Binary files differnew file mode 100644 index 000000000000..62066c24b687 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarThumbMiddleMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarThumbMiddleNormal.png b/sdext/source/presenter/bitmaps/ScrollbarThumbMiddleNormal.png Binary files differnew file mode 100644 index 000000000000..c25e4edcf595 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarThumbMiddleNormal.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarThumbTopMouseOver.png b/sdext/source/presenter/bitmaps/ScrollbarThumbTopMouseOver.png Binary files differnew file mode 100644 index 000000000000..714481df996d --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarThumbTopMouseOver.png diff --git a/sdext/source/presenter/bitmaps/ScrollbarThumbTopNormal.png b/sdext/source/presenter/bitmaps/ScrollbarThumbTopNormal.png Binary files differnew file mode 100644 index 000000000000..7e0922c74966 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ScrollbarThumbTopNormal.png diff --git a/sdext/source/presenter/bitmaps/ViewBackground.png b/sdext/source/presenter/bitmaps/ViewBackground.png Binary files differnew file mode 100644 index 000000000000..ca52d8262a88 --- /dev/null +++ b/sdext/source/presenter/bitmaps/ViewBackground.png diff --git a/sdext/source/presenter/delzip b/sdext/source/presenter/delzip new file mode 100644 index 000000000000..636fda90bfcb --- /dev/null +++ b/sdext/source/presenter/delzip @@ -0,0 +1 @@ +ECHO is OFF diff --git a/sdext/source/presenter/description.xml b/sdext/source/presenter/description.xml new file mode 100644 index 000000000000..85393f76e9ff --- /dev/null +++ b/sdext/source/presenter/description.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description + + xmlns="http://openoffice.org/extensions/description/2006" + xmlns:dep="http://openoffice.org/extensions/description/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + + <identifier value="com.sun.PresenterScreen-UPDATED_PLATFORM" /> + + <dependencies> + <OpenOffice.org-minimal-version value="3.3" dep:name="OpenOffice.org 3.3"/> + </dependencies> + + <version value="1.1.0" /> + + <platform value="UPDATED_PLATFORM" /> + + <publisher> + <name xlink:href="http://www.oracle.com/us/products/applications/open-office" lang="en">Oracle</name> + </publisher> + + <display-name> + <name lang="en">Presenter Console</name> + </display-name> + + <icon> + <default xlink:href="bitmaps/extension_32.png" /> + </icon> + +</description> diff --git a/sdext/source/presenter/help/component.txt b/sdext/source/presenter/help/component.txt new file mode 100755 index 000000000000..26a10c622fe9 --- /dev/null +++ b/sdext/source/presenter/help/component.txt @@ -0,0 +1,2 @@ +The Presenter Console Extension provides more control over your slide show presentation, such as the ability to see the upcoming slide, the slide notes, and a presentation timer whereas the audience see only the current slide. +To avoid confusions by displaying a large number of presentation elements, the Presenter Console displays the elements on three different easily changeable views. diff --git a/sdext/source/presenter/help/en-US/com.sun.PresenterScreen/makefile.mk b/sdext/source/presenter/help/en-US/com.sun.PresenterScreen/makefile.mk new file mode 100644 index 000000000000..95678f13aa11 --- /dev/null +++ b/sdext/source/presenter/help/en-US/com.sun.PresenterScreen/makefile.mk @@ -0,0 +1,51 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=../../../../.. +PRJNAME=sdext +TARGET=PresenterScreenHelp +EXTNAME=PresenterScreen + +PACKAGE = com.sun.PresenterScreen + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk + +.IF "$(ENABLE_PRESENTER_SCREEN)" == "NO" +do_nothing: + @echo "Presenter Screen build disabled." +.ELSE + +XHPFILES= \ + presenter.xhp + + +.INCLUDE : target.mk +.INCLUDE : tg_help.mk + +.ENDIF diff --git a/sdext/source/presenter/help/en-US/com.sun.PresenterScreen/presenter.xhp b/sdext/source/presenter/help/en-US/com.sun.PresenterScreen/presenter.xhp new file mode 100644 index 000000000000..ba8f29bb497f --- /dev/null +++ b/sdext/source/presenter/help/en-US/com.sun.PresenterScreen/presenter.xhp @@ -0,0 +1,186 @@ +<?xml version="1.0" encoding="UTF-8"?> +<helpdocument version="1.0"> + +<!-- +*********************************************************************** + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************ + --> + + +<meta> + <topic id="textpresenterxml" indexer="include" status="PUBLISH"> + <title xml-lang="en-US" id="tit" l10n="NEW">@PRESENTEREXTENSIONPRODUCTNAME@ Keyboard Shortcuts</title> + <filename>/com.sun.PresenterScreen-PLATFORMID/presenter.xhp</filename> + </topic> + </meta> + <body> +<bookmark xml-lang="en-US" branch="hid/com.sun.PresenterScreen" id="bm_id3138439" localize="false"/> +<bookmark xml-lang="en-US" branch="index" id="bm_id0921200912285678"><bookmark_value>@PRESENTEREXTENSIONPRODUCTNAME@ shortcuts</bookmark_value> +</bookmark> +<paragraph xml-lang="en-US" id="hd_id0921201912165661" role="heading" level="1" l10n="NEW">@PRESENTEREXTENSIONPRODUCTNAME@ Keyboard Shortcuts</paragraph> + <paragraph xml-lang="en-US" id="par_id0921201912165656" role="paragraph" l10n="NEW">When running a slide show using the @PRESENTEREXTENSIONPRODUCTNAME@, you can use the following keys:</paragraph> + <table id="tbl_id0921200901051232"> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104028" role="tablehead" l10n="NEW">Action</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104093" role="tablehead" l10n="NEW">Key or Keys</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id092120090110418" role="tablecontent" l10n="NEW">Next slide, or next effect</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104120" role="tablecontent" l10n="NEW">Left click, right arrow, down arrow, spacebar, page down, enter, return, 'N'</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104165" role="tablecontent" l10n="NEW">Previous slide, or previous effect</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104115" role="tablecontent" l10n="NEW">Right click, left arrow, up arrow, page up, backspace, 'P'</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104164" role="tablecontent" l10n="NEW">First slide</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104148" role="tablecontent" l10n="NEW">Home</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104221" role="tablecontent" l10n="NEW">Last slide</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104277" role="tablecontent" l10n="NEW">End</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104279" role="tablecontent" l10n="NEW">Previous slide without effects</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id092120090110423" role="tablecontent" l10n="NEW">Alt+Page Up</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id092120090110427" role="tablecontent" l10n="NEW">Next slide without effects</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104261" role="tablecontent" l10n="NEW">Alt+Page Down</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104383" role="tablecontent" l10n="NEW">Black/Unblack the screen</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id092120090110431" role="tablecontent" l10n="NEW">'B', '.'</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104311" role="tablecontent" l10n="NEW">White/Unwhite the screen</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104359" role="tablecontent" l10n="NEW">'W', ','</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104336" role="tablecontent" l10n="NEW">End slide show</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104419" role="tablecontent" l10n="NEW">Esc, '-'</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104460" role="tablecontent" l10n="NEW">Go to slide number</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id092120090110440" role="tablecontent" l10n="NEW">Number followed by Enter</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104427" role="tablecontent" l10n="NEW">Grow/Shrink size of notes font</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104442" role="tablecontent" l10n="NEW">'G', 'S'</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104473" role="tablecontent" l10n="NEW">Scroll notes up/down</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id092120090110459" role="tablecontent" l10n="NEW">'A', 'Z'</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id092120090110456" role="tablecontent" l10n="NEW">Move caret in notes view backward/forward</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id092120090110457" role="tablecontent" l10n="NEW">'H', 'L'</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104566" role="tablecontent" l10n="NEW">Show the @PRESENTEREXTENSIONPRODUCTNAME@</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104544" role="tablecontent" l10n="NEW">Ctrl-'1'</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104535" role="tablecontent" l10n="NEW">Show the Presentation Notes</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104680" role="tablecontent" l10n="NEW">Ctrl-'2'</paragraph> + </tablecell> + </tablerow> + <tablerow> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104634" role="tablecontent" l10n="NEW">Show the Slides Overview</paragraph> + </tablecell> + <tablecell> + <paragraph xml-lang="en-US" id="par_id0921200901104632" role="tablecontent" l10n="NEW">Ctrl-'3'</paragraph> + </tablecell> + </tablerow> + </table> + + </body> +</helpdocument> diff --git a/sdext/source/presenter/makefile.mk b/sdext/source/presenter/makefile.mk new file mode 100644 index 000000000000..1a3c052f8095 --- /dev/null +++ b/sdext/source/presenter/makefile.mk @@ -0,0 +1,385 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. +PRJNAME=sdext +TARGET=PresenterScreen +GEN_HID=FALSE +EXTNAME=PresenterScreen + +ENABLE_EXCEPTIONS=TRUE +# survive zip dependencies +MAXLINELENGTH:=100000 + +# --- Settings ---------------------------------- + +.INCLUDE : rtlbootstrap.mk +.INCLUDE : settings.mk + +PACKAGE=com.sun.PresenterScreen-$(PLATFORMID) + +.IF "$(ENABLE_PRESENTER_SCREEN)" == "NO" +@all: + @echo "Presenter Screen build disabled." +.ELSE + +.IF "$(L10N_framework)"=="" +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +DLLPRE= +common_build_zip= + +# --- Files ------------------------------------- + +SLOFILES= \ + $(SLO)$/PresenterAccessibility.obj \ + $(SLO)$/PresenterAnimation.obj \ + $(SLO)$/PresenterAnimator.obj \ + $(SLO)$/PresenterBitmapContainer.obj \ + $(SLO)$/PresenterButton.obj \ + $(SLO)$/PresenterCanvasHelper.obj \ + $(SLO)$/PresenterConfigurationAccess.obj \ + $(SLO)$/PresenterController.obj \ + $(SLO)$/PresenterCurrentSlideObserver.obj \ + $(SLO)$/PresenterFrameworkObserver.obj \ + $(SLO)$/PresenterGeometryHelper.obj \ + $(SLO)$/PresenterHelper.obj \ + $(SLO)$/PresenterHelpView.obj \ + $(SLO)$/PresenterNotesView.obj \ + $(SLO)$/PresenterPaintManager.obj \ + $(SLO)$/PresenterPane.obj \ + $(SLO)$/PresenterPaneAnimator.obj \ + $(SLO)$/PresenterPaneBase.obj \ + $(SLO)$/PresenterPaneBorderManager.obj \ + $(SLO)$/PresenterPaneBorderPainter.obj \ + $(SLO)$/PresenterPaneContainer.obj \ + $(SLO)$/PresenterPaneFactory.obj \ + $(SLO)$/PresenterProtocolHandler.obj \ + $(SLO)$/PresenterScreen.obj \ + $(SLO)$/PresenterScrollBar.obj \ + $(SLO)$/PresenterSlidePreview.obj \ + $(SLO)$/PresenterSlideShowView.obj \ + $(SLO)$/PresenterSlideSorter.obj \ + $(SLO)$/PresenterSprite.obj \ + $(SLO)$/PresenterSpritePane.obj \ + $(SLO)$/PresenterTextView.obj \ + $(SLO)$/PresenterTheme.obj \ + $(SLO)$/PresenterTimer.obj \ + $(SLO)$/PresenterToolBar.obj \ + $(SLO)$/PresenterUIPainter.obj \ + $(SLO)$/PresenterViewFactory.obj \ + $(SLO)$/PresenterWindowManager.obj \ + $(SLO)$/PresenterComponent.obj + + +# --- Library ----------------------------------- + +SHL1TARGET= $(TARGET).uno + +SHL1STDLIBS= $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +SHL1DEPN= +SHL1IMPLIB= i$(SHL1TARGET) +SHL1LIBS= $(SLB)$/$(TARGET).lib +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +SHL1VERSIONMAP=$(SOLARENV)/src/reg-component.map +SHL1RPATH= OXT +DEF1NAME= $(SHL1TARGET) + +ZIP2TARGET= presenter-screen_develop +ZIP2DIR= $(COMMONMISC) +ZIP2EXT= .zip +ZIP2FLAGS=-r +ZIP2LIST= */com.sun.PresenterScreen/*.xhp + +ZIP1TARGET= presenter-screen +ZIP1DIR= $(MISC)$/$(TARGET) +ZIP1EXT= .oxt +ZIP1FLAGS=-r +ZIP1LIST= * + +DESCRIPTION:=$(ZIP1DIR)$/description.xml + +.IF "$(WITH_LANG)"=="" +FIND_XCU=registry/data +.ELSE # "$(WITH_LANG)"=="" +FIND_XCU=$(MISC)$/$(EXTNAME)_in$/merge +.ENDIF # "$(WITH_LANG)"=="" + +COMPONENT_FILES= \ + $(ZIP1DIR)$/registry$/data$/org$/openoffice$/Office$/Jobs.xcu \ + $(ZIP1DIR)$/registry$/data$/org$/openoffice$/Office$/ProtocolHandler.xcu \ + $(ZIP1DIR)$/registry$/schema/org$/openoffice$/Office$/extension$/PresenterScreen.xcs \ + $(ZIP1DIR)$/registry$/data/$/org$/openoffice$/Office$/extension$/PresenterScreen.xcu + +COMPONENT_BITMAPS= \ + $(ZIP1DIR)$/bitmaps$/BorderTop.png \ + $(ZIP1DIR)$/bitmaps$/BorderTopLeft.png \ + $(ZIP1DIR)$/bitmaps$/BorderTopRight.png \ + $(ZIP1DIR)$/bitmaps$/BorderLeft.png \ + $(ZIP1DIR)$/bitmaps$/BorderRight.png \ + $(ZIP1DIR)$/bitmaps$/BorderBottomLeft.png \ + $(ZIP1DIR)$/bitmaps$/BorderBottomRight.png \ + $(ZIP1DIR)$/bitmaps$/BorderBottom.png \ + \ + $(ZIP1DIR)$/bitmaps$/BorderActiveTop.png \ + $(ZIP1DIR)$/bitmaps$/BorderActiveTopLeft.png \ + $(ZIP1DIR)$/bitmaps$/BorderActiveTopRight.png \ + $(ZIP1DIR)$/bitmaps$/BorderActiveLeft.png \ + $(ZIP1DIR)$/bitmaps$/BorderActiveRight.png \ + $(ZIP1DIR)$/bitmaps$/BorderActiveBottomLeft.png \ + $(ZIP1DIR)$/bitmaps$/BorderActiveBottomRight.png \ + $(ZIP1DIR)$/bitmaps$/BorderActiveBottom.png \ + $(ZIP1DIR)$/bitmaps$/BorderActiveBottomCallout.png \ + \ + $(ZIP1DIR)$/bitmaps$/BorderCurrentSlideTop.png \ + $(ZIP1DIR)$/bitmaps$/BorderCurrentSlideTopLeft.png \ + $(ZIP1DIR)$/bitmaps$/BorderCurrentSlideTopRight.png \ + $(ZIP1DIR)$/bitmaps$/BorderCurrentSlideLeft.png \ + $(ZIP1DIR)$/bitmaps$/BorderCurrentSlideRight.png \ + $(ZIP1DIR)$/bitmaps$/BorderCurrentSlideBottomLeft.png \ + $(ZIP1DIR)$/bitmaps$/BorderCurrentSlideBottomRight.png \ + $(ZIP1DIR)$/bitmaps$/BorderCurrentSlideBottom.png \ + \ + $(ZIP1DIR)$/bitmaps$/BorderToolbarTop.png \ + $(ZIP1DIR)$/bitmaps$/BorderToolbarTopLeft.png \ + $(ZIP1DIR)$/bitmaps$/BorderToolbarTopRight.png \ + $(ZIP1DIR)$/bitmaps$/BorderToolbarLeft.png \ + $(ZIP1DIR)$/bitmaps$/BorderToolbarRight.png \ + $(ZIP1DIR)$/bitmaps$/BorderToolbarBottom.png \ + \ + $(ZIP1DIR)$/bitmaps$/Background.png \ + $(ZIP1DIR)$/bitmaps$/ViewBackground.png \ + \ + $(ZIP1DIR)$/bitmaps$/ButtonSlidePreviousNormal.png \ + $(ZIP1DIR)$/bitmaps$/ButtonSlidePreviousMouseOver.png \ + $(ZIP1DIR)$/bitmaps$/ButtonSlidePreviousSelected.png \ + $(ZIP1DIR)$/bitmaps$/ButtonSlidePreviousDisabled.png \ + $(ZIP1DIR)$/bitmaps$/ButtonEffectNextNormal.png \ + $(ZIP1DIR)$/bitmaps$/ButtonEffectNextMouseOver.png \ + $(ZIP1DIR)$/bitmaps$/ButtonEffectNextSelected.png \ + $(ZIP1DIR)$/bitmaps$/ButtonEffectNextDisabled.png \ + $(ZIP1DIR)$/bitmaps$/ButtonNotesNormal.png \ + $(ZIP1DIR)$/bitmaps$/ButtonNotesMouseOver.png \ + $(ZIP1DIR)$/bitmaps$/ButtonNotesSelected.png \ + $(ZIP1DIR)$/bitmaps$/ButtonNotesDisabled.png \ + $(ZIP1DIR)$/bitmaps$/ButtonSlideSorterNormal.png \ + $(ZIP1DIR)$/bitmaps$/ButtonSlideSorterMouseOver.png \ + $(ZIP1DIR)$/bitmaps$/ButtonSlideSorterSelected.png \ + $(ZIP1DIR)$/bitmaps$/ButtonSlideSorterDisabled.png \ + $(ZIP1DIR)$/bitmaps$/ButtonHelpNormal.png \ + $(ZIP1DIR)$/bitmaps$/ButtonHelpMouseOver.png \ + $(ZIP1DIR)$/bitmaps$/ButtonHelpSelected.png \ + $(ZIP1DIR)$/bitmaps$/ButtonHelpDisabled.png \ + \ + $(ZIP1DIR)$/bitmaps/ScrollbarArrowUpNormal.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarArrowUpMouseOver.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarArrowUpSelected.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarArrowUpDisabled.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarArrowDownNormal.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarArrowDownMouseOver.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarArrowDownSelected.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarArrowDownDisabled.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarPagerMiddleNormal.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarPagerMiddleMouseOver.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarThumbTopNormal.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarThumbTopMouseOver.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarThumbBottomNormal.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarThumbBottomMouseOver.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarThumbMiddleNormal.png \ + $(ZIP1DIR)$/bitmaps/ScrollbarThumbMiddleMouseOver.png \ + \ + $(ZIP1DIR)$/bitmaps$/ButtonPlusNormal.png \ + $(ZIP1DIR)$/bitmaps$/ButtonPlusMouseOver.png \ + $(ZIP1DIR)$/bitmaps$/ButtonPlusSelected.png \ + $(ZIP1DIR)$/bitmaps$/ButtonPlusDisabled.png \ + $(ZIP1DIR)$/bitmaps$/ButtonMinusNormal.png \ + $(ZIP1DIR)$/bitmaps$/ButtonMinusMouseOver.png \ + $(ZIP1DIR)$/bitmaps$/ButtonMinusSelected.png \ + $(ZIP1DIR)$/bitmaps$/ButtonMinusDisabled.png \ + \ + $(ZIP1DIR)$/bitmaps$/ButtonFrameLeftNormal.png \ + $(ZIP1DIR)$/bitmaps$/ButtonFrameCenterNormal.png \ + $(ZIP1DIR)$/bitmaps$/ButtonFrameRightNormal.png \ + $(ZIP1DIR)$/bitmaps$/ButtonFrameLeftMouseOver.png \ + $(ZIP1DIR)$/bitmaps$/ButtonFrameCenterMouseOver.png \ + $(ZIP1DIR)$/bitmaps$/ButtonFrameRightMouseOver.png \ + \ + $(ZIP1DIR)$/bitmaps$/LabelMouseOverLeft.png \ + $(ZIP1DIR)$/bitmaps$/LabelMouseOverCenter.png \ + $(ZIP1DIR)$/bitmaps$/LabelMouseOverRight.png + +COMPONENT_IMAGES=\ + $(ZIP1DIR)$/bitmaps$/extension_32.png + +COMPONENT_MANIFEST= \ + $(ZIP1DIR)$/META-INF$/manifest.xml + +COMPONENT_LIBRARY= \ + $(ZIP1DIR)$/$(TARGET).uno$(DLLPOST) + +PLATFORMID:=$(RTL_OS:l)_$(RTL_ARCH:l) + +COMPONENT_HELP= \ + $(ZIP1DIR)$/help/component.txt \ + $(foreach,l,$(alllangiso) $(ZIP1DIR)$/help$/$l$/com.sun.PresenterScreen-$(PLATFORMID)$/presenter.xhp) + +ZIP1DEPS= \ + $(DESCRIPTION) \ + $(COMPONENT_MANIFEST) \ + $(COMPONENT_FILES) \ + $(COMPONENT_BITMAPS) \ + $(COMPONENT_IMAGES) \ + $(COMPONENT_LIBRARY) \ + $(COMPONENT_HELP) + +LINKNAME:=help +XHPLINKSRC:=$(ZIP1DIR)/help + +my_XHPFILES= \ + presenter.xhp + +LINKLINKFILES= \ + $(PACKAGE)/{$(my_XHPFILES)} + +# --- Targets ---------------------------------- +.ENDIF # L10N_framework + +.INCLUDE : target.mk +.INCLUDE : extension_helplink.mk + +.IF "$(L10N_framework)"=="" +$(SLO)$/PresenterComponent.obj : $(INCCOM)$/PresenterExtensionIdentifier.hxx + +$(INCCOM)$/PresenterExtensionIdentifier.hxx : PresenterExtensionIdentifier.txx + $(TYPE) $< | sed s/UPDATED_PLATFORM/$(PLATFORMID)/ > $@ + +$(COMPONENT_MANIFEST) : $$(@:f) + @-$(MKDIRHIER) $(@:d) + +$(TYPE) $< | $(SED) "s/SHARED_EXTENSION/$(DLLPOST)/" > $@ + +$(ZIP1DIR)$/help$/component.txt : help$/$$(@:f) + @@-$(MKDIRHIER) $(@:d) + $(COPY) $< $@ + +$(ZIP1DIR)/help/%/com.sun.PresenterScreen-$(PLATFORMID)/presenter.xhp : $(COMMONMISC)/%/com.sun.PresenterScreen/presenter.xhp + @echo creating $@ + @-$(MKDIRHIER) $(@:d) + $(TYPE) $< | sed "s/PLATFORMID/$(PLATFORMID)/" | sed 's/@PRESENTEREXTENSIONPRODUCTNAME@/Presenter Console/g' > $@ + +.IF "$(ZIP1TARGETN)"!="" +$(ZIP1TARGETN) : $(HELPLINKALLTARGETS) + +.ENDIF # "$(ZIP1TARGETN)"!="" + +$(COMPONENT_BITMAPS) : bitmaps$/$$(@:f) + @-$(MKDIRHIER) $(@:d) + +$(COPY) $< $@ + +$(COMPONENT_IMAGES) : $(SOLARSRC)$/$(RSCDEFIMG)$/desktop$/res$/$$(@:f) + @@-$(MKDIRHIER) $(@:d) + $(COPY) $< $@ + +$(COMPONENT_LIBRARY) : $(DLLDEST)$/$$(@:f) + @-$(MKDIRHIER) $(@:d) + +$(COPY) $< $@ +.IF "$(OS)$(CPU)"=="WNTI" && "$(WITH_EXTENSION_INTEGRATION)"!="YES" + .IF "$(COM)"=="GCC" + $(GNUCOPY) $(SOLARBINDIR)$/mingwm10.dll $(ZIP1DIR) + .ELSE + .IF "$(PACKMS)"!="" + .IF "$(CCNUMVER)" <= "001399999999" + $(GNUCOPY) $(PACKMS)$/msvcr71.dll $(ZIP1DIR) + $(GNUCOPY) $(PACKMS)$/msvcp71.dll $(ZIP1DIR) + .ELSE + .IF "$(CCNUMVER)" <= "001499999999" + $(GNUCOPY) $(PACKMS)$/msvcr80.dll $(ZIP1DIR) + $(GNUCOPY) $(PACKMS)$/msvcp80.dll $(ZIP1DIR) + $(GNUCOPY) $(PACKMS)$/msvcm80.dll $(ZIP1DIR) + $(GNUCOPY) $(PACKMS)$/Microsoft.VC80.CRT.manifest $(ZIP1DIR) + .ELSE + $(GNUCOPY) $(PACKMS)$/msvcr90.dll $(ZIP1DIR) + $(GNUCOPY) $(PACKMS)$/msvcp90.dll $(ZIP1DIR) + $(GNUCOPY) $(PACKMS)$/msvcm90.dll $(ZIP1DIR) + $(GNUCOPY) $(PACKMS)$/Microsoft.VC90.CRT.manifest $(ZIP1DIR) + .ENDIF + .ENDIF + .ELSE # "$(PACKMS)"!="" + .IF "$(CCNUMVER)" <= "001399999999" + $(GNUCOPY) $(SOLARBINDIR)$/msvcr71.dll $(ZIP1DIR) + $(GNUCOPY) $(SOLARBINDIR)$/msvcp71.dll $(ZIP1DIR) + .ELSE + .IF "$(CCNUMVER)" <= "001499999999" + $(GNUCOPY) $(SOLARBINDIR)$/msvcr80.dll $(ZIP1DIR) + $(GNUCOPY) $(SOLARBINDIR)$/msvcp80.dll $(ZIP1DIR) + $(GNUCOPY) $(SOLARBINDIR)$/msvcm80.dll $(ZIP1DIR) + $(GNUCOPY) $(SOLARBINDIR)$/Microsoft.VC80.CRT.manifest $(ZIP1DIR) + .ELSE + $(GNUCOPY) $(SOLARBINDIR)$/msvcr90.dll $(ZIP1DIR) + $(GNUCOPY) $(SOLARBINDIR)$/msvcp90.dll $(ZIP1DIR) + $(GNUCOPY) $(SOLARBINDIR)$/msvcm90.dll $(ZIP1DIR) + $(GNUCOPY) $(SOLARBINDIR)$/Microsoft.VC90.CRT.manifest $(ZIP1DIR) + .ENDIF + .ENDIF + .ENDIF # "$(PACKMS)"!="" + .ENDIF #"$(COM)"=="GCC" +.ENDIF #"$(OS)$(CPU)"=="WNTI" && "$(WITH_EXTENSION_INTEGRATION)"!="YES" + + + +$(ZIP1DIR)/%.xcu : %.xcu + @@-$(MKDIRHIER) $(@:d) + $(GNUCOPY) $< $@ + +$(ZIP1DIR)$/%.xcs : %.xcs + @@-$(MKDIRHIER) $(@:d) + $(GNUCOPY) $< $@ + +.INCLUDE .IGNORE : $(ZIP1DIR)_lang_track.mk +.IF "$(LAST_WITH_LANG)"!="$(WITH_LANG)" +PHONYDESC=.PHONY +.ENDIF # "$(LAST_WITH_LANG)"!="$(WITH_LANG)" +$(DESCRIPTION) $(PHONYDESC) : $$(@:f) + @-$(MKDIRHIER) $(@:d) + @echo LAST_WITH_LANG=$(WITH_LANG) > $(ZIP1DIR)_lang_track.mk + $(TYPE) description.xml | sed s/UPDATED_PLATFORM/$(PLATFORMID)/ > $@ + +ALLTAR: $(MISC)/../bin/presenter-screen.oxt +# hotfix to missing localizations +.IF "$(WITH_LANG)"!="" + $(COPY) $(ZIP1DIR)_in/merge/org/openoffice/Office/extension/PresenterScreen.xcu $(ZIP1DIR)/registry/data/org/openoffice/Office/extension/ + cd $(ZIP1DIR);zip -r -u ../../bin/presenter-screen.oxt registry/data/org/openoffice/Office/extension/PresenterScreen.xcu +.ENDIF + +.ELSE +ivo: + $(ECHO) +.ENDIF # L10N_framework + +.ENDIF # "$(ENABLE_PRESENTER_SCREEN)" != "NO" diff --git a/sdext/source/presenter/manifest.xml b/sdext/source/presenter/manifest.xml new file mode 100644 index 000000000000..7466467f879f --- /dev/null +++ b/sdext/source/presenter/manifest.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE manifest:manifest PUBLIC "-//OpenOffice.org//DTD Manifest 1.0//EN" "Manifest.dtd"> +<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest"> + <manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-component;type=native" + manifest:full-path="PresenterScreen.unoSHARED_EXTENSION"/> + <manifest:file-entry manifest:media-type="application/vnd.sun.star.configuration-data" + manifest:full-path="registry/data/org/openoffice/Office/Jobs.xcu"/> + <manifest:file-entry manifest:media-type="application/vnd.sun.star.configuration-data" + manifest:full-path="registry/data/org/openoffice/Office/ProtocolHandler.xcu"/> + <manifest:file-entry manifest:media-type="application/vnd.sun.star.configuration-data" + manifest:full-path="registry/data/org/openoffice/Office/extension/PresenterScreen.xcu"/> + <manifest:file-entry manifest:media-type="application/vnd.sun.star.configuration-schema" + manifest:full-path="registry/schema/org/openoffice/Office/extension/PresenterScreen.xcs"/> + <manifest:file-entry manifest:media-type="application/vnd.sun.star.help" + manifest:full-path="help"/> + <manifest:file-entry manifest:media-type="application/vnd.sun.star.package-bundle-description" + manifest:full-path="help/component.txt"/> +</manifest:manifest> diff --git a/sdext/source/presenter/registry/data/org/openoffice/Office/Jobs.xcu b/sdext/source/presenter/registry/data/org/openoffice/Office/Jobs.xcu new file mode 100644 index 000000000000..1241a72a0243 --- /dev/null +++ b/sdext/source/presenter/registry/data/org/openoffice/Office/Jobs.xcu @@ -0,0 +1,20 @@ +<?xml version='1.0' encoding='UTF-8'?> +<oor:component-data oor:name="Jobs" oor:package="org.openoffice.Office" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <node oor:name="Jobs"> + <node oor:name="onDocumentOpenedJob" oor:op="replace"> + <prop oor:name="Service"> + <value>com.sun.star.comp.Draw.framework.PresenterScreenJob</value> + </prop> + <prop oor:name="Context"> + <value>com.sun.star.presentation.PresentationDocument</value> + </prop> + </node> + </node> + <node oor:name="Events"> + <node oor:name="onDocumentOpened" oor:op="fuse"> + <node oor:name="JobList"> + <node oor:name="onDocumentOpenedJob" oor:op="replace"/> + </node> + </node> + </node> +</oor:component-data> diff --git a/sdext/source/presenter/registry/data/org/openoffice/Office/ProtocolHandler.xcu b/sdext/source/presenter/registry/data/org/openoffice/Office/ProtocolHandler.xcu new file mode 100644 index 000000000000..0f8369973a20 --- /dev/null +++ b/sdext/source/presenter/registry/data/org/openoffice/Office/ProtocolHandler.xcu @@ -0,0 +1,10 @@ +<?xml version='1.0' encoding='UTF-8'?> +<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="ProtocolHandler" oor:package="org.openoffice.Office"> + <node oor:name="HandlerSet"> + <node oor:name="vnd.sun.star.sdext.presenter.PresenterProtocolHandler" oor:op="replace"> + <prop oor:name="Protocols"> + <value>vnd.com.sun.star.comp.PresenterScreen:*</value> + </prop> + </node> + </node> +</oor:component-data> diff --git a/sdext/source/presenter/registry/data/org/openoffice/Office/extension/PresenterScreen.xcu b/sdext/source/presenter/registry/data/org/openoffice/Office/extension/PresenterScreen.xcu new file mode 100644 index 000000000000..22316392f807 --- /dev/null +++ b/sdext/source/presenter/registry/data/org/openoffice/Office/extension/PresenterScreen.xcu @@ -0,0 +1,1224 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!--*********************************************************************** + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************ --> +<!DOCTYPE oor:component-data SYSTEM "../../../../component-update.dtd"> +<oor:component-data xmlns:install="http://openoffice.org/2004/installation" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" oor:package="org.openoffice.Office.extension" oor:name="PresenterScreen"> + <node oor:name="PresenterScreenSettings"> + <node oor:name="ToolBars"> + <node oor:name="ToolBar" oor:op="replace"> + <node oor:name="Entries"> + <node oor:name="a" oor:op="replace"> + <prop oor:name="Name"><value>PreviousSlide</value></prop> + <prop oor:name="Type"><value>Button</value></prop> + <node oor:name="Normal"> + <prop oor:name="Text"><value xml:lang="en-US">Previous</value></prop> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonSlidePreviousNormal.png</value></prop> + </node> + <prop oor:name="Action"><value>vnd.com.sun.star.comp.PresenterScreen:PrevSlide</value></prop> + <node oor:name="Font"> + <prop oor:name="Size"><value>12</value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Color"><value>B3B7BC</value></prop> + <prop oor:name="Anchor"><value>Center</value></prop> + </node> + </node> + <node oor:name="MouseOver"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonSlidePreviousMouseOver.png</value></prop> + </node> + <node oor:name="Font"> + <prop oor:name="Color"><value>FFFFFF</value></prop> + </node> + </node> + <node oor:name="Disabled"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonSlidePreviousDisabled.png</value></prop> + </node> + </node> + </node> + <node oor:name="b" oor:op="replace"> + <prop oor:name="Name"><value>NextEffect</value></prop> + <prop oor:name="Type"><value>Button</value></prop> + <node oor:name="Normal"> + <prop oor:name="Text"><value xml:lang="en-US">Next</value></prop> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonEffectNextNormal.png</value></prop> + </node> + <prop oor:name="Action"><value>vnd.com.sun.star.comp.PresenterScreen:NextEffect</value></prop> + <node oor:name="Font"> + <prop oor:name="Size"><value>12</value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Color"><value>B3B7BC</value></prop> + <prop oor:name="Anchor"><value>Center</value></prop> + </node> + </node> + <node oor:name="MouseOver"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonEffectNextMouseOver.png</value></prop> + </node> + <node oor:name="Font"> + <prop oor:name="Color"><value>FFFFFF</value></prop> + </node> + </node> + <node oor:name="Disabled"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonEffectNextDisabled.png</value></prop> + </node> + </node> + </node> + <node oor:name="c" oor:op="replace"> + <prop oor:name="Name"><value>Notes</value></prop> + <prop oor:name="Type"><value>Button</value></prop> + <node oor:name="Normal"> + <prop oor:name="Text"><value xml:lang="en-US">Notes</value></prop> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonNotesNormal.png</value></prop> + </node> + <prop oor:name="Action"><value>vnd.com.sun.star.comp.PresenterScreen:ShowNotes</value></prop> + <node oor:name="Font"> + <prop oor:name="Size"><value>12</value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Color"><value>B3B7BC</value></prop> + <prop oor:name="Anchor"><value>Center</value></prop> + </node> + </node> + <node oor:name="MouseOver"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonNotesMouseOver.png</value></prop> + </node> + <node oor:name="Font"> + <prop oor:name="Color"><value>FFFFFF</value></prop> + </node> + </node> + <node oor:name="Selected"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonNotesSelected.png</value></prop> + </node> + <node oor:name="Font"> + <prop oor:name="Color"><value>FFFFFF</value></prop> + </node> + <prop oor:name="Action"><value>vnd.com.sun.star.comp.PresenterScreen:CloseNotes</value></prop> + </node> + <node oor:name="Disabled"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonNotesDisabled.png</value></prop> + </node> + </node> + </node> + <node oor:name="d" oor:op="replace"> + <prop oor:name="Name"><value>SlideSorter</value></prop> + <prop oor:name="Type"><value>Button</value></prop> + <node oor:name="Normal"> + <prop oor:name="Text"><value xml:lang="en-US">Slides</value></prop> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonSlideSorterNormal.png</value></prop> + </node> + <prop oor:name="Action"><value>vnd.com.sun.star.comp.PresenterScreen:ShowSlideSorter</value></prop> + <node oor:name="Font"> + <prop oor:name="Size"><value>12</value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Color"><value>B3B7BC</value></prop> + <prop oor:name="Anchor"><value>Center</value></prop> + </node> + </node> + <node oor:name="MouseOver"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonSlideSorterMouseOver.png</value></prop> + </node> + <node oor:name="Font"> + <prop oor:name="Color"><value>FFFFFF</value></prop> + </node> + </node> + <node oor:name="Selected"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonSlideSorterSelected.png</value></prop> + </node> + <node oor:name="Font"> + <prop oor:name="Color"><value>FFFFFF</value></prop> + </node> + <prop oor:name="Action"><value>vnd.com.sun.star.comp.PresenterScreen:CloseSlideSorter</value></prop> + </node> + <node oor:name="Disabled"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonSlideSorterDisabled.png</value></prop> + </node> + </node> + </node> + <node oor:name="e" oor:op="replace"> + <prop oor:name="Type"><value>VerticalSeparator</value></prop> + <node oor:name="Normal"> + <node oor:name="Font"> + <prop oor:name="Color"><value>76797C</value></prop> + </node> + </node> + </node> + <node oor:name="f" oor:op="replace"> + <prop oor:name="Type"><value>ChangeOrientation</value></prop> + </node> + <node oor:name="g" oor:op="replace"> + <prop oor:name="Type"><value>CurrentTimeLabel</value></prop> + <node oor:name="Normal"> + <node oor:name="Font"> + <prop oor:name="Size"><value>18</value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Color"><value>ffffff</value></prop> + <prop oor:name="Anchor"><value>Center</value></prop> + </node> + </node> + </node> + <node oor:name="h" oor:op="replace"> + <prop oor:name="Type"><value>HorizontalSeparator</value></prop> + <node oor:name="Normal"> + <node oor:name="Font"> + <prop oor:name="Color"><value>71767a</value></prop> + </node> + </node> + </node> + <node oor:name="i" oor:op="replace"> + <prop oor:name="Type"><value>PresentationTimeLabel</value></prop> + <node oor:name="Normal"> + <node oor:name="Font"> + <prop oor:name="Size"><value>26</value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Color"><value>ffe969</value></prop> + <prop oor:name="Anchor"><value>Center</value></prop> + </node> + </node> + </node> + <node oor:name="j" oor:op="replace"> + <prop oor:name="Type"><value>ChangeOrientation</value></prop> + </node> + <node oor:name="k" oor:op="replace"> + <prop oor:name="Type"><value>VerticalSeparator</value></prop> + <node oor:name="Normal"> + <node oor:name="Font"> + <prop oor:name="Color"><value>76797C</value></prop> + </node> + </node> + </node> + <node oor:name="l" oor:op="replace"> + <prop oor:name="Name"><value>Help</value></prop> + <prop oor:name="Type"><value>Button</value></prop> + <node oor:name="Normal"> + <prop oor:name="Text"><value xml:lang="en-US">Help</value></prop> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonHelpNormal.png</value></prop> + </node> + <prop oor:name="Action"><value>vnd.com.sun.star.comp.PresenterScreen:ShowHelp</value></prop> + <node oor:name="Font"> + <prop oor:name="Size"><value>12</value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Color"><value>B3B7BC</value></prop> + <prop oor:name="Anchor"><value>Center</value></prop> + </node> + </node> + <node oor:name="MouseOver"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonHelpMouseOver.png</value></prop> + </node> + <node oor:name="Font"> + <prop oor:name="Color"><value>FFFFFF</value></prop> + </node> + </node> + <node oor:name="Selected"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonHelpSelected.png</value></prop> + </node> + <node oor:name="Font"> + <prop oor:name="Color"><value>FFFFFF</value></prop> + </node> + <prop oor:name="Action"><value>vnd.com.sun.star.comp.PresenterScreen:CloseHelp</value></prop> + </node> + <node oor:name="Disabled"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonHelpDisabled.png</value></prop> + </node> + </node> + </node> + </node> + </node> + <node oor:name="NotesToolBar" oor:op="replace"> + <node oor:name="Entries"> + <node oor:name="a" oor:op="replace"> + <prop oor:name="Name"><value>Zoom</value></prop> + <prop oor:name="Type"><value>Label</value></prop> + <node oor:name="Normal"> + <prop oor:name="Text"><value xml:lang="en-US">Zoom</value></prop> + <node oor:name="Font"> + <prop oor:name="Size"><value>14</value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Color"><value>B3B7BC</value></prop> + </node> + </node> + </node> + <node oor:name="b" oor:op="replace"> + <prop oor:name="Name"><value>Grow</value></prop> + <prop oor:name="Type"><value>Button</value></prop> + <node oor:name="Normal"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonPlusNormal.png</value></prop> + </node> + <prop oor:name="Action"><value>vnd.com.sun.star.comp.PresenterScreen:GrowNotesFont</value></prop> + </node> + <node oor:name="MouseOver"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonPlusMouseOver.png</value></prop> + </node> + </node> + <node oor:name="Disabled"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonPlusDisabled.png</value></prop> + </node> + </node> + </node> + <node oor:name="c" oor:op="replace"> + <prop oor:name="Name"><value>Shrink</value></prop> + <prop oor:name="Type"><value>Button</value></prop> + <node oor:name="Normal"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonMinusNormal.png</value></prop> + </node> + <prop oor:name="Action"><value>vnd.com.sun.star.comp.PresenterScreen:ShrinkNotesFont</value></prop> + </node> + <node oor:name="MouseOver"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonMinusMouseOver.png</value></prop> + </node> + </node> + <node oor:name="Disabled"> + <node oor:name="Icon"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonMinusDisabled.png</value></prop> + </node> + </node> + </node> + </node> + </node> + </node> + <node oor:name="Buttons"> + <node oor:name="SlideSorterCloser" oor:op="replace"> + <prop oor:name="Name"><value>SlideSorterCloser</value></prop> + <prop oor:name="Text"> + <value xml:lang="en-US">Close</value> + </prop> + <prop oor:name="Action"><value>vnd.com.sun.star.comp.PresenterScreen:CloseSlideSorter</value></prop> + </node> + <node oor:name="NotesViewCloser" oor:op="replace"> + <prop oor:name="Name"><value>NotesViewCloser</value></prop> + <prop oor:name="Text"> + <value xml:lang="en-US">Close</value> + </prop> + <prop oor:name="Action"><value>vnd.com.sun.star.comp.PresenterScreen:CloseNotes</value></prop> + </node> + <node oor:name="HelpViewCloser" oor:op="replace"> + <prop oor:name="Name"><value>HelpViewCloser</value></prop> + <prop oor:name="Text"> + <value xml:lang="en-US">Close</value> + </prop> + <prop oor:name="Action"><value>vnd.com.sun.star.comp.PresenterScreen:CloseHelp</value></prop> + </node> + </node> + <node oor:name="ScrollBar"> + <node oor:name="Bitmaps"> + <node oor:name="up" oor:op="replace"> + <prop oor:name="Name"><value>Up</value></prop> + <prop oor:name="NormalFileName"><value>bitmaps/ScrollbarArrowUpNormal.png</value></prop> + <prop oor:name="MouseOverFileName"><value>bitmaps/ScrollbarArrowUpMouseOver.png</value></prop> + <prop oor:name="DisabledFileName"><value>bitmaps/ScrollbarArrowUpDisabled.png</value></prop> + </node> + <node oor:name="down" oor:op="replace"> + <prop oor:name="Name"><value>Down</value></prop> + <prop oor:name="NormalFileName"><value>bitmaps/ScrollbarArrowDownNormal.png</value></prop> + <prop oor:name="MouseOverFileName"><value>bitmaps/ScrollbarArrowDownMouseOver.png</value></prop> + <prop oor:name="DisabledFileName"><value>bitmaps/ScrollbarArrowDownDisabled.png</value></prop> + </node> + <node oor:name="pagervertical" oor:op="replace"> + <prop oor:name="Name"><value>PagerVertical</value></prop> + <prop oor:name="NormalFileName"><value>bitmaps/ScrollbarPagerMiddleNormal.png</value></prop> + <prop oor:name="MouseOverFileName"><value>bitmaps/ScrollbarPagerMiddleMouseOver.png</value></prop> + </node> + <node oor:name="thumbtop" oor:op="replace"> + <prop oor:name="Name"><value>ThumbTop</value></prop> + <prop oor:name="NormalFileName"><value>bitmaps/ScrollbarThumbTopNormal.png</value></prop> + <prop oor:name="MouseOverFileName"><value>bitmaps/ScrollbarThumbTopMouseOver.png</value></prop> + </node> + <node oor:name="thumbbottom" oor:op="replace"> + <prop oor:name="Name"><value>ThumbBottom</value></prop> + <prop oor:name="NormalFileName"><value>bitmaps/ScrollbarThumbBottomNormal.png</value></prop> + <prop oor:name="MouseOverFileName"><value>bitmaps/ScrollbarThumbBottomMouseOver.png</value></prop> + </node> + <node oor:name="thumbvertical" oor:op="replace"> + <prop oor:name="Name"><value>ThumbVertical</value></prop> + <prop oor:name="NormalFileName"><value>bitmaps/ScrollbarThumbMiddleNormal.png</value></prop> + <prop oor:name="MouseOverFileName"><value>bitmaps/ScrollbarThumbMiddleMouseOver.png</value></prop> + </node> + </node> + </node> + <node oor:name="SlideSorter"> + <node oor:name="BorderSize"> + <prop oor:name="Left"><value>9</value></prop> + <prop oor:name="Top"><value>9</value></prop> + <prop oor:name="Right"><value>9</value></prop> + <prop oor:name="Bottom"><value>9</value></prop> + </node> + <node oor:name="CurrentSlideBorderBitmaps"> + <node oor:name="TopLeft" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderCurrentSlideTopLeft.png</value></prop> + </node> + <node oor:name="Top" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderCurrentSlideTop.png</value></prop> + </node> + <node oor:name="TopRight" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderCurrentSlideTopRight.png</value></prop> + </node> + <node oor:name="Left" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderCurrentSlideLeft.png</value></prop> + </node> + <node oor:name="Right" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderCurrentSlideRight.png</value></prop> + </node> + <node oor:name="BottomLeft" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderCurrentSlideBottomLeft.png</value></prop> + </node> + <node oor:name="Bottom" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderCurrentSlideBottom.png</value></prop> + </node> + <node oor:name="BottomRight" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderCurrentSlideBottomRight.png</value></prop> + </node> + </node> + </node> + <node oor:name="HelpView"> + <node oor:name="HelpStrings"> + <node oor:name="a" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">Left click, right or down arrow, spacebar, page down, enter, return, 'N'</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">Next slide, or next effect</value> + </prop> + </node> + <node oor:name="b" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">Right click, left or up arrow, page up, backspace, 'P'</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">Previous slide, or previous effect</value> + </prop> + </node> + <node oor:name="c" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US"> </value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US"> </value> + </prop> + </node> + <node oor:name="d" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">Home</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">First slide</value> + </prop> + </node> + <node oor:name="e" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">End</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">Last slide</value> + </prop> + </node> + <node oor:name="f" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US"> </value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US"> </value> + </prop> + </node> + <node oor:name="g" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">Alt-Page Up</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">Previous slide without effects</value> + </prop> + </node> + <node oor:name="h" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">Alt-Page Down</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">Next slide without effects</value> + </prop> + </node> + <node oor:name="i" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US"> </value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US"> </value> + </prop> + </node> + <node oor:name="j" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">'B', '.'</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">Blacks/Unblacks the screen</value> + </prop> + </node> + <node oor:name="k" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">'W', ','</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">Whites/Unwhites the screen</value> + </prop> + </node> + <node oor:name="l" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US"> </value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US"> </value> + </prop> + </node> + <node oor:name="m" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">Esc, '-'</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">End slide show</value> + </prop> + </node> + <node oor:name="n" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US"> </value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US"> </value> + </prop> + </node> + <node oor:name="o" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">Number followed by Enter</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">Go to that slide</value> + </prop> + </node> + <node oor:name="p" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US"> </value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US"> </value> + </prop> + </node> + <node oor:name="q" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">'G', 'S'</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">Grow/Shrink size of notes font</value> + </prop> + </node> + <node oor:name="r" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">'A', 'Z'</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">Scroll notes up/down</value> + </prop> + </node> + <node oor:name="s" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">'H', 'L'</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">Move caret in notes view backward/forward</value> + </prop> + </node> + <node oor:name="t" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US"> </value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US"> </value> + </prop> + </node> + <node oor:name="u" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">Ctrl-'1'</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">Shows the Presenter Console</value> + </prop> + </node> + <node oor:name="v" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">Ctrl-'2'</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">Shows the Presentation Notes</value> + </prop> + </node> + <node oor:name="w" oor:op="replace"> + <prop oor:name="Left"> + <value xml:lang="en-US">Ctrl-'3'</value> + </prop> + <prop oor:name="Right"> + <value xml:lang="en-US">Shows the Slides Overview</value> + </prop> + </node> + </node> + </node> + </node> + <node oor:name="Presenter"> + <node oor:name="Themes"> + <node oor:name="Theme_1" oor:op="replace"> + <prop oor:name="ThemeName"> + <value>DefaultTheme</value> + </prop> + <node oor:name="PaneStyles"> + <node oor:name="PaneStyle_1" oor:op="replace"> + <prop oor:name="StyleName"> + <value>DefaultPaneStyle</value> + </prop> + <node oor:name="TitleFont"> + <prop oor:name="FamilyName"><value></value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Size"><value>14</value></prop> + <prop oor:name="Color"><value>B3B7BC</value></prop> + <prop oor:name="Anchor"><value>Center</value></prop> + <prop oor:name="YOffset"><value>-7</value></prop> + </node> + <node oor:name="InnerBorderSize"> + <prop oor:name="Left"><value>6</value></prop> + <prop oor:name="Top"><value>6</value></prop> + <prop oor:name="Right"><value>6</value></prop> + <prop oor:name="Bottom"><value>6</value></prop> + </node> + <node oor:name="OuterBorderSize"> + <prop oor:name="Left"><value>20</value></prop> + <prop oor:name="Top"><value>28</value></prop> + <prop oor:name="Right"><value>20</value></prop> + <prop oor:name="Bottom"><value>29</value></prop> + </node> + <node oor:name="BorderBitmapList"> + <node oor:name="Top" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderTop.png</value></prop> + <prop oor:name="YOffset"><value>6</value></prop> + </node> + <node oor:name="TopLeft" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderTopLeft.png</value></prop> + <prop oor:name="XOffset"><value>6</value></prop> + <prop oor:name="YOffset"><value>6</value></prop> + </node> + <node oor:name="TopRight" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderTopRight.png</value></prop> + <prop oor:name="XOffset"><value>-6</value></prop> + <prop oor:name="YOffset"><value>6</value></prop> + </node> + <node oor:name="Left" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderLeft.png</value></prop> + <prop oor:name="XOffset"><value>6</value></prop> + </node> + <node oor:name="Right" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderRight.png</value></prop> + <prop oor:name="XOffset"><value>-6</value></prop> + </node> + <node oor:name="BottomLeft" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderBottomLeft.png</value></prop> + <prop oor:name="XOffset"><value>6</value></prop> + <prop oor:name="YOffset"><value>-6</value></prop> + </node> + <node oor:name="BottomRight" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderBottomRight.png</value></prop> + <prop oor:name="XOffset"><value>-6</value></prop> + <prop oor:name="YOffset"><value>-6</value></prop> + </node> + <node oor:name="Bottom" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderBottom.png</value></prop> + <prop oor:name="YOffset"><value>-6</value></prop> + </node> + </node> + </node> + <node oor:name="PaneStyle_2" oor:op="replace"> + <prop oor:name="StyleName"> + <value>ActivePaneStyle</value> + </prop> + <prop oor:name="ParentStyle"> + <value>DefaultPaneStyle</value> + </prop> + <node oor:name="TitleFont"> + <prop oor:name="FamilyName"><value></value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Size"><value>14</value></prop> + <prop oor:name="Color"><value>FFFFFF</value></prop> + <prop oor:name="Anchor"><value>Center</value></prop> + <prop oor:name="YOffset"><value>-10</value></prop> + </node> + <node oor:name="BorderBitmapList"> + <node oor:name="Top" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderActiveTop.png</value></prop> + <prop oor:name="YOffset"><value>6</value></prop> + </node> + <node oor:name="TopLeft" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderActiveTopLeft.png</value></prop> + <prop oor:name="XOffset"><value>6</value></prop> + <prop oor:name="YOffset"><value>6</value></prop> + </node> + <node oor:name="TopRight" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderActiveTopRight.png</value></prop> + <prop oor:name="XOffset"><value>-6</value></prop> + <prop oor:name="YOffset"><value>6</value></prop> + </node> + <node oor:name="Left" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderActiveLeft.png</value></prop> + <prop oor:name="XOffset"><value>6</value></prop> + </node> + <node oor:name="Right" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderActiveRight.png</value></prop> + <prop oor:name="XOffset"><value>-6</value></prop> + </node> + <node oor:name="BottomLeft" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderActiveBottomLeft.png</value></prop> + <prop oor:name="XOffset"><value>6</value></prop> + <prop oor:name="YOffset"><value>-6</value></prop> + </node> + <node oor:name="BottomRight" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderActiveBottomRight.png</value></prop> + <prop oor:name="XOffset"><value>-6</value></prop> + <prop oor:name="YOffset"><value>-6</value></prop> + </node> + <node oor:name="Bottom" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderActiveBottom.png</value></prop> + <prop oor:name="YOffset"><value>-6</value></prop> + </node> + </node> + </node> + <node oor:name="PaneStyle_3" oor:op="replace"> + <prop oor:name="StyleName"> + <value>ToolbarPaneStyle</value> + </prop> + <node oor:name="InnerBorderSize"> + <prop oor:name="Left"><value>4</value></prop> + <prop oor:name="Top"><value>4</value></prop> + <prop oor:name="Right"><value>4</value></prop> + <prop oor:name="Bottom"><value>4</value></prop> + </node> + <node oor:name="OuterBorderSize"> + <prop oor:name="Left"><value>8</value></prop> + <prop oor:name="Top"><value>8</value></prop> + <prop oor:name="Right"><value>8</value></prop> + <prop oor:name="Bottom"><value>0</value></prop> + </node> + <node oor:name="BorderBitmapList"> + <node oor:name="Top" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderToolbarTop.png</value></prop> + <prop oor:name="YOffset"><value>4</value></prop> + </node> + <node oor:name="TopLeft" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderToolbarTopLeft.png</value></prop> + <prop oor:name="XOffset"><value>4</value></prop> + <prop oor:name="YOffset"><value>4</value></prop> + </node> + <node oor:name="TopRight" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderToolbarTopRight.png</value></prop> + <prop oor:name="XOffset"><value>-4</value></prop> + <prop oor:name="YOffset"><value>4</value></prop> + </node> + <node oor:name="Left" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderToolbarLeft.png</value></prop> + <prop oor:name="XOffset"><value>4</value></prop> + </node> + <node oor:name="Right" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderToolbarRight.png</value></prop> + <prop oor:name="XOffset"><value>-4</value></prop> + </node> + <node oor:name="BottomLeft" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderToolbarLeft.png</value></prop> + <prop oor:name="XOffset"><value>4</value></prop> + </node> + <node oor:name="BottomRight" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderToolbarRight.png</value></prop> + <prop oor:name="XOffset"><value>-4</value></prop> + </node> + <node oor:name="Bottom" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderToolbarBottom.png</value></prop> + <prop oor:name="YOffset"><value>-4</value></prop> + </node> + </node> + </node> + <node oor:name="PaneStyle_4" oor:op="replace"> + <prop oor:name="StyleName"> + <value>ActiveBottomCalloutPaneStyle</value> + </prop> + <prop oor:name="ParentStyle"> + <value>ActivePaneStyle</value> + </prop> + <node oor:name="OuterBorderSize"> + <prop oor:name="Bottom"><value>52</value></prop> + </node> + <node oor:name="BorderBitmapList"> + <node oor:name="BottomCallout" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/BorderActiveBottomCallout.png</value></prop> + <prop oor:name="YOffset"><value>-6</value></prop> + <prop oor:name="XHotSpot"><value>49</value></prop> + <prop oor:name="YHotSpot"><value>41</value></prop> + </node> + </node> + </node> + </node> + <node oor:name="ViewStyles"> + <node oor:name="ViewStyle_1" oor:op="replace"> + <prop oor:name="StyleName"><value>DefaultViewStyle</value></prop> + <node oor:name="Font"> + <prop oor:name="FamilyName"><value></value></prop> + <prop oor:name="Size"><value>20</value></prop> + <prop oor:name="Color"><value>FFFFFF</value> + </prop> + </node> + <node oor:name="Background"> + <prop oor:name="NormalFileName"><value>bitmaps/ViewBackground.png</value></prop> + <prop oor:name="HorizontalTexturingMode"><value>Repeat</value></prop> + <prop oor:name="VerticalTexturingMode"><value>Repeat</value></prop> + <prop oor:name="ReplacementColor"><value>33000000</value></prop> + </node> + </node> + <node oor:name="ViewStyle_2" oor:op="replace"> + <prop oor:name="StyleName"><value>NotesViewStyle</value></prop> + <prop oor:name="ParentStyle"><value>DefaultViewStyle</value></prop> + <node oor:name="Font"> + <prop oor:name="FamilyName"><value></value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Size"><value>26</value></prop> + <prop oor:name="Color"><value>d1d6dc</value></prop> + </node> + </node> + <node oor:name="ViewStyle_3" oor:op="replace"> + <prop oor:name="StyleName"><value>SlideSorterViewStyle</value></prop> + <prop oor:name="ParentStyle"><value>DefaultViewStyle</value></prop> + </node> + <node oor:name="ViewStyle_4" oor:op="replace"> + <prop oor:name="StyleName"><value>HelpViewStyle</value></prop> + <prop oor:name="ParentStyle"><value>DefaultViewStyle</value></prop> + <node oor:name="Font"> + <prop oor:name="FamilyName"><value></value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Size"><value>20</value></prop> + <prop oor:name="Color"><value>ffffff</value></prop> + </node> + </node> + </node> + <node oor:name="Background"> + <prop oor:name="NormalFileName"><value>bitmaps/Background.png</value></prop> + <prop oor:name="ReplacementColor"><value>E4EFF9</value></prop> + <prop oor:name="HorizontalTexturingMode"><value>Repeat</value></prop> + <prop oor:name="VerticalTexturingMode"><value>Stretch</value></prop> + </node> + <node oor:name="Bitmaps"> + <node oor:name="ButtonFrameLeft" oor:op="replace"> + <prop oor:name="Name"><value>ButtonFrameLeft</value></prop> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonFrameLeftNormal.png</value></prop> + <prop oor:name="MouseOverFileName"><value>bitmaps/ButtonFrameLeftMouseOver.png</value></prop> + <prop oor:name="YOffset"><value>2</value></prop> + </node> + <node oor:name="ButtonFrameCenter" oor:op="replace"> + <prop oor:name="Name"><value>ButtonFrameCenter</value></prop> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonFrameCenterNormal.png</value></prop> + <prop oor:name="MouseOverFileName"><value>bitmaps/ButtonFrameCenterMouseOver.png</value></prop> + <prop oor:name="YOffset"><value>2</value></prop> + </node> + <node oor:name="ButtonFrameRight" oor:op="replace"> + <prop oor:name="Name"><value>ButtonFrameRight</value></prop> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonFrameRightNormal.png</value></prop> + <prop oor:name="MouseOverFileName"><value>bitmaps/ButtonFrameRightMouseOver.png</value></prop> + <prop oor:name="YOffset"><value>2</value></prop> + </node> + <node oor:name="LabelLeft" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/LabelMouseOverLeft.png</value></prop> + </node> + <node oor:name="LabelCenter" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/LabelMouseOverCenter.png</value></prop> + </node> + <node oor:name="LabelRight" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/LabelMouseOverRight.png</value></prop> + </node> + <node oor:name="MousePointerNextEffect" oor:op="replace"> + <prop oor:name="NormalFileName"><value>bitmaps/ButtonSlideNextNormal.png</value></prop> + </node> + </node> + <node oor:name="Fonts"> + <node oor:name="ButtonFont" oor:op="replace"> + <prop oor:name="FamilyName"><value></value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Size"><value>18</value></prop> + <prop oor:name="Color"><value>b3b7bc</value></prop> + </node> + <node oor:name="ButtonMouseOverFont" oor:op="replace"> + <prop oor:name="FamilyName"><value></value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Size"><value>18</value></prop> + <prop oor:name="Color"><value>ffffff</value></prop> + </node> + <node oor:name="SlideSorterLabelFont" oor:op="replace"> + <prop oor:name="FamilyName"><value></value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Size"><value>20</value></prop> + <prop oor:name="Color"><value>ffffff</value></prop> + </node> + <node oor:name="PendingSlideNumberFont" oor:op="replace"> + <prop oor:name="FamilyName"><value></value></prop> + <prop oor:name="Style"><value>Bold</value></prop> + <prop oor:name="Size"><value>24</value></prop> + <prop oor:name="Color"><value>e02050</value></prop> + </node> + </node> + <node oor:name="StyleAssociations"> + <node oor:name="PreviewPane" oor:op="replace"> + <prop oor:name="ResourceURL"> + <value>private:resource/pane/Presenter/Pane1</value> + </prop> + <prop oor:name="StyleName"> + <value>ActivePaneStyle</value> + </prop> + </node> + <node oor:name="PreviewView" oor:op="replace"> + <prop oor:name="ResourceURL"> + <value>private:resource/view/Presenter/CurrentSlidePreview</value> + </prop> + <prop oor:name="StyleName"> + <value>DefaultViewStyle</value> + </prop> + </node> + <node oor:name="NextSlidePreviewPane" oor:op="replace"> + <prop oor:name="ResourceURL"> + <value>private:resource/pane/Presenter/Pane2</value> + </prop> + <prop oor:name="StyleName"> + <value>DefaultPaneStyle</value> + </prop> + </node> + <node oor:name="NextSlidePreviewView" oor:op="replace"> + <prop oor:name="ResourceURL"> + <value>private:resource/view/Presenter/NextSlidePreview</value> + </prop> + <prop oor:name="StyleName"> + <value>DefaultViewStyle</value> + </prop> + </node> + <node oor:name="ToolBarPane" oor:op="replace"> + <prop oor:name="ResourceURL"> + <value>private:resource/pane/Presenter/Pane4</value> + </prop> + <prop oor:name="StyleName"> + <value>ToolbarPaneStyle</value> + </prop> + </node> + <node oor:name="ToolBarView" oor:op="replace"> + <prop oor:name="ResourceURL"> + <value>private:resource/view/Presenter/ToolBar</value> + </prop> + <prop oor:name="StyleName"> + <value>DefaultViewStyle</value> + </prop> + </node> + <node oor:name="NotesPane" oor:op="replace"> + <prop oor:name="ResourceURL"> + <value>private:resource/pane/Presenter/Pane3</value> + </prop> + <prop oor:name="StyleName"> + <value>ActivePaneStyle</value> + </prop> + </node> + <node oor:name="NotesView" oor:op="replace"> + <prop oor:name="ResourceURL"> + <value>private:resource/view/Presenter/Notes</value> + </prop> + <prop oor:name="StyleName"> + <value>NotesViewStyle</value> + </prop> + </node> + <node oor:name="SlideSorter" oor:op="replace"> + <prop oor:name="ResourceURL"> + <value>private:resource/view/Presenter/SlideSorter</value> + </prop> + <prop oor:name="StyleName"> + <value>SlideSorterViewStyle</value> + </prop> + </node> + <node oor:name="OverlayPane" oor:op="replace"> + <prop oor:name="ResourceURL"> + <value>private:resource/pane/Presenter/Overlay</value> + </prop> + <prop oor:name="StyleName"> + <value>ActivePaneStyle</value> + </prop> + </node> + <node oor:name="HelpView" oor:op="replace"> + <prop oor:name="ResourceURL"> + <value>private:resource/view/Presenter/Help</value> + </prop> + <prop oor:name="StyleName"> + <value>HelpViewStyle</value> + </prop> + </node> + <node oor:name="HelpPane" oor:op="replace"> + <prop oor:name="ResourceURL"> + <value>private:resource/pane/Presenter/Pane6</value> + </prop> + <prop oor:name="StyleName"> + <value>ActivePaneStyle</value> + </prop> + </node> + </node> + </node> + </node> + <node oor:name="Views"> + <node oor:name="CurrentSlidePreview" oor:op="replace"> + <prop oor:name="ViewURL"> + <value>private:resource/view/Presenter/CurrentSlidePreview</value> + </prop> + <prop oor:name="Title"> + <value xml:lang="en-US">Current Slide (%CURRENT_SLIDE_NUMBER% of %SLIDE_COUNT%)</value> + </prop> + <prop oor:name="AccessibleTitle"> + <value xml:lang="en-US">Current Slide, %CURRENT_SLIDE_NAME%, %CURRENT_SLIDE_NUMBER% of %SLIDE_COUNT%</value> + </prop> + <prop oor:name="IsOpaque"><value>true</value></prop> + <node oor:name="Strings"> + <node oor:name="ClickToExitPresentationText" oor:op="replace"> + <prop oor:name="String"> + <value xml:lang="en-US">Click to exit presentation...</value> + </prop> + </node> + <node oor:name="ClickToExitPresentationTitle" oor:op="replace"> + <prop oor:name="String"> + <value xml:lang="en-US">Current Slide (end)</value> + </prop> + </node> + </node> + </node> + <node oor:name="NextSlidePreview" oor:op="replace"> + <prop oor:name="ViewURL"> + <value>private:resource/view/Presenter/NextSlidePreview</value> + </prop> + <prop oor:name="Title"> + <value xml:lang="en-US">Next Slide</value> + </prop> + <prop oor:name="IsOpaque"><value>false</value></prop> + </node> + <node oor:name="ToolBar" oor:op="replace"> + <prop oor:name="ViewURL"> + <value>private:resource/view/Presenter/ToolBar</value> + </prop> + <prop oor:name="IsOpaque"><value>false</value></prop> + </node> + <node oor:name="NotesView" oor:op="replace"> + <prop oor:name="ViewURL"> + <value>private:resource/view/Presenter/Notes</value> + </prop> + <prop oor:name="Title"> + <value xml:lang="en-US">Notes</value> + </prop> + <prop oor:name="IsOpaque"><value>false</value></prop> + </node> + <node oor:name="SlideSorter" oor:op="replace"> + <prop oor:name="ViewURL"> + <value>private:resource/view/Presenter/SlideSorter</value> + </prop> + <prop oor:name="IsOpaque"><value>false</value></prop> + <prop oor:name="Title"> + <value xml:lang="en-US"></value> + </prop> + <prop oor:name="AccessibleTitle"> + <value xml:lang="en-US">Slide Overview, %CURRENT_SLIDE_NAME%, %CURRENT_SLIDE_NUMBER% of %SLIDE_COUNT%</value> + </prop> + </node> + <node oor:name="HelpView" oor:op="replace"> + <prop oor:name="ViewURL"> + <value>private:resource/view/Presenter/Help</value> + </prop> + <prop oor:name="Title"> + <value xml:lang="en-US">Help</value> + </prop> + <prop oor:name="IsOpaque"><value>false</value></prop> + </node> + </node> + <node oor:name="Layouts"> + <node oor:name="DefaultLayout" oor:op="replace"> + <prop oor:name="LayoutName"> + <value>DefaultLayout</value> + </prop> + <node oor:name="Layout"> + <node oor:name="CurrentSlidePreview" oor:op="replace"> + <prop oor:name="PaneURL"> + <value>private:resource/pane/Presenter/Pane1</value> + </prop> + <prop oor:name="ViewURL"> + <value>private:resource/view/Presenter/CurrentSlidePreview</value> + </prop> + <prop oor:name="RelativeX"> + <value>0.05</value> + </prop> + <prop oor:name="RelativeY"> + <value>0.05</value> + </prop> + <prop oor:name="RelativeWidth"> + <value>0.50</value> + </prop> + <prop oor:name="RelativeHeight"> + <value>0.50</value> + </prop> + </node> + <node oor:name="NextSlidePreview" oor:op="replace"> + <prop oor:name="PaneURL"> + <value>private:resource/pane/Presenter/Pane2</value> + </prop> + <prop oor:name="ViewURL"> + <value>private:resource/view/Presenter/NextSlidePreview</value> + </prop> + <prop oor:name="RelativeX"> + <value>0.60</value> + </prop> + <prop oor:name="RelativeY"> + <value>0.05</value> + </prop> + <prop oor:name="RelativeWidth"> + <value>0.35</value> + </prop> + <prop oor:name="RelativeHeight"> + <value>0.35</value> + </prop> + </node> + <node oor:name="ToolBar" oor:op="replace"> + <prop oor:name="PaneURL"> + <value>private:resource/pane/Presenter/Pane4</value> + </prop> + <prop oor:name="ViewURL"> + <value>private:resource/view/Presenter/ToolBar</value> + </prop> + <prop oor:name="RelativeX"> + <value>0.60</value> + </prop> + <prop oor:name="RelativeY"> + <value>0.45</value> + </prop> + <prop oor:name="RelativeWidth"> + <value>0.25</value> + </prop> + <prop oor:name="RelativeHeight"> + <value>0.1</value> + </prop> + </node> + <node oor:name="NotesView" oor:op="replace"> + <prop oor:name="PaneURL"> + <value>private:resource/pane/Presenter/Pane3</value> + </prop> + <prop oor:name="ViewURL"> + <value>private:resource/view/Presenter/Notes</value> + </prop> + <prop oor:name="RelativeX"> + <value>0.05</value> + </prop> + <prop oor:name="RelativeY"> + <value>0.60</value> + </prop> + <prop oor:name="RelativeWidth"> + <value>0.9</value> + </prop> + <prop oor:name="RelativeHeight"> + <value>0.35</value> + </prop> + </node> + <node oor:name="SlideSorter" oor:op="replace"> + <prop oor:name="PaneURL"> + <value>private:resource/pane/Presenter/Overlay</value> + </prop> + <prop oor:name="ViewURL"> + <value>private:resource/view/Presenter/SlideSorter</value> + </prop> + <prop oor:name="RelativeX"> + <value>0.05</value> + </prop> + <prop oor:name="RelativeY"> + <value>0.05</value> + </prop> + <prop oor:name="RelativeWidth"> + <value>0.95</value> + </prop> + <prop oor:name="RelativeHeight"> + <value>0.8</value> + </prop> + </node> + <node oor:name="HelpView" oor:op="replace"> + <prop oor:name="PaneURL"> + <value>private:resource/pane/Presenter/Pane6</value> + </prop> + <prop oor:name="ViewURL"> + <value>private:resource/view/Presenter/Help</value> + </prop> + <prop oor:name="RelativeX"> + <value>0.05</value> + </prop> + <prop oor:name="RelativeY"> + <value>0.05</value> + </prop> + <prop oor:name="RelativeWidth"> + <value>0.95</value> + </prop> + <prop oor:name="RelativeHeight"> + <value>0.8</value> + </prop> + </node> + </node> + </node> + </node> + <node oor:name="Accessibility"> + <node oor:name="Console" oor:op="replace"> + <prop oor:name="String"> + <value xml:lang="en-US">Presenter Console</value> + </prop> + </node> + <node oor:name="Preview" oor:op="replace"> + <prop oor:name="String"> + <value xml:lang="en-US">Current Slide Info</value> + </prop> + </node> + <node oor:name="Notes" oor:op="replace"> + <prop oor:name="String"> + <value xml:lang="en-US">Presenter Notes</value> + </prop> + </node> + </node> + </node> +</oor:component-data> diff --git a/sdext/source/presenter/registry/data/org/openoffice/Office/extension/makefile.mk b/sdext/source/presenter/registry/data/org/openoffice/Office/extension/makefile.mk new file mode 100644 index 000000000000..d3efd284ff66 --- /dev/null +++ b/sdext/source/presenter/registry/data/org/openoffice/Office/extension/makefile.mk @@ -0,0 +1,51 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/..$/..$/..$/..$/..$/.. + +PRJNAME=sdext +TARGET=data_ooOfficeext +PACKAGE=org.openoffice.Office.extension +EXTENSIONNAME=PresenterScreen + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +XCSROOT=$(PRJ)$/source$/presenter +ABSXCSROOT=$(PWD)/$(PRJ)$/source$/presenter + +# --- Targets ------------------------------------------------------ + +XCUFILES= \ + PresenterScreen.xcu + +MODULEFILES= + +LOCALIZEDFILES= \ + PresenterScreen.xcu + +.INCLUDE : target.mk diff --git a/sdext/source/presenter/registry/data/org/openoffice/Office/makefile.mk b/sdext/source/presenter/registry/data/org/openoffice/Office/makefile.mk new file mode 100644 index 000000000000..358ffd9f59a5 --- /dev/null +++ b/sdext/source/presenter/registry/data/org/openoffice/Office/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# 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 +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/..$/..$/..$/..$/.. + +PRJNAME=sdext +TARGET=data_ooOffice +PACKAGE=org.openoffice.Office +EXTNAME=presenter + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Targets ------------------------------------------------------ + +XCUFILES= \ + Jobs.xcu \ + ProtocolHandler.xcu + +MODULEFILES= + +LOCALIZEDFILES= + +.INCLUDE : target.mk diff --git a/sdext/source/presenter/registry/schema/org/openoffice/Office/extension/PresenterScreen.xcs b/sdext/source/presenter/registry/schema/org/openoffice/Office/extension/PresenterScreen.xcs new file mode 100644 index 000000000000..deba55ab258b --- /dev/null +++ b/sdext/source/presenter/registry/schema/org/openoffice/Office/extension/PresenterScreen.xcs @@ -0,0 +1,469 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--*********************************************************************** + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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 + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************ --> +<oor:component-schema xml:lang="en-US" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" oor:package="org.openoffice.Office.extension" oor:name="PresenterScreen"> + <info> + <author>AF</author> + <desc>Configuration of the Presenter Screen extension.</desc> + </info> + <import oor:component="org.openoffice.Office.Impress"></import> + <templates> + <group oor:name="BitmapDescriptor"> + <info><desc>Describes one bitmap that can be used as button icon or to paint + a pane border.</desc></info> + <prop oor:name="Name" oor:type="xs:string"> + <info><desc>Name of the bitmap. Used to look-up the bitmap in a container.</desc></info> + </prop> + <prop oor:name="Text" oor:type="xs:string" oor:localized="true"> + <info><desc>Text that is displayed together with the icon.</desc></info> + </prop> + <prop oor:name="NormalFileName" oor:type="xs:string"> + <info><desc>Relative file name to the bitmap for the normal icon.</desc></info> + </prop> + <prop oor:name="MouseOverFileName" oor:type="xs:string"> + <info><desc>Relative file name to the bitmap for the mouse over icon.</desc></info> + </prop> + <prop oor:name="ButtonDownFileName" oor:type="xs:string"> + <info><desc>Relative file name to the bitmap for the button down icon.</desc></info> + </prop> + <prop oor:name="DisabledFileName" oor:type="xs:string"> + <info><desc>Relative file name to the bitmap for the icon in disabled state.</desc></info> + </prop> + <prop oor:name="SelectedFileName" oor:type="xs:string"> + <info><desc>Relative file name to the bitmap for the icon in disabled state.</desc></info> + </prop> + <prop oor:name="MaskFileName" oor:type="xs:string"> + <info><desc>The file name of the mask bitmap. Use red for pixel outside of + the border and blue for inside pixels.</desc></info> + <value></value> + </prop> + <prop oor:name="XOffset" oor:type="xs:int"> + <info><desc>Horizontal offset to move the bitmap just outside the + window border.</desc></info> + <value>0</value> + </prop> + <prop oor:name="YOffset" oor:type="xs:int"> + <info><desc>Vertical offset to move the bitmap just outside the + window border.</desc></info> + <value>0</value> + </prop> + <prop oor:name="XHotSpot" oor:type="xs:int"> + <info><desc>Horizontal position of a hot spot.</desc></info> + </prop> + <prop oor:name="YHotSpot" oor:type="xs:int"> + <info><desc>Vertical position of a hot spot.</desc></info> + </prop> + <prop oor:name="ReplacementColor" oor:type="xs:hexBinary"> + <info><desc>Color that is used as replacement for the bitmap when the later + can for some reason not be used.</desc></info> + </prop> + <prop oor:name="HorizontalTexturingMode" oor:type="xs:string"> + <info><desc>Horizontal texturing mode.</desc></info> + <constraints> + <enumeration oor:value="Once"> + <info><desc>Show texture only once</desc></info> + </enumeration> + <enumeration oor:value="Repeat"> + <info><desc>Repeat the texture</desc></info> + </enumeration> + <enumeration oor:value="Stretch"> + <info><desc>Stretch the texture to cover the paint area</desc></info> + </enumeration> + </constraints> + </prop> + <prop oor:name="VerticalTexturingMode" oor:type="xs:string"> + <info><desc>Vertical texturing mode.</desc></info> + <constraints> + <enumeration oor:value="Once"> + <info><desc>Show texture only once</desc></info> + </enumeration> + <enumeration oor:value="Repeat"> + <info><desc>Repeat the texture</desc></info> + </enumeration> + <enumeration oor:value="Stretch"> + <info><desc>Stretch the texture to cover the paint area</desc></info> + </enumeration> + </constraints> + <value>Once</value> + </prop> + </group> + <group oor:name="ThemeBorderSize"> + <info><desc>Four values describing the sizes of a border around a + rectangular area.</desc></info> + <prop oor:name="Left" oor:type="xs:int"> + <info><desc>Left border size.</desc></info> + </prop> + <prop oor:name="Top" oor:type="xs:int"> + <info><desc>Top border size.</desc></info> + </prop> + <prop oor:name="Right" oor:type="xs:int"> + <info><desc>Right border size.</desc></info> + </prop> + <prop oor:name="Bottom" oor:type="xs:int"> + <info><desc>Bottom border size.</desc></info> + </prop> + </group> + <group oor:name="Font"> + <info><desc>Font description.</desc></info> + <prop oor:name="FamilyName" oor:type="xs:string"> + <info><desc>The name of the font family.</desc></info> + </prop> + <prop oor:name="Size" oor:type="xs:int"> + <info><desc>Font size.</desc></info> + </prop> + <prop oor:name="Style" oor:type="xs:string"> + <info><desc>Something like "Bold" or "Italic" or "Bold Italic".</desc></info> + </prop> + <prop oor:name="Color" oor:type="xs:hexBinary"> + <info><desc>Font color.</desc></info> + </prop> + <prop oor:name="Anchor" oor:type="xs:string"> + <info><desc>Orientation of text. Can be left, right, or centered.</desc></info> + <constraints> + <enumeration oor:value="Left"> + <info><desc>Flush left</desc></info> + </enumeration> + <enumeration oor:value="Right"> + <info><desc>Flush right</desc></info> + </enumeration> + <enumeration oor:value="Center"> + <info><desc>Centered</desc></info> + </enumeration> + </constraints> + </prop> + <prop oor:name="XOffset" oor:type="xs:int"> + <info><desc>Horizontal offset in relation to the anchor point.</desc></info> + </prop> + <prop oor:name="YOffset" oor:type="xs:int"> + <info><desc>Vertical offset in relation to the anchor point.</desc></info> + </prop> + </group> + <group oor:name="ToolBarDescription"> + <node-ref oor:name="Font" oor:node-type="Font"> + <info><desc>Font used for displaying the text.</desc></info> + </node-ref> + <node-ref oor:name="Icon" oor:node-type="BitmapDescriptor"> + <info><desc>The icon to display.</desc></info> + </node-ref> + <prop oor:name="Text" oor:type="xs:string" oor:localized="true"> + <info><desc>The text to display.</desc></info> + </prop> + <prop oor:name="Action" oor:type="xs:string"> + <info><desc>Action to execute when a button is triggered.</desc></info> + </prop> + </group> + <group oor:name="ToolBarEntry"> + <prop oor:name="Name" oor:type="xs:string"> + <info><desc>Name of the entry. May be used to have mode dependant entries.</desc></info> + </prop> + <prop oor:name="Type" oor:type="xs:string"> + <info><desc>Type of the entry. Examples are "Label" and "Button".</desc></info> + </prop> + <node-ref oor:name="Normal" oor:node-type="ToolBarDescription"> + <info><desc>Description of a tool bar entry in normal mode (not selected, not mouse over)</desc></info> + </node-ref> + <node-ref oor:name="MouseOver" oor:node-type="ToolBarDescription"> + <info><desc>Description of a tool bar entry when the mouse is over it.</desc></info> + </node-ref> + <node-ref oor:name="Selected" oor:node-type="ToolBarDescription"> + <info><desc>Description of a tool bar entry when it is selected.</desc></info> + </node-ref> + <node-ref oor:name="Disabled" oor:node-type="ToolBarDescription"> + <info><desc>Description of a tool bar entry when it is disabled.</desc></info> + </node-ref> + </group> + <group oor:name="ToolBar"> + <info><desc>Definition of one tool bar.</desc></info> + <set oor:name="Entries" oor:node-type="ToolBarEntry"> + <info><desc>Entries of the tool bars.</desc></info> + </set> + </group> + <group oor:name="Button"> + <prop oor:name="Name" oor:type="xs:string"> + <info><desc>Name of the button that is used to look up the button.</desc></info> + </prop> + <node-ref oor:name="Font" oor:node-type="Font"> + <info><desc>Font used for displaying the text.</desc></info> + </node-ref> + <node-ref oor:name="Icon" oor:node-type="BitmapDescriptor"> + <info><desc>The icon to display.</desc></info> + </node-ref> + <prop oor:name="Text" oor:type="xs:string" oor:localized="true"> + <info><desc>The text to display.</desc></info> + </prop> + <prop oor:name="Action" oor:type="xs:string"> + <info><desc>Action to execute when a button is triggered.</desc></info> + </prop> + </group> + <group oor:name="HelpEntry"> + <prop oor:name="Left" oor:type="xs:string" oor:localized="true"> + <info><desc>Typically a list of keyboard key names.</desc></info> + </prop> + <prop oor:name="Right" oor:type="xs:string" oor:localized="true"> + <info><desc>Typically a description of the action triggered by pressing the keys on the left.</desc></info> + </prop> + </group> + <group oor:name="PaneStyle"> + <info><desc>Visual properties of a pane style: + the border of a pane and its title font.</desc></info> + <prop oor:name="StyleName" oor:type="xs:string"> + <info><desc>Name of the style. Used for referencing the style. + Has to be unique among pane styles and view styles + in one theme.</desc></info> + </prop> + <prop oor:name="ParentStyle" oor:type="xs:string"> + <info><desc>Name of the parent style. Values not supplied in this style + are taken from the parent style. Empty string or missing + mean no parent.</desc></info> + <value></value> + </prop> + <node-ref oor:name="TitleFont" oor:node-type="Font"> + <info><desc>Font used for displaying the pane title.</desc></info> + </node-ref> + <node-ref oor:name="InnerBorderSize" oor:node-type="ThemeBorderSize"> + <info><desc>Size of the inner part of the border.</desc></info> + </node-ref> + <node-ref oor:name="OuterBorderSize" oor:node-type="ThemeBorderSize"> + <info><desc>Size of the outer part of the border.</desc></info> + </node-ref> + <set oor:name="BorderBitmapList" oor:node-type="BitmapDescriptor"> + <info><desc>Bitmaps that are used to paint the borders of + a pane.</desc></info> + </set> + </group> + <group oor:name="ViewStyle"> + <info><desc>Visual properties of a view style: + font and backround color.</desc></info> + <prop oor:name="StyleName" oor:type="xs:string"> + <info><desc>Name of the style. Used for referencing the style. + Has to be unique among pane styles and view styles + in one theme.</desc></info> + </prop> + <prop oor:name="ParentStyle" oor:type="xs:string"> + <info><desc>Name of the parent style. Values not supplied in this style + are taken from the parent style. Empty string or missing + mean no parent.</desc></info> + <value></value> + </prop> + <node-ref oor:name="Font" oor:node-type="Font"> + <info><desc>Font used for text display inside a view.</desc></info> + </node-ref> + <node-ref oor:name="Background" oor:node-type="BitmapDescriptor"> + <info><desc>Color (or bitmap) that is used to paint the + background of a view.</desc></info> + </node-ref> + </group> + <group oor:name="Style_Association"> + <info><desc>Association of a drawing framework resource to a + style of the presenter theme.</desc></info> + <prop oor:name="ResourceURL" oor:type="xs:string"> + <info><desc>URL of a drawing framework resource.</desc></info> + </prop> + <prop oor:name="StyleName" oor:type="xs:string"> + <info><desc>Name of a pane style or a view style.</desc></info> + </prop> + </group> + <group oor:name="PresenterString"> + <info><desc></desc></info> + <prop oor:name="String" oor:type="xs:string" oor:localized="true"> + </prop> + </group> + <group oor:name="ViewDescription"> + <info><desc>Association of a drawing framework resource to a + style of the presenter theme.</desc></info> + <prop oor:name="ViewURL" oor:type="xs:string"> + <info><desc>URL of a drawing framework view.</desc></info> + </prop> + <prop oor:name="StyleName" oor:type="xs:string"> + <info><desc>Name of a view style.</desc></info> + </prop> + <prop oor:name="Title" oor:type="xs:string" oor:localized="true"> + <info><desc>Title displayed for the component. An empty or missing + title means that no title is displayed.</desc></info> + <value></value> + </prop> + <prop oor:name="AccessibleTitle" oor:type="xs:string" oor:localized="true"> + <info><desc>Title displayed for the component when accessibility support is active. + An empty or missing title means that no title is displayed.</desc></info> + <value></value> + </prop> + <prop oor:name="IsOpaque" oor:type="xs:boolean"> + <info><desc>When the value is false then the background is painted before the + view is painted.</desc></info> + <value>false</value> + </prop> + <set oor:name="Strings" oor:node-type="PresenterString"> + <info><desc>List of localizable strings used by the view.</desc></info> + </set> + </group> + <group oor:name="PresenterTheme"> + <info><desc>Visual properties of the presenter view. The values in a theme + are hints and can be ignored.</desc></info> + <prop oor:name="ThemeName" oor:type="xs:string"> + <info><desc>Name of the theme. Used for referencing the theme. + Has to be unique among all themes. The name of the + default theme is 'DefaultTheme'</desc></info> + </prop> + <prop oor:name="ParentTheme" oor:type="xs:string"> + <info><desc>Name of the parent theme. Values not supplied in this theme + are taken from the parent theme. Empty string or missing + mean default theme.</desc></info> + <value></value> + </prop> + <prop oor:name="BitmapSourceExtension" oor:type="xs:string"> + <info><desc>Name of the extension which contains the bitmaps + referenced by this theme.</desc></info> + <value></value> + </prop> + <node-ref oor:name="Background" oor:node-type="BitmapDescriptor"> + <info><desc>Color or bitmap that is used to paint the + background.</desc></info> + </node-ref> + <set oor:name="PaneStyles" oor:node-type="PaneStyle"> + <info><desc>List of pane styles.</desc></info> + </set> + <set oor:name="ViewStyles" oor:node-type="ViewStyle"> + <info><desc>List of view styles.</desc></info> + </set> + <set oor:name="StyleAssociations" oor:node-type="Style_Association"> + <info><desc>List of style associations.</desc></info> + </set> + <set oor:name="Bitmaps" oor:node-type="BitmapDescriptor"> + <info><desc>List of additional bitmaps for example for buttons.</desc></info> + </set> + <set oor:name="Fonts" oor:node-type="Font"> + <info><desc>List of additional fonts.</desc></info> + </set> + </group> + <group oor:name="PresenterComponentLayout"> + <info><desc>Layout of a component of the presenter screen.</desc></info> + <prop oor:name="PaneURL" oor:type="xs:string"> + <info><desc>URL of a pane resource.</desc></info> + </prop> + <prop oor:name="ViewURL" oor:type="xs:string"> + <info><desc>URL of a view resource that is to be displayed in + the pane.</desc></info> + </prop> + <prop oor:name="RelativeX" oor:type="xs:double"> + <info><desc>Relative x position in the range of [0,1].</desc></info> + </prop> + <prop oor:name="RelativeY" oor:type="xs:double"> + <info><desc>Relative y position in the range of [0,1].</desc></info> + </prop> + <prop oor:name="RelativeWidth" oor:type="xs:double"> + <info><desc>Relative width in the range of [0,1].</desc></info> + </prop> + <prop oor:name="RelativeHeight" oor:type="xs:double"> + <info><desc>Relative height in the range of [0,1].</desc></info> + </prop> + </group> + <group oor:name="PresenterLayout"> + <info><desc>Layout of all components of the presenter screen.</desc></info> + <prop oor:name="LayoutName" oor:type="xs:string"> + <info><desc>Name of the layout. Used for referencing the layout. + Has to be unique among all presenter layouts.</desc></info> + </prop> + <prop oor:name="ParentLayout" oor:type="xs:string"> + <info><desc>Name of the parent layout. Values not supplied in this layout + are taken from the parent layout. Missing or empty string + mean no parent layout.</desc></info> + <value></value> + </prop> + <set oor:name="Layout" oor:node-type="PresenterComponentLayout"> + <info><desc>List of component layouts.</desc></info> + </set> + </group> + </templates> + <component> + <group oor:name="PresenterScreenSettings"> + <info><desc>Settings regarding controls that are only used by the Presenter + Screen.</desc></info> + <set oor:name="ToolBars" oor:node-type="ToolBar"> + <info><desc>Set of tool bars.</desc></info> + </set> + <set oor:name="Buttons" oor:node-type="Button"> + <info><desc>Set of buttons.</desc></info> + </set> + <group oor:name="ScrollBar"> + <info><desc>Settings of scroll bars.</desc></info> + <set oor:name="Bitmaps" oor:node-type="BitmapDescriptor"> + <info><desc>Bitmaps of icons used for displaying the scroll bar.</desc></info> + </set> + </group> + <group oor:name="SlideSorter"> + <info><desc>Settings of the slide sorter of the presenter screen.</desc></info> + <node-ref oor:name="BorderSize" oor:node-type="ThemeBorderSize"> + <info><desc>Size of the border around the current slide.</desc></info> + </node-ref> + <set oor:name="CurrentSlideBorderBitmaps" oor:node-type="BitmapDescriptor"> + <info><desc>Bitmaps that are used to paint the border around the current + slide.</desc></info> + </set> + </group> + <group oor:name="HelpView"> + <info><desc>Settings of help view.</desc></info> + <set oor:name="HelpStrings" oor:node-type="HelpEntry"> + <info><desc>List of entries displayed in the help view.</desc></info> + </set> + </group> + </group> + <group oor:name="Presenter"> + <info><desc>General properties of the presenter view.</desc></info> + <prop oor:name="StartAlways" oor:type="xs:boolean"> + <info><desc>When true then presenter screen is displayed on single screen systems + or when fullscreen presentation spans all screens.</desc></info> + <value>false</value> + </prop> + <set oor:name="Themes" oor:node-type="PresenterTheme"> + <info><desc>List of available themes.</desc></info> + </set> + <prop oor:name="CurrentTheme" oor:type="xs:string"> + <info><desc>Name of the current theme. An empty name or the string "DefaultTheme" + specify the default theme.</desc></info> + <value>DefaultTheme</value> + </prop> + <set oor:name="Views" oor:node-type="ViewDescription"> + <info><desc>Description of the views.</desc></info> + </set> + <set oor:name="Layouts" oor:node-type="PresenterLayout"> + <info><desc>List of visible presenter components.</desc></info> + </set> + <prop oor:name="CurrentLayout" oor:type="xs:string"> + <info><desc>Name of the current layout. An empty name or the + string "DefaultLayout" specify the default layout.</desc></info> + <value>DefaultLayout</value> + </prop> + <set oor:name="Accessibility" oor:node-type="PresenterString"> + <info><desc>Strings that are used make the presenter console accessible.</desc></info> + </set> + <prop oor:name="InitialViewMode" oor:type="xs:int"> + <info><desc>The view mode on start up of the extension. Valid values are 0 for the Preview-only mode, 1 for the notes view, 2 for the slide overview.</desc></info> + <value>0</value> + </prop> + </group> + </component> +</oor:component-schema> |