1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifndef INCLUDED_EDITENG_ACCESSIBLESTATICTEXTBASE_HXX
21 #define INCLUDED_EDITENG_ACCESSIBLESTATICTEXTBASE_HXX
22 
23 #include <memory>
24 #include <tools/gen.hxx>
25 #include <cppuhelper/implbase2.hxx>
26 #include <com/sun/star/uno/Reference.hxx>
27 #include <com/sun/star/accessibility/XAccessibleText.hpp>
28 #include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
29 #include <com/sun/star/accessibility/TextSegment.hpp>
30 #include <editeng/editengdllapi.h>
31 
32 namespace com::sun::star::accessibility { class XAccessible; }
33 
34 class SvxEditSource;
35 
36 namespace accessibility
37 {
38 
39     class AccessibleStaticTextBase_Impl;
40 
41     typedef ::cppu::ImplHelper2<
42         css::accessibility::XAccessibleText,
43         css::accessibility::XAccessibleTextAttributes > AccessibleStaticTextBase_BASE;
44 
45     /** Helper class for objects containing EditEngine/Outliner text
46 
47         This class implements the XAccessibleText interface for static
48         text, somewhat similar to the children of the
49         AccessibleTextHelper class. Currently, there are no children,
50         i.e. the whole text is presented in one big chunk. This might
51         change in the future, if a need for image bullets should
52         arise. These, by convention, would be represented as children
53         of the text.
54 
55         You have to implement the SvxEditSource, SvxTextForwarder,
56         SvxViewForwarder and SvxEditViewForwarder interfaces in order
57         to enable your object to cooperate with this
58         class. SvxTextForwarder encapsulates the fact that text
59         objects do not necessarily have an EditEngine at their
60         disposal, SvxViewForwarder and SvxEditViewForwarder do the
61         same for the document and the edit view. The three mentioned
62         forwarder objects are not stored by the AccessibleTextHelper,
63         but fetched every time from the SvxEditSource. So you are best
64         off making your SvxEditSource::Get*Forwarder methods cache the
65         current forwarder.
66 
67         As this class is intended for static (i.e. non-changing) text
68         only, no event broadcasting is necessary. You must handle
69         visibility by yourself, the bounding boxes returned by
70         getCharacterBounds() are relative to your accessibility
71         object.
72 
73         @attention All public non-UNO methods (those are the uppercase
74         ones) must not be called with any mutex hold, except when
75         calling from the main thread (with holds the solar mutex),
76         unless stated otherwise. This is because they themselves might
77         need the solar mutex in addition to the object mutex, and the
78         ordering of the locking must be: first solar mutex, then
79         object mutex. Furthermore, state change events might be fired
80         internally.
81 
82         @derive Use this class as a base for objects containing static
83         edit engine text. To avoid overwriting every interface method
84         to intercept derived object defunc state, just set NULL as the
85         edit source. Every interface method will then properly throw
86         an exception.
87     */
88     class EDITENG_DLLPUBLIC AccessibleStaticTextBase : public AccessibleStaticTextBase_BASE
89     {
90 
91     public:
92         /** Create accessible text object for given edit source
93 
94             @param pEditSource
95             The edit source to use. Object ownership is transferred
96             from the caller to the callee. The object listens on the
97             SvxEditSource for object disposal, so no provisions have
98             to be taken if the caller destroys the data (e.g. the
99             model) contained in the given SvxEditSource.
100 
101         */
102         explicit AccessibleStaticTextBase( ::std::unique_ptr< SvxEditSource > && pEditSource );
103 
104         virtual ~AccessibleStaticTextBase();
105 
106     private:
107         AccessibleStaticTextBase( const AccessibleStaticTextBase& ) = delete;
108         AccessibleStaticTextBase& operator= ( const AccessibleStaticTextBase& ) = delete;
109 
110     public:
111 
112         /** Set the current edit source
113 
114             @attention You are required to have the solar mutex
115             locked, when calling this method. Thus, the method should
116             only be called from the main office thread.
117 
118             The EditSource set here is required to broadcast out the
119             following hints: SfxHintId::EditSourceParasMoved,
120             SfxHintId::EditSourceSelectionChanged, SfxHintId::TextModified,
121             SfxHintId::TextParaInserted, SfxHintId::TextParaRemoved,
122             SfxHintId::TextHeightChanged,
123             SfxHintId::TextViewScrolled. Otherwise, not all state changes
124             will get noticed by the accessibility object. Further
125             more, when the corresponding core object or the model is
126             dying, either the edit source must be set to NULL or it
127             has to broadcast a SfxHintId::Dying hint.
128 
129             This class does not have a dispose method, since it is not
130             a UNO component. Nevertheless, it holds C++ references to
131             several core objects, so you should issue a
132             SetEditSource(::std::unique_ptr<SvxEditSource>()) in
133             your dispose() method.
134 
135             @param pEditSource
136             The new edit source to set. Object ownership is transferred
137             from the caller to the callee.
138         */
139         void SetEditSource( ::std::unique_ptr< SvxEditSource > && pEditSource );
140 
141         /** Set the event source
142 
143             @attention When setting a reference here, you should call
144             Dispose() when you as the owner are disposing, since until
145             then this object will hold that reference
146 
147             @param rInterface
148             The interface that should be set as the source for
149             accessibility events sent by this object.
150          */
151         void SetEventSource( const css::uno::Reference< css::accessibility::XAccessible >& rInterface );
152 
153         /** Set offset of EditEngine from parent
154 
155             @attention You are required to have the solar mutex
156             locked, when calling this method. Thus, the method should
157             only be called from the main office thread.
158 
159             If the origin of the underlying EditEngine does
160             not correspond to the upper left corner of the object
161             using this class, you have to specify the offset.
162 
163             @param rPoint
164             The offset in screen coordinates (i.e. pixel)
165         */
166         void SetOffset( const Point& rPoint );
167 
168         /** Drop all references and enter disposed state
169 
170             This method drops all references to external objects (also
171             the event source reference set via SetEventSource()) and
172             sets the object into the disposed state (i.e. the methods
173             return default values or throw a uno::DisposedException
174             exception).
175          */
176         void Dispose();
177 
178         // XAccessibleText interface implementation
179         virtual sal_Int32 SAL_CALL getCaretPosition() override;
180         virtual sal_Bool SAL_CALL setCaretPosition( sal_Int32 nIndex ) override;
181         virtual sal_Unicode SAL_CALL getCharacter( sal_Int32 nIndex ) override;
182         virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getCharacterAttributes( sal_Int32 nIndex, const css::uno::Sequence< OUString >& aRequestedAttributes ) override;
183         virtual css::awt::Rectangle SAL_CALL getCharacterBounds( sal_Int32 nIndex ) override;
184         virtual sal_Int32 SAL_CALL getCharacterCount() override;
185         virtual sal_Int32 SAL_CALL getIndexAtPoint( const css::awt::Point& aPoint ) override;
186         virtual OUString SAL_CALL getSelectedText() override;
187         virtual sal_Int32 SAL_CALL getSelectionStart() override;
188         virtual sal_Int32 SAL_CALL getSelectionEnd() override;
189         /// This will only work with a functional SvxEditViewForwarder, i.e. an EditEngine/Outliner in edit mode
190         virtual sal_Bool SAL_CALL setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) override;
191         virtual OUString SAL_CALL getText() override;
192         virtual OUString SAL_CALL getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) override;
193         /// Does not support AccessibleTextType::SENTENCE (missing feature in EditEngine)
194         virtual css::accessibility::TextSegment SAL_CALL getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) override;
195         /// Does not support AccessibleTextType::SENTENCE (missing feature in EditEngine)
196         virtual css::accessibility::TextSegment SAL_CALL getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) override;
197         /// Does not support AccessibleTextType::SENTENCE (missing feature in EditEngine)
198         virtual css::accessibility::TextSegment SAL_CALL getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) override;
199         /// This will only work with a functional SvxEditViewForwarder, i.e. an EditEngine/Outliner in edit mode
200         virtual sal_Bool SAL_CALL copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) override;
201 
202         // XAccessibleTextAttributes
203         virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getDefaultAttributes( const css::uno::Sequence< OUString >& RequestedAttributes ) override;
204         virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getRunAttributes( sal_Int32 Index, const css::uno::Sequence< OUString >& RequestedAttributes ) override;
205 
206         // child-related methods from XAccessibleContext
207         /// @throws css::uno::RuntimeException
208         virtual sal_Int32 SAL_CALL getAccessibleChildCount();
209         /// @throws css::lang::IndexOutOfBoundsException
210         /// @throws css::uno::RuntimeException
211         virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i );
212 
213         // child-related methods from XAccessibleComponent
214         /// @throws css::uno::RuntimeException
215         virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& aPoint );
216 
217     protected:
218         tools::Rectangle GetParagraphBoundingBox() const;
219 
220     private:
221 
222         /// @dyn
223         const std::unique_ptr< AccessibleStaticTextBase_Impl > mpImpl;
224 
225     };
226 
227 } // end of namespace accessibility
228 
229 #endif // INCLUDED_EDITENG_ACCESSIBLESTATICTEXTBASE_HXX
230 
231 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
232