diff options
author | Mathias Bauer <mba@openoffice.org> | 2009-09-25 21:47:16 +0200 |
---|---|---|
committer | Mathias Bauer <mba@openoffice.org> | 2009-09-25 21:47:16 +0200 |
commit | d381760a0bdbc403426db365fcdd79c48805a1f9 (patch) | |
tree | 969d1f2189bb9c5d73ea358016389539c1ef23c5 /sdext | |
parent | e7e8d94bb6d31abc98bbeb4026481aa052f29278 (diff) | |
parent | bbc5105d503634578685f235497b39965f528d1a (diff) |
merge commit
Diffstat (limited to 'sdext')
37 files changed, 5217 insertions, 560 deletions
diff --git a/sdext/source/minimizer/makefile.mk b/sdext/source/minimizer/makefile.mk index d3e13a0ca622..89b1e16c955f 100644 --- a/sdext/source/minimizer/makefile.mk +++ b/sdext/source/minimizer/makefile.mk @@ -37,6 +37,7 @@ ENABLE_EXCEPTIONS=TRUE # --- Settings ---------------------------------- .INCLUDE : settings.mk +.IF "$(L10N_framework)"=="" .INCLUDE : $(PRJ)$/source$/minimizer$/minimizer.pmk .INCLUDE : $(PRJ)$/util$/makefile.pmk @@ -122,8 +123,10 @@ EXTENSION_PACKDEPS=$(COMPONENT_BITMAPS) $(COMPONENT_HELP) .INCLUDE : extension_pre.mk +.ENDIF # L10N_framework .INCLUDE : target.mk +.IF "$(L10N_framework)"=="" .INCLUDE : extension_post.mk $(COMPONENT_BITMAPS) : $(SOLARSRC)$/$(RSCDEFIMG)$/minimizer$/$$(@:f) @@ -133,3 +136,5 @@ $(COMPONENT_BITMAPS) : $(SOLARSRC)$/$(RSCDEFIMG)$/minimizer$/$$(@:f) $(COMPONENT_HELP) : help$/$$(@:f) @@-$(MKDIRHIER) $(@:d) $(COPY) $< $@ + +.ENDIF # L10N_framework diff --git a/sdext/source/pdfimport/makefile.mk b/sdext/source/pdfimport/makefile.mk index d6cd4783454f..f8c6f71f0d3d 100644 --- a/sdext/source/pdfimport/makefile.mk +++ b/sdext/source/pdfimport/makefile.mk @@ -39,6 +39,9 @@ ENABLE_EXCEPTIONS=TRUE MKDEPENDSOLVER:= .INCLUDE: settings.mk + +.IF "$(L10N_framework)"=="" + .INCLUDE: pdfisettings.pmk INCPRE=-I$(PRJ)$/source$/pdfimport$/inc @@ -132,7 +135,9 @@ COMPONENT_IMAGES=\ EXTENSION_PACKDEPS=$(CONVERTER_FILE) $(COMPONENT_DIALOGS) $(COMPONENT_HELP) $(COMPONENT_IMAGES) makefile.mk .INCLUDE : extension_pre.mk +.ENDIF # L10N_framework .INCLUDE : target.mk +.IF "$(L10N_framework)"=="" .INCLUDE : extension_post.mk $(CONVERTER_FILE) : $(BIN)$/$$(@:f) @@ -150,3 +155,5 @@ $(COMPONENT_HELP) : help$/$$(@:f) $(COMPONENT_IMAGES) : images$/$$(@:f) @@-$(MKDIRHIER) $(@:d) $(COPY) $< $@ +.ENDIF # L10N_framework + diff --git a/sdext/source/pdfimport/pdfparse/makefile.mk b/sdext/source/pdfimport/pdfparse/makefile.mk index 7249e52205eb..9cbb5f1b92fd 100644 --- a/sdext/source/pdfimport/pdfparse/makefile.mk +++ b/sdext/source/pdfimport/pdfparse/makefile.mk @@ -44,6 +44,8 @@ EXTERNAL_WARNINGS_NOT_ERRORS=TRUE CFLAGS+=-DSYSTEM_ZLIB .ENDIF +ENVCFLAGS += -DBOOST_SPIRIT_USE_OLD_NAMESPACE + # --- Files -------------------------------------------------------- SLOFILES=\ diff --git a/sdext/source/pdfimport/pdfparse/pdfparse.cxx b/sdext/source/pdfimport/pdfparse/pdfparse.cxx index baaef9877270..c9b3b1522cc5 100644 --- a/sdext/source/pdfimport/pdfparse/pdfparse.cxx +++ b/sdext/source/pdfimport/pdfparse/pdfparse.cxx @@ -42,14 +42,10 @@ // workaround windows compiler: do not include multi_pass.hpp //#include <boost/spirit.hpp> -#include <boost/spirit/core.hpp> -#include <boost/spirit/utility.hpp> -#include <boost/spirit/error_handling.hpp> -#include <boost/spirit/iterator/file_iterator.hpp> -#if SPIRIT_VERSION >= 0x1800 -#define USE_ASSIGN_ACTOR -#include <boost/spirit/actor/assign_actor.hpp> -#endif +#include <boost/spirit/include/classic_core.hpp> +#include <boost/spirit/include/classic_utility.hpp> +#include <boost/spirit/include/classic_error_handling.hpp> +#include <boost/spirit/include/classic_file_iterator.hpp> #include <boost/bind.hpp> #include <string> diff --git a/sdext/source/presenter/PresenterAccessibility.cxx b/sdext/source/presenter/PresenterAccessibility.cxx new file mode 100644 index 000000000000..4480c05b4cbf --- /dev/null +++ b/sdext/source/presenter/PresenterAccessibility.cxx @@ -0,0 +1,2492 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: PresenterPane.hxx,v $ + * + * $Revision: 1.4 $ + * + * 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 <vcl/svapp.hxx> +#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::WeakComponentImplHelper5 < + 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); + + + //----- 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); + + using PresenterAccessibleObjectInterfaceBase::addEventListener; + using PresenterAccessibleObjectInterfaceBase::removeEventListener; + + //----- 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::createFromAscii("/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::createFromAscii("/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(A2S(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::createFromAscii("/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 diff --git a/sdext/source/presenter/PresenterAccessibility.hxx b/sdext/source/presenter/PresenterAccessibility.hxx new file mode 100644 index 000000000000..28c86c749eed --- /dev/null +++ b/sdext/source/presenter/PresenterAccessibility.hxx @@ -0,0 +1,160 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: PresenterPane.hxx,v $ + * + * $Revision: 1.4 $ + * + * 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 diff --git a/sdext/source/presenter/PresenterButton.cxx b/sdext/source/presenter/PresenterButton.cxx index e9683c472405..215cd48598db 100644 --- a/sdext/source/presenter/PresenterButton.cxx +++ b/sdext/source/presenter/PresenterButton.cxx @@ -481,8 +481,6 @@ void PresenterButton::RenderButton ( GetBitmap(rpCenter, eMode), GetBitmap(rpRight, eMode)); - sal_Int32 nBottomOffset ( - ::std::max(rpLeft->mnYOffset, ::std::max(rpCenter->mnYOffset, rpRight->mnYOffset))); if (rpFont.get()==NULL || ! rpFont->mxFont.is()) return; @@ -495,7 +493,7 @@ void PresenterButton::RenderButton ( 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 - gnVerticalBorder - nBottomOffset; + aRenderState.AffineTransform.m12 = (rSize.Height - aTextBBox.Y2 + aTextBBox.Y1)/2 - aTextBBox.Y1; rxCanvas->drawText( aContext, diff --git a/sdext/source/presenter/PresenterCanvasHelper.cxx b/sdext/source/presenter/PresenterCanvasHelper.cxx index 450e29b1b3c9..14103d088f4a 100644 --- a/sdext/source/presenter/PresenterCanvasHelper.cxx +++ b/sdext/source/presenter/PresenterCanvasHelper.cxx @@ -298,23 +298,35 @@ void PresenterCanvasHelper::SetDeviceColor( -css::geometry::RealSize2D PresenterCanvasHelper::GetTextSize ( +css::geometry::RealRectangle2D PresenterCanvasHelper::GetTextBoundingBox ( const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, - const ::rtl::OUString& rsText) + 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, rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0)); - const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds()); - return css::geometry::RealSize2D(aTextBBox.X2 - aTextBBox.X1, aTextBBox.Y2 - aTextBBox.Y1); + rxFont->createTextLayout(aContext, nTextDirection, 0)); + return xLayout->queryTextBounds(); } else { - return geometry::RealSize2D(0,0); + 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 diff --git a/sdext/source/presenter/PresenterCanvasHelper.hxx b/sdext/source/presenter/PresenterCanvasHelper.hxx index 90d4dec2deec..f254b5c2d6a1 100644 --- a/sdext/source/presenter/PresenterCanvasHelper.hxx +++ b/sdext/source/presenter/PresenterCanvasHelper.hxx @@ -35,6 +35,7 @@ #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> @@ -76,9 +77,15 @@ public: 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 ::rtl::OUString& rsText, + const sal_Int8 = css::rendering::TextDirection::WEAK_LEFT_TO_RIGHT); private: const css::rendering::ViewState maDefaultViewState; diff --git a/sdext/source/presenter/PresenterController.cxx b/sdext/source/presenter/PresenterController.cxx index bcf88fddfa95..58f7053cc11c 100644 --- a/sdext/source/presenter/PresenterController.cxx +++ b/sdext/source/presenter/PresenterController.cxx @@ -34,29 +34,33 @@ #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 "PresenterPaneFactory.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/ResourceId.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> @@ -78,6 +82,7 @@ using ::rtl::OUStringBuffer; namespace { const sal_Int32 ResourceActivationEventType = 0; const sal_Int32 ResourceDeactivationEventType = 1; + const sal_Int32 ConfigurationUpdateEndEventType = 2; } @@ -128,7 +133,9 @@ PresenterController::PresenterController ( mxPresenterHelper(), mpPaintManager(), mnPendingSlideNumber(-1), - mxUrlTransformer() + mxUrlTransformer(), + mpAccessibleObject(), + mbIsAccessibilityActive(false) { OSL_ASSERT(mxController.is()); @@ -153,6 +160,10 @@ PresenterController::PresenterController ( this, A2S("ResourceDeactivation"), Any(ResourceDeactivationEventType)); + mxConfigurationController->addConfigurationChangeListener( + this, + A2S("ConfigurationUpdateEnd"), + Any(ConfigurationUpdateEndEventType)); } // Listen for the frame being activated. @@ -286,6 +297,16 @@ 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); + } } @@ -349,7 +370,8 @@ void PresenterController::UpdatePaneTitles (void) return; // Get placeholders and their values. - const OUString sCurrentSlidePlaceholder (A2S("CURRENT_SLIDE_NUMBER")); + 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. @@ -359,7 +381,31 @@ void PresenterController::UpdatePaneTitles (void) sSlideCount = OUString::valueOf(xIndexAccess->getCount()); // Get string for current slide index. - OUString sCurrentSlide (OUString::valueOf(mnCurrentSlideIndex + 1)); + 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; @@ -367,7 +413,9 @@ void PresenterController::UpdatePaneTitles (void) { OSL_ASSERT((*iPane).get() != NULL); - OUString sTemplate ((*iPane)->msTitleTemplate); + OUString sTemplate (IsAccessibilityActive() + ? (*iPane)->msAccessibleTitleTemplate + : (*iPane)->msTitleTemplate); if (sTemplate.getLength() <= 0) continue; @@ -397,8 +445,10 @@ void PresenterController::UpdatePaneTitles (void) nIndex = nEndIndex+1; // Replace the placeholder with its current value. - if (sPlaceholder == sCurrentSlidePlaceholder) - sResult.append(sCurrentSlide); + if (sPlaceholder == sCurrentSlideNumberPlaceholder) + sResult.append(sCurrentSlideNumber); + else if (sPlaceholder == sCurrentSlideNamePlaceholder) + sResult.append(sCurrentSlideName); else if (sPlaceholder == sSlideCountPlaceholder) sResult.append(sSlideCount); } @@ -660,7 +710,7 @@ Reference<drawing::framework::XConfigurationController> -css::uno::Reference<css::drawing::XDrawPage> PresenterController::GetCurrentSlide (void) const +Reference<drawing::XDrawPage> PresenterController::GetCurrentSlide (void) const { return mxCurrentSlide; } @@ -668,6 +718,34 @@ css::uno::Reference<css::drawing::XDrawPage> PresenterController::GetCurrentSlid +::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()) @@ -766,7 +844,6 @@ void SAL_CALL PresenterController::notifyConfigurationChange ( { PresenterPaneContainer::SharedPaneDescriptor pDescriptor ( mpPaneContainer->FindPaneId(xPane->getResourceId())); - mpWindowManager->NotifyPaneCreation(pDescriptor); // When there is a call out anchor location set then tell the // window about it. @@ -811,6 +888,14 @@ void SAL_CALL PresenterController::notifyConfigurationChange ( } } break; + + case ConfigurationUpdateEndEventType: + if (IsAccessibilityActive()) + { + mpAccessibleObject->UpdateAccessibilityHierarchy(); + UpdateCurrentSlide(0); + } + break; } } @@ -907,8 +992,8 @@ void SAL_CALL PresenterController::keyReleased (const awt::KeyEvent& rEvent) } break; - case awt::Key::SPACE: case awt::Key::RIGHT: + case awt::Key::SPACE: case awt::Key::DOWN: case awt::Key::N: if (mxSlideShowController.is()) @@ -917,8 +1002,8 @@ void SAL_CALL PresenterController::keyReleased (const awt::KeyEvent& rEvent) } break; - case awt::Key::PAGEUP: case awt::Key::LEFT: + case awt::Key::PAGEUP: case awt::Key::UP: case awt::Key::P: case awt::Key::BACKSPACE: @@ -995,7 +1080,11 @@ void SAL_CALL PresenterController::keyReleased (const awt::KeyEvent& rEvent) case awt::Key::F1: // Toggle the help view. if (mpWindowManager.get() != NULL) - mpWindowManager->SetHelpViewState( ! mpWindowManager->IsHelpViewActive()); + if (mpWindowManager->GetViewMode() != PresenterWindowManager::VM_Help) + mpWindowManager->SetViewMode(PresenterWindowManager::VM_Help); + else + mpWindowManager->SetHelpViewState(false); + break; default: @@ -1038,18 +1127,13 @@ void PresenterController::HandleNumericKeyPress ( switch(nKey) { case 1: - mpWindowManager->SetSlideSorterState(false); - mpWindowManager->SetHelpViewState(false); - mpWindowManager->SetLayoutMode(PresenterWindowManager::Standard); + mpWindowManager->SetViewMode(PresenterWindowManager::VM_Standard); break; case 2: - mpWindowManager->SetSlideSorterState(false); - mpWindowManager->SetHelpViewState(false); - mpWindowManager->SetLayoutMode(PresenterWindowManager::Notes); + mpWindowManager->SetViewMode(PresenterWindowManager::VM_Notes); break; case 3: - mpWindowManager->SetHelpViewState(false); - mpWindowManager->SetSlideSorterState(true); + mpWindowManager->SetViewMode(PresenterWindowManager::VM_SlideOverview); break; default: // Ignore unsupported key. @@ -1152,6 +1236,11 @@ 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 @@ -1171,6 +1260,9 @@ void PresenterController::InitializeMainPane (const Reference<XPane>& rxPane) 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)); @@ -1178,6 +1270,8 @@ void PresenterController::InitializeMainPane (const Reference<XPane>& rxPane) if (mxSlideShowController.is()) mxSlideShowController->activate(); + + UpdateCurrentSlide(0); } diff --git a/sdext/source/presenter/PresenterController.hxx b/sdext/source/presenter/PresenterController.hxx index 70e3e6bf748f..114e28157443 100644 --- a/sdext/source/presenter/PresenterController.hxx +++ b/sdext/source/presenter/PresenterController.hxx @@ -32,6 +32,8 @@ #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> @@ -135,6 +137,9 @@ public: 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); @@ -234,6 +239,8 @@ private: ::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); diff --git a/sdext/source/presenter/PresenterHelpView.cxx b/sdext/source/presenter/PresenterHelpView.cxx index 9b1137c09954..9b545a0f42bd 100644 --- a/sdext/source/presenter/PresenterHelpView.cxx +++ b/sdext/source/presenter/PresenterHelpView.cxx @@ -190,9 +190,7 @@ PresenterHelpView::PresenterHelpView ( mxCanvas, A2S("HelpViewCloser")); - mnMaximalWidth = (mxWindow->getPosSize().Width - 4*gnHorizontalGap) / 2; ReadHelpStrings(); - CheckFontSize(); Resize(); } catch (RuntimeException&) @@ -434,6 +432,10 @@ void PresenterHelpView::CheckFontSize (void) 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 @@ -448,15 +450,25 @@ void PresenterHelpView::CheckFontSize (void) (*iBlock)->maLeft.GetHeight(), (*iBlock)->maRight.GetHeight()); - if (nY <= aWindowBox.Height-gnVerticalBorder) - break; + 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 (::std::min(0.95,double(aWindowBox.Height-gnVerticalBorder) / nY)); + 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); @@ -465,6 +477,23 @@ void PresenterHelpView::CheckFontSize (void) 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); + } + } } @@ -517,6 +546,7 @@ 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 @@ -525,6 +555,8 @@ void PresenterHelpView::Resize (void) mpCloseButton->SetCenter(geometry::RealPoint2D( aWindowBox.Width/2, aWindowBox.Height - mpCloseButton->GetSize().Height/2)); + + CheckFontSize(); } } @@ -753,7 +785,9 @@ void LineDescriptorList::FormatText ( } } if ( ! aLineDescriptor.IsEmpty()) + { mpLineDescriptors->push_back(aLineDescriptor); + } } diff --git a/sdext/source/presenter/PresenterNotesView.cxx b/sdext/source/presenter/PresenterNotesView.cxx index fce82f93faee..4a90b76247a1 100644 --- a/sdext/source/presenter/PresenterNotesView.cxx +++ b/sdext/source/presenter/PresenterNotesView.cxx @@ -38,7 +38,10 @@ #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> @@ -71,93 +74,6 @@ static const double gnLineScrollFactor (1.2); namespace sdext { namespace presenter { -//===== PresenterNotesView::BitmapContainer =================================== - -namespace { - class NotesBitmapDescriptor - { - public: - NotesBitmapDescriptor (const sal_Int32 nTop, const sal_Int32 nBottom, - const Reference<rendering::XBitmap> xBitmap) - : Top(nTop), Bottom(nBottom), Bitmap(xBitmap) - { } - sal_Int32 Top; - sal_Int32 Bottom; - Reference<rendering::XBitmap> Bitmap; - }; - typedef ::boost::shared_ptr<NotesBitmapDescriptor> SharedNotesBitmapDescriptor; -} -typedef ::std::vector<SharedNotesBitmapDescriptor> BitmapDescriptorSet; - - -/** Container of bitmaps that show parts of the notes text. If the bitmaps - use more than a specified amount of memory then some bitmaps that are - currently not on the screen are discarded. -*/ -class PresenterNotesView::BitmapContainer - : public BitmapDescriptorSet -{ -public: - BitmapContainer (const ::boost::shared_ptr<BitmapFactory>& rpFactory); - - /** Call this when for instance the font size has changed and all - bitmaps have to be created anew or the slide has changed. - */ - void Clear (void); - void Prune (const sal_Int32 nTop, const sal_Int32 nBottom); - sal_Int32 GetMemorySize (const Reference<rendering::XBitmap>& rxBitmap) const; - sal_Int32 GetMemorySize (void) const; - const_iterator GetBegin (const double nTop, const double nBottom); - const_iterator GetEnd (const double nTop, const double nBottom); - -private: - ::boost::shared_ptr<BitmapFactory> mpFactory; - sal_Int32 mnMaximalCacheSize; - const sal_Int32 mnPartHeight; - sal_Int32 mnTotalHeight; - - sal_Int32 GetTopIndex (const double nValue) const; - sal_Int32 GetBottomIndex (const double nValue) const; - void ProvideBitmaps ( - const sal_Int32 nTopIndex, - const sal_Int32 nBottomIndex); -}; - - - - -//===== PresenterNotesView::BitmapFactory ===================================== - -class PresenterNotesView::BitmapFactory -{ -public: - BitmapFactory ( - const Reference<XComponentContext>& rxComponentContext, - const PresenterTheme::SharedFontDescriptor& rpFont, - const Reference<rendering::XCanvas>& rxCanvas, - const SharedBitmapDescriptor& rpBackground); - ~BitmapFactory (void); - void SetText (const OUString& rsText); - void SetWidth (const sal_Int32 nWidth); - void SetFontHeight (const sal_Int32 nHeight); - sal_Int32 GetHeightForWidth (const sal_Int32 nWidth); - sal_Int32 GetTotalHeight (void); - Reference<rendering::XBitmap> CreateBitmap (const sal_Int32 nTop, const sal_Int32 nBottom); - -private: - Reference<rendering::XCanvas> mxCanvas; - OUString msText; - PresenterTheme::SharedFontDescriptor mpFont; - css::awt::FontDescriptor maFontDescriptor; - sal_Int32 mnWidth; - sal_Int32 mnTotalHeight; - css::uno::Reference<css::beans::XPropertySet> mxTextView; - SharedBitmapDescriptor mpBackground; -}; - - - - //===== PresenterNotesView ==================================================== PresenterNotesView::PresenterNotesView ( @@ -169,8 +85,6 @@ PresenterNotesView::PresenterNotesView ( mxViewId(rxViewId), mpPresenterController(rpPresenterController), mxCanvas(), - mpBitmapContainer(), - mpBitmapFactory(), mxCurrentNotesPage(), mpScrollBar(), mxToolBarWindow(), @@ -182,7 +96,8 @@ PresenterNotesView::PresenterNotesView ( maTextBoundingBox(), mpBackground(), mnTop(0), - mnFontSize(12) + mpFont(), + mpTextView() { try { @@ -192,19 +107,16 @@ PresenterNotesView::PresenterNotesView ( mxParentWindow = xPane->getWindow(); mxCanvas = xPane->getCanvas(); - - const OUString sResourceURL (mxViewId->getResourceURL()); - PresenterTheme::SharedFontDescriptor pFont( - rpPresenterController->GetViewFont(sResourceURL)); - mpBitmapFactory.reset(new BitmapFactory( + mpTextView.reset(new PresenterTextView( rxComponentContext, - pFont, mxCanvas, - mpPresenterController->GetViewBackground(mxViewId->getResourceURL()))); - mpBitmapContainer.reset(new BitmapContainer(mpBitmapFactory)); + mpPresenterController->GetPaintManager()->GetInvalidator(mxParentWindow))); - maSeparatorColor = pFont->mnColor; - mnFontSize = pFont->mnSize; + const OUString sResourceURL (mxViewId->getResourceURL()); + mpFont.reset(new PresenterTheme::FontDescriptor( + rpPresenterController->GetViewFont(sResourceURL))); + maSeparatorColor = mpFont->mnColor; + mpTextView->SetFont(mpFont); CreateToolBar(rxComponentContext, rpPresenterController); @@ -383,16 +295,14 @@ void PresenterNotesView::SetSlide (const Reference<drawing::XDrawPage>& rxNotesP if (xText.is()) { sText += xText->getString(); + mpTextView->SetText(Reference<text::XText>(xText, UNO_QUERY)); } } } } } - mpBitmapFactory->SetText(sText); - Layout(); - mpBitmapContainer->Clear(); if (mpScrollBar.get() != NULL) { @@ -535,12 +445,12 @@ void SAL_CALL PresenterNotesView::keyPressed (const awt::KeyEvent& rEvent) switch (rEvent.KeyCode) { case awt::Key::A: - Scroll(-gnLineScrollFactor * mnFontSize); + Scroll(-gnLineScrollFactor * mpFont->mnSize); break; case awt::Key::Y: case awt::Key::Z: - Scroll(+gnLineScrollFactor * mnFontSize); + Scroll(+gnLineScrollFactor * mpFont->mnSize); break; case awt::Key::S: @@ -550,6 +460,24 @@ void SAL_CALL PresenterNotesView::keyPressed (const awt::KeyEvent& rEvent) 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; } } @@ -602,8 +530,7 @@ void PresenterNotesView::Layout (void) try { const double nTextBoxHeight (aNewTextBoundingBox.Y2 - aNewTextBoundingBox.Y1); - const sal_Int32 nHeight (mpBitmapFactory->GetHeightForWidth( - sal_Int32(aNewTextBoundingBox.X2 - aNewTextBoundingBox.X1))); + const double nHeight (mpTextView->GetTotalTextHeight()); if (nHeight > nTextBoxHeight) { bShowVerticalScrollbar = true; @@ -617,7 +544,6 @@ void PresenterNotesView::Layout (void) } mpScrollBar->SetVisible(bShowVerticalScrollbar); - mpBitmapFactory->SetWidth(sal_Int32(aNewTextBoundingBox.X2 - aNewTextBoundingBox.X1)); mpScrollBar->SetPosSize( geometry::RealRectangle2D( aNewTextBoundingBox.X2, @@ -638,14 +564,14 @@ void PresenterNotesView::Layout (void) { maTextBoundingBox = aNewTextBoundingBox; - // When the size has changed then we need a new text bitmap. - if (aNewTextBoundingBox.X2-aNewTextBoundingBox.X1 - != maTextBoundingBox.X2-maTextBoundingBox.X1 - || aNewTextBoundingBox.Y2-aNewTextBoundingBox.Y1 - != maTextBoundingBox.Y2-maTextBoundingBox.Y1) - { - mpBitmapContainer->Clear(); - } + mpTextView->SetLocation( + geometry::RealPoint2D( + aNewTextBoundingBox.X1, + aNewTextBoundingBox.Y1)); + mpTextView->SetSize( + geometry::RealSize2D( + aNewTextBoundingBox.X2 - aNewTextBoundingBox.X1, + aNewTextBoundingBox.Y2 - aNewTextBoundingBox.Y1)); } } @@ -668,6 +594,8 @@ void PresenterNotesView::Paint (const awt::Rectangle& rUpdateBox) PaintText(rUpdateBox); } + mpTextView->Paint(rUpdateBox); + if (rUpdateBox.Y + rUpdateBox.Height > maTextBoundingBox.Y2) { PaintToolBar(rUpdateBox); @@ -743,21 +671,6 @@ void PresenterNotesView::PaintText (const awt::Rectangle& rUpdateBox) awt::Rectangle()); } - // Iterator over all bitmaps that are (partially) visible and paint - // them. - const double nBottom (mnTop + maTextBoundingBox.Y2 - maTextBoundingBox.Y1); - BitmapContainer::const_iterator iBitmap (mpBitmapContainer->GetBegin(mnTop, nBottom)); - BitmapContainer::const_iterator iEnd (mpBitmapContainer->GetEnd(mnTop, nBottom)); - for ( ; iBitmap!=iEnd; ++iBitmap) - { - if (iBitmap->get() != NULL && (*iBitmap)->Bitmap.is()) - { - aRenderState.AffineTransform.m02 = maTextBoundingBox.X1; - aRenderState.AffineTransform.m12 = (*iBitmap)->Top + maTextBoundingBox.Y1 - mnTop; - mxCanvas->drawBitmap((*iBitmap)->Bitmap, aViewState, aRenderState); - } - } - Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); if (xSpriteCanvas.is()) xSpriteCanvas->updateScreen(sal_False); @@ -781,6 +694,7 @@ void PresenterNotesView::Scroll (const double rnDistance) try { mnTop += rnDistance; + mpTextView->SetOffset(0, mnTop); UpdateScrollBar(); Invalidate(); @@ -797,6 +711,7 @@ void PresenterNotesView::SetTop (const double nTop) try { mnTop = nTop; + mpTextView->SetOffset(0, mnTop); UpdateScrollBar(); Invalidate(); @@ -810,12 +725,12 @@ void PresenterNotesView::SetTop (const double nTop) void PresenterNotesView::ChangeFontSize (const sal_Int32 nSizeChange) { - const sal_Int32 nNewSize (mnFontSize + nSizeChange); + const sal_Int32 nNewSize (mpFont->mnSize + nSizeChange); if (nNewSize > 5) { - mnFontSize = nNewSize; - mpBitmapFactory->SetFontHeight(mnFontSize); - mpBitmapContainer->Clear(); + mpFont->mnSize = nNewSize; + mpFont->mxFont = NULL; + mpTextView->SetFont(mpFont); Layout(); UpdateScrollBar(); @@ -847,21 +762,28 @@ void PresenterNotesView::ChangeFontSize (const sal_Int32 nSizeChange) +::boost::shared_ptr<PresenterTextView> PresenterNotesView::GetTextView (void) const +{ + return mpTextView; +} + + + + void PresenterNotesView::UpdateScrollBar (void) { if (mpScrollBar.get() != NULL) { try { - double nHeight = mpBitmapFactory->GetTotalHeight(); - mpScrollBar->SetTotalSize(nHeight); + mpScrollBar->SetTotalSize(mpTextView->GetTotalTextHeight()); } catch(beans::UnknownPropertyException&) { OSL_ASSERT(false); } - mpScrollBar->SetLineHeight(mnFontSize*1.2); + mpScrollBar->SetLineHeight(mpFont->mnSize*1.2); mpScrollBar->SetThumbPosition(mnTop, false); mpScrollBar->SetThumbSize(maTextBoundingBox.Y2 - maTextBoundingBox.Y1); @@ -886,323 +808,4 @@ void PresenterNotesView::ThrowIfDisposed (void) -//===== PresenterNotesView::BitmapContainer =================================== - -PresenterNotesView::BitmapContainer::BitmapContainer ( - const ::boost::shared_ptr<BitmapFactory>& rpFactory) - : mpFactory(rpFactory), - mnMaximalCacheSize(gnMaximalCacheSize), - mnPartHeight(gnPartHeight), - mnTotalHeight(0) -{ -} - - - - -void PresenterNotesView::BitmapContainer::Clear (void) -{ - clear(); - mnTotalHeight = mpFactory->GetTotalHeight(); - const sal_Int32 nSize ((mnTotalHeight+mnPartHeight-1) / mnPartHeight); - if (nSize > 0) - resize(nSize, SharedNotesBitmapDescriptor()); -} - - - - -void PresenterNotesView::BitmapContainer::Prune ( - const sal_Int32 nTopIndex, - const sal_Int32 nBottomIndex) -{ - sal_Int32 nDistance (::std::max(nTopIndex-0, sal_Int32(size())-nBottomIndex)); - sal_Int32 nIndex; - sal_Int32 nTotalSize (GetMemorySize()); - iterator iPart; - - while (nDistance > 0 - && nTotalSize > mnMaximalCacheSize) - { - // Remove bitmap that is nDistance places before nTopIndex. - nIndex = nTopIndex - nDistance; - if (nIndex >= 0) - { - iPart = begin() + nIndex; - nTotalSize -= GetMemorySize((*iPart)->Bitmap); - (*iPart)->Bitmap = NULL; - } - - if (nTotalSize <= mnMaximalCacheSize) - break; - - // Remove bitmap that is nDistance places behind nBottomIndex. - nIndex = nBottomIndex + nDistance; - if (nIndex < sal_Int32(size())) - { - iPart = begin() + nIndex; - nTotalSize -= GetMemorySize((*iPart)->Bitmap); - (*iPart)->Bitmap = NULL; - } - } -} - - - - -sal_Int32 PresenterNotesView::BitmapContainer::GetMemorySize ( - const Reference<rendering::XBitmap>& rxBitmap) const -{ - if (rxBitmap.is()) - { - const geometry::IntegerSize2D aSize (rxBitmap->getSize()); - return aSize.Width * aSize.Height * 3; - } - return 0; -} - - - - -sal_Int32 PresenterNotesView::BitmapContainer::GetMemorySize (void) const -{ - sal_Int32 nSize (0); - for (const_iterator iBitmap=begin(); iBitmap!=end(); ++iBitmap) - if (iBitmap->get() != NULL) - if ((*iBitmap)->Bitmap.is()) - nSize += GetMemorySize((*iBitmap)->Bitmap); - return nSize; -} - - - - -sal_Int32 PresenterNotesView::BitmapContainer::GetTopIndex (const double nValue) const -{ - const sal_Int32 nIndex (sal::static_int_cast<sal_Int32>(nValue) / mnPartHeight); - if (nIndex < 0) - return 0; - else if (nIndex >= sal_Int32(size())) - return sal_Int32(size())-1; - else - return nIndex; -} - - - - -sal_Int32 PresenterNotesView::BitmapContainer::GetBottomIndex (const double nValue) const -{ - const sal_Int32 nIndex ((sal::static_int_cast<sal_Int32>(nValue)+mnPartHeight-1) / mnPartHeight); - if (nIndex >= sal_Int32(size())) - return size()-1; - else if (nIndex < 0) - return -1; - else return nIndex; -} - - - - -PresenterNotesView::BitmapContainer::const_iterator PresenterNotesView::BitmapContainer::GetBegin ( - const double nTop, - const double nBottom) -{ - const sal_Int32 nTopIndex (GetTopIndex(nTop)); - const sal_Int32 nBottomIndex(GetBottomIndex(nBottom)); - ProvideBitmaps(nTopIndex, nBottomIndex); - if (nTopIndex >= 0) - return begin()+nTopIndex; - else - return end(); -} - - - - -PresenterNotesView::BitmapContainer::const_iterator PresenterNotesView::BitmapContainer::GetEnd ( - const double nTop, - const double nBottom) -{ - (void)nTop; - const sal_Int32 nIndex (GetBottomIndex(nBottom)); - if (nIndex >= 0) - return (begin() + nIndex)+1; - else - return end(); -} - - - - -void PresenterNotesView::BitmapContainer::ProvideBitmaps ( - const sal_Int32 nTopIndex, - const sal_Int32 nBottomIndex) -{ - BitmapDescriptorSet aNewBitmaps; - - if (nTopIndex < 0 || nBottomIndex<0) - return; - - if (nTopIndex > nBottomIndex) - return; - - for (sal_Int32 nIndex=nTopIndex; nIndex<=nBottomIndex; ++nIndex) - { - iterator iPart (begin() + nIndex); - const sal_Int32 nTop (nIndex * mnPartHeight); - const sal_Int32 nBottom (nTop + mnPartHeight - 1); - if (iPart->get() == NULL) - { - iPart->reset(new NotesBitmapDescriptor(nTop, nBottom, NULL)); - } - if ( ! (*iPart)->Bitmap.is()) - { - (*iPart)->Bitmap = mpFactory->CreateBitmap(nTop, nBottom); - (*iPart)->Top = nTop; - (*iPart)->Bottom = nTop + (*iPart)->Bitmap->getSize().Height; - } - } - - // Calculate memory size used by all bitmaps. - if (GetMemorySize() > mnMaximalCacheSize) - Prune(nTopIndex,nBottomIndex); -} - - - - -//===== PresenterNotesView::BitmapFactory ===================================== - -PresenterNotesView::BitmapFactory::BitmapFactory ( - const Reference<XComponentContext>& rxComponentContext, - const PresenterTheme::SharedFontDescriptor& rpFont, - const Reference<rendering::XCanvas>& rxCanvas, - const SharedBitmapDescriptor& rpBackground) - : mxCanvas(rxCanvas), - msText(), - mpFont(rpFont), - maFontDescriptor(), - mnWidth(100), - mnTotalHeight(0), - mxTextView(), - mpBackground(rpBackground) -{ - Reference<lang::XMultiComponentFactory> xFactory ( - rxComponentContext->getServiceManager(), UNO_QUERY_THROW); - Sequence<Any> aArguments(1); - aArguments[0] <<= rxCanvas; - mxTextView = Reference<beans::XPropertySet>( - xFactory->createInstanceWithArgumentsAndContext( - A2S("com.sun.star.drawing.PresenterTextView"), - aArguments, - rxComponentContext), - UNO_QUERY_THROW); - mxTextView->setPropertyValue(A2S("BackgroundColor"), Any(sal_uInt32(0x00ff0000))); - if (mpFont.get() != NULL) - { - maFontDescriptor.Name = mpFont->msFamilyName; - maFontDescriptor.Height = sal::static_int_cast<sal_Int16>(mpFont->mnSize); - maFontDescriptor.StyleName = mpFont->msStyleName; - mxTextView->setPropertyValue(A2S("FontDescriptor"), Any(maFontDescriptor)); - mxTextView->setPropertyValue(A2S("TextColor"), Any(mpFont->mnColor)); - } -} - - - - -PresenterNotesView::BitmapFactory::~BitmapFactory (void) -{ - { - Reference<XComponent> xComponent (mxTextView, UNO_QUERY); - mxTextView = NULL; - if (xComponent.is()) - xComponent->dispose(); - } -} - - - - -void PresenterNotesView::BitmapFactory::SetText (const OUString& rsText) -{ - if (mxTextView.is()) - mxTextView->setPropertyValue(A2S("Text"), Any(rsText)); - mnTotalHeight = 0; -} - - - - -void PresenterNotesView::BitmapFactory::SetWidth (const sal_Int32 nWidth) -{ - mnWidth = nWidth; -} - - - - -void PresenterNotesView::BitmapFactory::SetFontHeight (const sal_Int32 nHeight) -{ - maFontDescriptor.Height = sal::static_int_cast<sal_Int16>(nHeight); - mxTextView->setPropertyValue(A2S("FontDescriptor"), Any(maFontDescriptor)); - if (mpFont.get() != NULL) - mpFont->mnSize = nHeight; - mnTotalHeight = 0; -} - - - - -sal_Int32 PresenterNotesView::BitmapFactory::GetHeightForWidth (const sal_Int32 nWidth) -{ - mxTextView->setPropertyValue( - A2S("Size"), - Any(awt::Size(nWidth, 100))); - sal_Int32 nHeight (0); - if (mxTextView->getPropertyValue(A2S("TotalHeight")) >>= nHeight) - return nHeight; - else - return -1; -} - - - - -sal_Int32 PresenterNotesView::BitmapFactory::GetTotalHeight (void) -{ - if (mnTotalHeight == 0) - { - sal_Int32 nHeight (0); - if (mxTextView->getPropertyValue(A2S("TotalHeight")) >>= nHeight) - mnTotalHeight = nHeight; - } - return mnTotalHeight; -} - - - - -Reference<rendering::XBitmap> PresenterNotesView::BitmapFactory::CreateBitmap ( - const sal_Int32 nTop, - const sal_Int32 nBottom) -{ - // Get text bitmap. - sal_Int32 nHeight; - if (nBottom > GetTotalHeight()) - nHeight = GetTotalHeight() - nTop + 1; - else - nHeight = nBottom - nTop + 1; - mxTextView->setPropertyValue(A2S("Size"), Any(awt::Size(mnWidth,nHeight))); - mxTextView->setPropertyValue(A2S("Top"), Any(sal_Int32(nTop))); - Reference<rendering::XBitmap> xTextBitmap ( - mxTextView->getPropertyValue(A2S("Bitmap")), UNO_QUERY); - - return xTextBitmap; -} - - - - } } // end of namespace ::sdext::presenter diff --git a/sdext/source/presenter/PresenterNotesView.hxx b/sdext/source/presenter/PresenterNotesView.hxx index c9d4974c8cfe..743770989b0d 100644 --- a/sdext/source/presenter/PresenterNotesView.hxx +++ b/sdext/source/presenter/PresenterNotesView.hxx @@ -49,7 +49,7 @@ #include <com/sun/star/drawing/framework/XResourceId.hpp> #include <com/sun/star/frame/XController.hpp> #include <rtl/ref.hxx> -#include <boost/scoped_ptr.hpp> +#include <boost/shared_ptr.hpp> namespace css = ::com::sun::star; @@ -67,6 +67,8 @@ 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 @@ -98,6 +100,9 @@ public: void ChangeFontSize (const sal_Int32 nSizeChange); + ::boost::shared_ptr<PresenterTextView> GetTextView (void) const; + + // lang::XEventListener virtual void SAL_CALL @@ -152,16 +157,11 @@ public: virtual void SAL_CALL keyReleased (const css::awt::KeyEvent& rEvent) throw (css::uno::RuntimeException); - class BitmapContainer; - class BitmapFactory; - 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; - ::boost::scoped_ptr<BitmapContainer> mpBitmapContainer; - ::boost::shared_ptr<BitmapFactory> mpBitmapFactory; css::uno::Reference<css::drawing::XDrawPage> mxCurrentNotesPage; ::rtl::Reference<PresenterScrollBar> mpScrollBar; css::uno::Reference<css::awt::XWindow> mxToolBarWindow; @@ -173,7 +173,8 @@ private: css::geometry::RealRectangle2D maTextBoundingBox; SharedBitmapDescriptor mpBackground; double mnTop; - sal_Int32 mnFontSize; + PresenterTheme::SharedFontDescriptor mpFont; + ::boost::shared_ptr<PresenterTextView> mpTextView; void CreateToolBar ( const css::uno::Reference<css::uno::XComponentContext>& rxContext, @@ -186,6 +187,7 @@ private: 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. diff --git a/sdext/source/presenter/PresenterPaintManager.cxx b/sdext/source/presenter/PresenterPaintManager.cxx index 49f9e0f905ee..11bcb04cca57 100644 --- a/sdext/source/presenter/PresenterPaintManager.cxx +++ b/sdext/source/presenter/PresenterPaintManager.cxx @@ -37,6 +37,7 @@ #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; @@ -57,6 +58,25 @@ PresenterPaintManager::PresenterPaintManager ( +::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) diff --git a/sdext/source/presenter/PresenterPaintManager.hxx b/sdext/source/presenter/PresenterPaintManager.hxx index a31ea78f883b..97b1099cdf49 100644 --- a/sdext/source/presenter/PresenterPaintManager.hxx +++ b/sdext/source/presenter/PresenterPaintManager.hxx @@ -36,6 +36,7 @@ #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; @@ -58,6 +59,11 @@ public: 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. diff --git a/sdext/source/presenter/PresenterPaneBase.cxx b/sdext/source/presenter/PresenterPaneBase.cxx index 1e63f90e5435..dcf05cc79469 100644 --- a/sdext/source/presenter/PresenterPaneBase.cxx +++ b/sdext/source/presenter/PresenterPaneBase.cxx @@ -37,6 +37,7 @@ #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> @@ -143,6 +144,14 @@ void PresenterPaneBase::SetTitle (const OUString& rsTitle) +::rtl::OUString PresenterPaneBase::GetTitle (void) const +{ + return msTitle; +} + + + + Reference<drawing::framework::XPaneBorderPainter> PresenterPaneBase::GetPaneBorderPainter (void) const { @@ -192,6 +201,19 @@ awt::Point PresenterPaneBase::GetCalloutAnchor (void) const +::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) diff --git a/sdext/source/presenter/PresenterPaneBase.hxx b/sdext/source/presenter/PresenterPaneBase.hxx index 8f97784577c4..5d205c326f0e 100644 --- a/sdext/source/presenter/PresenterPaneBase.hxx +++ b/sdext/source/presenter/PresenterPaneBase.hxx @@ -51,11 +51,13 @@ #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 < @@ -89,10 +91,13 @@ public: 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) @@ -124,9 +129,11 @@ public: // 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; diff --git a/sdext/source/presenter/PresenterPaneBorderPainter.cxx b/sdext/source/presenter/PresenterPaneBorderPainter.cxx index e2122f23dccc..7c84218dfb12 100644 --- a/sdext/source/presenter/PresenterPaneBorderPainter.cxx +++ b/sdext/source/presenter/PresenterPaneBorderPainter.cxx @@ -621,7 +621,7 @@ void PresenterPaneBorderPainter::Renderer::PaintTitle ( 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 + 3*nTextHeight/4; + double nY = rOuterBox.Y + (nTitleBarHeight - nTextHeight) / 2 - aBox.Y1; if (nY >= rInnerBox.Y) nY = rInnerBox.Y - 1; switch (rpStyle->meFontAnchor) diff --git a/sdext/source/presenter/PresenterPaneContainer.cxx b/sdext/source/presenter/PresenterPaneContainer.cxx index bd12aff59374..0fb36d0a34ad 100644 --- a/sdext/source/presenter/PresenterPaneContainer.cxx +++ b/sdext/source/presenter/PresenterPaneContainer.cxx @@ -78,6 +78,7 @@ 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, @@ -106,6 +107,7 @@ void PresenterPaneContainer::PreparePane ( pDescriptor->msTitleTemplate = rsTitle; pDescriptor->msTitle = OUString(); } + pDescriptor->msAccessibleTitleTemplate = rsAccessibleTitle; pDescriptor->maViewInitialization = rViewInitialization; pDescriptor->mnLeft = nLeft; pDescriptor->mnTop = nTop; @@ -151,7 +153,7 @@ PresenterPaneContainer::SharedPaneDescriptor pDescriptor = FindPaneURL(sPaneURL); if (pDescriptor.get() == NULL) - PreparePane(xPaneId, OUString(), OUString(), + PreparePane(xPaneId, OUString(), OUString(), OUString(), false, ViewInitializationFunction(), 0,0,0,0); pDescriptor = FindPaneURL(sPaneURL); if (pDescriptor.get() != NULL) diff --git a/sdext/source/presenter/PresenterPaneContainer.hxx b/sdext/source/presenter/PresenterPaneContainer.hxx index 26d7a86e31b2..584bd8fcfb94 100644 --- a/sdext/source/presenter/PresenterPaneContainer.hxx +++ b/sdext/source/presenter/PresenterPaneContainer.hxx @@ -102,6 +102,7 @@ public: 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; @@ -128,6 +129,7 @@ public: 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, diff --git a/sdext/source/presenter/PresenterPaneFactory.cxx b/sdext/source/presenter/PresenterPaneFactory.cxx index 9c9be61222ce..c5e6403de440 100644 --- a/sdext/source/presenter/PresenterPaneFactory.cxx +++ b/sdext/source/presenter/PresenterPaneFactory.cxx @@ -260,8 +260,6 @@ Reference<XResource> PresenterPaneFactory::CreatePane ( const Reference<XResourceId>& rxPaneId, const OUString& rsTitle) { - (void)rsTitle; - if ( ! rxPaneId.is()) return NULL; diff --git a/sdext/source/presenter/PresenterProtocolHandler.cxx b/sdext/source/presenter/PresenterProtocolHandler.cxx index cb680748ac2d..8e29da2544b8 100644 --- a/sdext/source/presenter/PresenterProtocolHandler.cxx +++ b/sdext/source/presenter/PresenterProtocolHandler.cxx @@ -801,9 +801,9 @@ void SetNotesViewCommand::Execute (void) return; if (mbOn) - pWindowManager->SetLayoutMode(PresenterWindowManager::Notes); + pWindowManager->SetViewMode(PresenterWindowManager::VM_Notes); else - pWindowManager->SetLayoutMode(PresenterWindowManager::Standard); + pWindowManager->SetViewMode(PresenterWindowManager::VM_Standard); } @@ -836,9 +836,7 @@ Any SetNotesViewCommand::GetState (void) const bool SetNotesViewCommand::IsActive ( const ::rtl::Reference<PresenterWindowManager>& rpWindowManager) const { - return rpWindowManager->GetLayoutMode() == PresenterWindowManager::Notes - && !rpWindowManager->IsSlideSorterActive() - && !rpWindowManager->IsHelpViewActive(); + return rpWindowManager->GetViewMode() == PresenterWindowManager::VM_Notes; } @@ -891,7 +889,7 @@ Any SetSlideSorterCommand::GetState (void) const if ( ! pWindowManager.is()) return Any(false); - return Any(pWindowManager->IsSlideSorterActive()); + return Any(pWindowManager->GetViewMode()==PresenterWindowManager::VM_SlideOverview); } @@ -944,7 +942,7 @@ Any SetHelpViewCommand::GetState (void) const if ( ! pWindowManager.is()) return Any(false); - return Any(pWindowManager->IsHelpViewActive()); + return Any(pWindowManager->GetViewMode()==PresenterWindowManager::VM_Help); } diff --git a/sdext/source/presenter/PresenterScreen.cxx b/sdext/source/presenter/PresenterScreen.cxx index 015884abfb25..52ad08583539 100644 --- a/sdext/source/presenter/PresenterScreen.cxx +++ b/sdext/source/presenter/PresenterScreen.cxx @@ -467,9 +467,7 @@ void PresenterScreen::InitializePresenterScreen (void) SetupPaneFactory(xContext); SetupViewFactory(xContext); - mpPresenterController->GetWindowManager()->SetSlideSorterState(false); - mpPresenterController->GetWindowManager()->SetLayoutMode( - PresenterWindowManager::Standard); + mpPresenterController->GetWindowManager()->RestoreViewMode(); } catch (RuntimeException&) { @@ -790,10 +788,11 @@ void PresenterScreen::ProcessViewDescriptions ( rConfiguration.GetConfigurationNode(A2S("Presenter/Views")), UNO_QUERY_THROW); - ::std::vector<rtl::OUString> aProperties (3); + ::std::vector<rtl::OUString> aProperties (4); aProperties[0] = OUString::createFromAscii("ViewURL"); aProperties[1] = OUString::createFromAscii("Title"); - aProperties[2] = OUString::createFromAscii("IsOpaque"); + aProperties[2] = OUString::createFromAscii("AccessibleTitle"); + aProperties[3] = OUString::createFromAscii("IsOpaque"); mnComponentIndex = 1; PresenterConfigurationAccess::ForAll( xViewDescriptionsNode, @@ -865,7 +864,7 @@ void PresenterScreen::ProcessViewDescription ( { (void)rsKey; - if (rValues.size() != 3) + if (rValues.size() != 4) return; try @@ -874,7 +873,10 @@ void PresenterScreen::ProcessViewDescription ( OUString sViewURL; rValues[0] >>= sViewURL; rValues[1] >>= aViewDescriptor.msTitle; - rValues[2] >>= aViewDescriptor.mbIsOpaque; + rValues[2] >>= aViewDescriptor.msAccessibleTitle; + rValues[3] >>= aViewDescriptor.mbIsOpaque; + if (aViewDescriptor.msAccessibleTitle.getLength()==0) + aViewDescriptor.msAccessibleTitle = aViewDescriptor.msTitle; maViewDescriptors[sViewURL] = aViewDescriptor; } catch (Exception&) @@ -913,6 +915,7 @@ void PresenterScreen::SetupView( xPaneId, rsViewURL, aViewDescriptor.msTitle, + aViewDescriptor.msAccessibleTitle, aViewDescriptor.mbIsOpaque, rViewInitialization, nLeft, diff --git a/sdext/source/presenter/PresenterScreen.hxx b/sdext/source/presenter/PresenterScreen.hxx index 7f7171477e25..e56f841f5cd3 100644 --- a/sdext/source/presenter/PresenterScreen.hxx +++ b/sdext/source/presenter/PresenterScreen.hxx @@ -164,6 +164,7 @@ private: { public: ::rtl::OUString msTitle; + ::rtl::OUString msAccessibleTitle; bool mbIsOpaque; }; typedef ::std::map<rtl::OUString,ViewDescriptor> ViewDescriptorContainer; diff --git a/sdext/source/presenter/PresenterSpritePane.hxx b/sdext/source/presenter/PresenterSpritePane.hxx index 0beb75a0c37e..42ea005cacf7 100644 --- a/sdext/source/presenter/PresenterSpritePane.hxx +++ b/sdext/source/presenter/PresenterSpritePane.hxx @@ -86,10 +86,10 @@ public: // XPane - css::uno::Reference<css::awt::XWindow> SAL_CALL getWindow (void) + virtual css::uno::Reference<css::awt::XWindow> SAL_CALL getWindow (void) throw (css::uno::RuntimeException); - css::uno::Reference<css::rendering::XCanvas> SAL_CALL getCanvas (void) + virtual css::uno::Reference<css::rendering::XCanvas> SAL_CALL getCanvas (void) throw (css::uno::RuntimeException); diff --git a/sdext/source/presenter/PresenterTextView.cxx b/sdext/source/presenter/PresenterTextView.cxx new file mode 100644 index 000000000000..2bb334b376f3 --- /dev/null +++ b/sdext/source/presenter/PresenterTextView.cxx @@ -0,0 +1,1599 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: PresenterNotesView.hxx,v $ + * + * $Revision: 1.5 $ + * + * 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); + sal_Int32 nLineEnd (0); + if ( ! maLines.empty()) + { + nLineStart = rCurrentLine.startPos; + nLineEnd = rCurrentLine.endPos; + } + + 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. + sal_Int32 nFirstCharacterIndex (0); + sal_Int32 nEndCharacterIndex (0); + double nX (mnXOrigin); + double nY (mnYOrigin + mnVerticalOffset + mnAscent); + const sal_Int8 nTextDirection (GetTextDirection()); + for (sal_Int32 nLineIndex=0,nLineCount=maLines.size(); + nLineIndex<nLineCount; + ++nLineIndex, nFirstCharacterIndex=nEndCharacterIndex, 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 diff --git a/sdext/source/presenter/PresenterTextView.hxx b/sdext/source/presenter/PresenterTextView.hxx new file mode 100644 index 000000000000..e168645ba01d --- /dev/null +++ b/sdext/source/presenter/PresenterTextView.hxx @@ -0,0 +1,323 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: PresenterNotesView.hxx,v $ + * + * $Revision: 1.5 $ + * + * 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 diff --git a/sdext/source/presenter/PresenterTheme.cxx b/sdext/source/presenter/PresenterTheme.cxx index 120522284d42..81aaf693f8d9 100644 --- a/sdext/source/presenter/PresenterTheme.cxx +++ b/sdext/source/presenter/PresenterTheme.cxx @@ -649,24 +649,66 @@ bool PresenterTheme::FontDescriptor::PrepareFont ( 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 = mnSize; + 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; - mxFont = rxCanvas->createFont( + return rxCanvas->createFont( aFontRequest, Sequence<beans::PropertyValue>(), geometry::Matrix2D(1,0,0,1)); +} - return mxFont.is(); + + + +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; } diff --git a/sdext/source/presenter/PresenterTheme.hxx b/sdext/source/presenter/PresenterTheme.hxx index 1d4e334db78d..cde59fe350ba 100644 --- a/sdext/source/presenter/PresenterTheme.hxx +++ b/sdext/source/presenter/PresenterTheme.hxx @@ -108,6 +108,14 @@ public: 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; diff --git a/sdext/source/presenter/PresenterTimer.cxx b/sdext/source/presenter/PresenterTimer.cxx index f66289f2e5e6..8acdec7ff417 100644 --- a/sdext/source/presenter/PresenterTimer.cxx +++ b/sdext/source/presenter/PresenterTimer.cxx @@ -68,6 +68,20 @@ public: typedef ::boost::shared_ptr<TimerTask> SharedTimerTask; +class TimerTaskComparator +{ +public: + bool operator() (const SharedTimerTask& rpTask1, const SharedTimerTask& rpTask2) + { + 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 @@ -100,7 +114,7 @@ private: static sal_Int32 mnTaskId; ::osl::Mutex maTaskContainerMutex; - typedef ::std::set<SharedTimerTask> TaskContainer; + typedef ::std::set<SharedTimerTask,TimerTaskComparator> TaskContainer; TaskContainer maScheduledTasks; bool mbIsRunning; ::osl::Mutex maCurrentTaskMutex; @@ -255,7 +269,7 @@ void TimerScheduler::ScheduleTask (const SharedTimerTask& rpTask) return; osl::MutexGuard aGuard (maTaskContainerMutex); - maScheduledTasks.insert(rpTask); + maScheduledTasks.insert(rpTask); if ( ! mbIsRunning) { diff --git a/sdext/source/presenter/PresenterTimer.hxx b/sdext/source/presenter/PresenterTimer.hxx index a5c111965917..812c0dfed5f0 100644 --- a/sdext/source/presenter/PresenterTimer.hxx +++ b/sdext/source/presenter/PresenterTimer.hxx @@ -70,6 +70,11 @@ public: 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, diff --git a/sdext/source/presenter/PresenterWindowManager.cxx b/sdext/source/presenter/PresenterWindowManager.cxx index 273753e0b4da..53db58867e27 100644 --- a/sdext/source/presenter/PresenterWindowManager.cxx +++ b/sdext/source/presenter/PresenterWindowManager.cxx @@ -32,6 +32,9 @@ // 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" @@ -73,8 +76,6 @@ using namespace ::com::sun::star::uno; using namespace ::com::sun::star::drawing::framework; using ::rtl::OUString; -#undef ENABLE_PANE_RESIZING - #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) namespace sdext { namespace presenter { @@ -121,6 +122,8 @@ namespace { } + + //===== PresenterWindowManager ================================================ PresenterWindowManager::PresenterWindowManager ( @@ -142,7 +145,7 @@ PresenterWindowManager::PresenterWindowManager ( mxScaledBackgroundBitmap(), maPaneBackgroundColor(), mxClipPolygon(), - meLayoutMode(Generic), + meLayoutMode(LM_Generic), mbIsSlideSorterActive(false), mbIsHelpViewActive(false), maLayoutListeners(), @@ -517,6 +520,8 @@ void SAL_CALL PresenterWindowManager::focusGained (const css::awt::FocusEvent& r { ThrowIfDisposed(); (void)rEvent; + OSL_TRACE("PresenterWindowManager::focusGained window %x\n", + rEvent.Source.get()); } @@ -623,7 +628,7 @@ void PresenterWindowManager::SetLayoutMode (const LayoutMode eMode) mpPresenterController->RequestViews( mbIsSlideSorterActive, - meLayoutMode==Notes, + meLayoutMode==LM_Notes, mbIsHelpViewActive); Layout(); NotifyLayoutModeChange(); @@ -648,10 +653,11 @@ void PresenterWindowManager::SetSlideSorterState (bool bIsActive) mbIsSlideSorterActive = bIsActive; if (mbIsSlideSorterActive) mbIsHelpViewActive = false; + StoreViewMode(GetViewMode()); mpPresenterController->RequestViews( mbIsSlideSorterActive, - meLayoutMode==Notes, + meLayoutMode==LM_Notes, mbIsHelpViewActive); Layout(); NotifyLayoutModeChange(); @@ -676,10 +682,11 @@ void PresenterWindowManager::SetHelpViewState (bool bIsActive) mbIsHelpViewActive = bIsActive; if (mbIsHelpViewActive) mbIsSlideSorterActive = false; + StoreViewMode(GetViewMode()); mpPresenterController->RequestViews( mbIsSlideSorterActive, - meLayoutMode==Notes, + meLayoutMode==LM_Notes, mbIsHelpViewActive); Layout(); NotifyLayoutModeChange(); @@ -697,6 +704,119 @@ bool PresenterWindowManager::IsHelpViewActive (void) const +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::createFromAscii("/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::createFromAscii("/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) { @@ -743,18 +863,14 @@ void PresenterWindowManager::Layout (void) else switch (meLayoutMode) { - case Standard: + case LM_Standard: default: LayoutStandardMode(); break; - case Notes: + case LM_Notes: LayoutNotesMode(); break; - - case Generic: - LayoutUnknownMode(); - break; } } catch (Exception&) diff --git a/sdext/source/presenter/PresenterWindowManager.hxx b/sdext/source/presenter/PresenterWindowManager.hxx index 2b71fc6b4311..6631ec70d413 100644 --- a/sdext/source/presenter/PresenterWindowManager.hxx +++ b/sdext/source/presenter/PresenterWindowManager.hxx @@ -113,15 +113,29 @@ public: void Update (void); void Layout (void); - enum LayoutMode { Standard, Notes, Generic }; + 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; - void SetSlideSorterState (bool bIsActive); bool IsSlideSorterActive (void) const; - - void SetHelpViewState (bool bIsActive); 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); @@ -219,6 +233,8 @@ private: void Invalidate (void); + void StoreViewMode (const ViewMode eViewMode); + void LayoutStandardMode (void); void LayoutNotesMode (void); void LayoutUnknownMode (void); diff --git a/sdext/source/presenter/makefile.mk b/sdext/source/presenter/makefile.mk index 04b13a2174aa..b35c3f3a4ae0 100644 --- a/sdext/source/presenter/makefile.mk +++ b/sdext/source/presenter/makefile.mk @@ -41,6 +41,7 @@ ENABLE_EXCEPTIONS=TRUE .INCLUDE : rtlbootstrap.mk .INCLUDE : settings.mk +.IF "$(L10N_framework)"=="" .INCLUDE : $(PRJ)$/util$/makefile.pmk .IF "$(ENABLE_PRESENTER_SCREEN)" == "NO" @@ -54,6 +55,7 @@ common_build_zip= # --- Files ------------------------------------- SLOFILES= \ + $(SLO)$/PresenterAccessibility.obj \ $(SLO)$/PresenterAnimation.obj \ $(SLO)$/PresenterAnimator.obj \ $(SLO)$/PresenterBitmapContainer.obj \ @@ -83,6 +85,7 @@ SLOFILES= \ $(SLO)$/PresenterSlideSorter.obj \ $(SLO)$/PresenterSprite.obj \ $(SLO)$/PresenterSpritePane.obj \ + $(SLO)$/PresenterTextView.obj \ $(SLO)$/PresenterTheme.obj \ $(SLO)$/PresenterTimer.obj \ $(SLO)$/PresenterToolBar.obj \ @@ -99,6 +102,7 @@ SHL1TARGET= $(TARGET).uno SHL1STDLIBS= $(CPPUHELPERLIB) \ $(CPPULIB) \ $(SALLIB) + SHL1DEPN= SHL1IMPLIB= i$(SHL1TARGET) SHL1LIBS= $(SLB)$/$(TARGET).lib @@ -257,9 +261,10 @@ PLATFORMID:=$(RTL_OS:l)_$(RTL_ARCH:l) # --- Targets ---------------------------------- +.ENDIF # L10N_framework .INCLUDE : target.mk - +.IF "$(L10N_framework)"=="" $(SLO)$/PresenterComponent.obj : $(INCCOM)$/PresenterExtensionIdentifier.hxx $(INCCOM)$/PresenterExtensionIdentifier.hxx : PresenterExtensionIdentifier.txx @@ -362,3 +367,8 @@ $(DESCRIPTION) $(PHONYDESC) : $$(@:f) .ENDIF # "$(ENABLE_PRESENTER_SCREEN)" != "NO" +.ELSE +ivo: + $(ECHO) +.ENDIF # L10N_framework + 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 index 4fd6b68b974d..b407d9215621 100644 --- a/sdext/source/presenter/registry/data/org/openoffice/Office/extension/PresenterScreen.xcu +++ b/sdext/source/presenter/registry/data/org/openoffice/Office/extension/PresenterScreen.xcu @@ -434,7 +434,7 @@ <value xml:lang="en-US">Previous slide, or previous effect</value> </prop> </node> - <node oor:name="c_Separator" oor:op="replace"> + <node oor:name="c" oor:op="replace"> <prop oor:name="Left"> <value xml:lang="en-US"> </value> </prop> @@ -458,7 +458,7 @@ <value xml:lang="en-US">Last slide</value> </prop> </node> - <node oor:name="f_Separator" oor:op="replace"> + <node oor:name="f" oor:op="replace"> <prop oor:name="Left"> <value xml:lang="en-US"> </value> </prop> @@ -482,7 +482,7 @@ <value xml:lang="en-US">Next slide without effects</value> </prop> </node> - <node oor:name="i_Separator" oor:op="replace"> + <node oor:name="i" oor:op="replace"> <prop oor:name="Left"> <value xml:lang="en-US"> </value> </prop> @@ -506,7 +506,7 @@ <value xml:lang="en-US">Whites/Unwhites the screen</value> </prop> </node> - <node oor:name="l_Separator" oor:op="replace"> + <node oor:name="l" oor:op="replace"> <prop oor:name="Left"> <value xml:lang="en-US"> </value> </prop> @@ -522,7 +522,7 @@ <value xml:lang="en-US">End slide show</value> </prop> </node> - <node oor:name="n_Separator" oor:op="replace"> + <node oor:name="n" oor:op="replace"> <prop oor:name="Left"> <value xml:lang="en-US"> </value> </prop> @@ -538,7 +538,7 @@ <value xml:lang="en-US">Go to that slide</value> </prop> </node> - <node oor:name="p_Separator" oor:op="replace"> + <node oor:name="p" oor:op="replace"> <prop oor:name="Left"> <value xml:lang="en-US"> </value> </prop> @@ -562,7 +562,15 @@ <value xml:lang="en-US">Scroll notes up/down</value> </prop> </node> - <node oor:name="s_Separator" oor:op="replace"> + <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> @@ -570,7 +578,7 @@ <value xml:lang="en-US"> </value> </prop> </node> - <node oor:name="t" oor:op="replace"> + <node oor:name="u" oor:op="replace"> <prop oor:name="Left"> <value xml:lang="en-US">Ctrl-'1'</value> </prop> @@ -578,7 +586,7 @@ <value xml:lang="en-US">Shows the Presenter Console</value> </prop> </node> - <node oor:name="u" oor:op="replace"> + <node oor:name="v" oor:op="replace"> <prop oor:name="Left"> <value xml:lang="en-US">Ctrl-'2'</value> </prop> @@ -586,7 +594,7 @@ <value xml:lang="en-US">Shows the Presentation Notes</value> </prop> </node> - <node oor:name="v" oor:op="replace"> + <node oor:name="w" oor:op="replace"> <prop oor:name="Left"> <value xml:lang="en-US">Ctrl-'3'</value> </prop> @@ -1007,6 +1015,9 @@ <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"> @@ -1050,6 +1061,12 @@ <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"> @@ -1190,5 +1207,22 @@ </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/schema/org/openoffice/Office/extension/PresenterScreen.xcs b/sdext/source/presenter/registry/schema/org/openoffice/Office/extension/PresenterScreen.xcs index 48aad71027d8..58f23c625db2 100644 --- a/sdext/source/presenter/registry/schema/org/openoffice/Office/extension/PresenterScreen.xcs +++ b/sdext/source/presenter/registry/schema/org/openoffice/Office/extension/PresenterScreen.xcs @@ -310,6 +310,11 @@ title means that no title is displayed.</desc></info> <value></value> </prop> + <prop oor:name="AccessibleTitle" oor:type="xs:string"> + <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> @@ -456,6 +461,13 @@ 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> |