AccessibleTextHelper.hxx 18.4 KB
Newer Older
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126

#ifndef _SVX_ACCESSILE_TEXT_HELPER_HXX_
#define _SVX_ACCESSILE_TEXT_HELPER_HXX_

#include <memory>
#include <sal/types.h>
#include <tools/gen.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/accessibility/XAccessible.hpp>
#include <com/sun/star/accessibility/XAccessibleContext.hpp>
#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
#include "svx/svxdllapi.h"


class SvxTextForwarder;
class SvxViewForwarder;
class SvxEditSource;

namespace accessibility
{

    class AccessibleTextHelper_Impl;

    /** Helper class for objects containing EditEngine/Outliner text

        This class provides the methods from the XAccessibleContext,
        XAccessibleEventBroadcaster and XAccessibleComponent
        interfaces, that are common to all accessible objects
        containing an edit engine.

        The text contained in the EditEngine/Outliner is presented as
        children of this class, namely for every text paragraph a
        AccessibleEditableTextPara child object is generated. As this
        class manages these children for itself, it has to send out
        AccessibleEventId::CHILD events on your
        behalf. Thus, you must forward every call to your
        addEventListener()/removeEventListener() methods to the
        AccessibleTextHelper (methods
        AddEventListener/RemoveEventListener), otherwise none or not
        every one of your event listener will notice child changes.

        You have to implement the SvxEditSource, SvxTextForwarder,
        SvxViewForwarder and SvxEditViewForwarder interfaces in order
        to enable your object to cooperate with this
        class. SvxTextForwarder encapsulates the fact that text
        objects do not necessarily have an EditEngine at their
        disposal, SvxViewForwarder and SvxEditViewForwarder do the
        same for the document and the edit view. The three mentioned
        forwarder objects are not stored by the AccessibleTextHelper,
        but fetched every time from the SvxEditSource. So you are best
        off making your SvxEditSource::Get*Forwarder methods cache the
        current forwarder.

        To support changes in edit mode or conversion of fixed text
        into EditEngine text, you can change the SvxEditSource this
        class is referring to. This might render all children invalid
        and change the child count, since the AccessibleTextHelper
        reinitializes itself from scratch.

        This class registers itself at the SvxEditSource as a state
        listener and manages the state of its children (i.e. the
        paragraphs). See the method documentation of
        AccessibleTextHelper::SetEditSource for the expected
        events. Generally, be prepared that when sending any of these
        events via SvxEditSource::GetBroadcaster() broadcaster, the
        AccessibleTextHelper will call the SvxEditSource and their
        forwarder to update it's state. Avoid being inconsistent in
        the facts you tell in the events, e.g. when sending a
        TEXT_HINT_PARAINSERTED event, the
        SvxEditSource::GetTextForwarder().GetParagraphCount() should
        already include the newly inserted paragraph.

        @attention All public methods must not be called with any
        mutex hold, except when calling from the main thread (with
        holds the solar mutex), unless stated otherwise. This is
        because they themselves might need the solar mutex in addition
        to the object mutex, and the ordering of the locking must be:
        first solar mutex, then object mutex. Furthermore, state
        change events might be fired internally.

        @derive Use this class in an aggregation and forward, or
        derive from it and overwrite. If the Remove/AddEventListener
        methods are overwritten, make sure FireEvent is adapted,
        too.

        @see SvxEditSource
        @see SvxTextForwarder
        @see SvxViewForwarder
        @see SvxEditViewForwarder
    */
    class SVX_DLLPUBLIC AccessibleTextHelper
    {

    public:
        typedef ::std::vector< sal_Int16 > VectorOfStates;

        /** Create accessible text object for given edit source

            @param pEditSource
            The edit source to use. Object ownership is transferred
            from the caller to the callee. The object listens on the
            SvxEditSource for object disposal, so no provisions have
            to be taken if the caller destroys the data (e.g. the
            model) contained in the given SvxEditSource.

        */
Peter Foley's avatar
Peter Foley committed
127
        SAL_WNODEPRECATED_DECLARATIONS_PUSH
128
        explicit AccessibleTextHelper( ::std::auto_ptr< SvxEditSource > pEditSource );
Peter Foley's avatar
Peter Foley committed
129
        SAL_WNODEPRECATED_DECLARATIONS_POP
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
        virtual ~AccessibleTextHelper();

    protected:

        // declared, but not defined
        AccessibleTextHelper( const AccessibleTextHelper& );
        // declared, but not defined
        AccessibleTextHelper& operator= ( const AccessibleTextHelper& );

    public:
        /** Query the current edit source

            @attention This method returns by reference, so you are
            responsible for serialization (typically, you aquired the
            solar mutex when calling this method). Thus, the method
            should only be called from the main office thread.

         */
        virtual const SvxEditSource& GetEditSource() const SAL_THROW((::com::sun::star::uno::RuntimeException));

        /** Set the current edit source

            @attention Might fire state change events, therefore,
            don't hold any mutex except solar mutex, which you are
            required to lock before. This method should only be called
            from the main office thread.

            The EditSource set here is required to broadcast out the
            following hints: EDITSOURCE_HINT_PARASMOVED,
            EDITSOURCE_HINT_SELECTIONCHANGED, TEXT_HINT_MODIFIED,
            TEXT_HINT_PARAINSERTED, TEXT_HINT_PARAREMOVED,
            TEXT_HINT_TEXTHEIGHTCHANGED,
            TEXT_HINT_VIEWSCROLLED. Otherwise, not all state changes
            will get noticed by the accessibility object. Further
            more, when the corresponding core object or the model is
            dying, either the edit source must be set to NULL or it
            has to broadcast a SFX_HINT_DYING hint.

            If the SvxEditSource's managed text can change between
            edit/non-edit mode (i.e. there are times when
            SvxEditSource::GetEditViewForwarder(sal_False) returns
            NULL), then the two additional hints are required:
            HINT_BEGEDIT and HINT_ENDEDIT. When the
            AccessibleTextHelper receives a HINT_BEGEDIT, it expects
            the SvxEditSource already in edit mode. On a HINT_ENDEDIT,
            edit mode must already been left. The rationale for these
            events are the fact that focus and selection have to be
            updated in edit mode, and completely relinquished and
            reset to the parent (for the focus) in non-edit mode.

            This class does not have a dispose method, since it is not
            a UNO component. Nevertheless, it holds C++ references to
            several core objects, so you should issue a
            SetEditSource(::std::auto_ptr<SvxEditSource>(NULL)) in
            your dispose() method.

            @param pEditSource
            The new edit source to set. Object ownership is transferred
            from the caller to the callee.
        */
Peter Foley's avatar
Peter Foley committed
190
        SAL_WNODEPRECATED_DECLARATIONS_PUSH
191
        virtual void SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((::com::sun::star::uno::RuntimeException));
Peter Foley's avatar
Peter Foley committed
192
        SAL_WNODEPRECATED_DECLARATIONS_POP
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284

        /** Set the event source

            You should set the event source before registering any
            event listener and before requesting any child. Children
            of this object receive the event source as their parent
            accessible object. That is, the event source is best set
            in your object's init method.

            @attention When setting a reference here, you should call
            Dispose() when you as the owner are disposing, since until
            then this object will hold that reference

            @param rInterface
            The interface that should be set as the source for
            accessibility events sent by this object.
         */
        virtual void SetEventSource( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rInterface );

        /** Get the event source

            @return the interface that is set as the source for
            accessibility events sent by this object.
         */
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > GetEventSource() const;

        /** Set offset of EditEngine/Outliner from parent

            If the origin of the underlying EditEngine/Outliner does
            not correspond to the upper left corner of the object
            using this class, you have to specify the offset.

            @attention Might fire state change events, therefore,
            don't hold any mutex except solar mutex, which you are
            required to lock before. This method should only be called
            from the main office thread.

            @param rPoint
            The offset in screen coordinates (i.e. pixel)
        */
        virtual void SetOffset( const Point& rPoint );

        /** Query offset of EditEngine/Outliner from parent

            @return the offset in screen coordinates (i.e. pixel)
        */
        virtual Point GetOffset() const;

        /** Set offset the object adds to all children's indices

            This can be used if the owner of this object has children
            handled by itself. Setting an offset different from 0
            leads to this object mimicking that all it's children are
            within the range [nOffset, GetChildCount()+nOffset). That
            means, GetChild() also expects the index to be in this
            range.

            @attention Might fire state change events, therefore,
            don't hold any mutex except solar mutex, which you are
            required to lock before. This method should only be called
            from the main office thread.

            @param nOffset
            The offset to add to every children's index.
        */
        virtual void SetStartIndex( sal_Int32 nOffset );

        /** Query offset the object adds to all children's indices

            @return the offset to add to every children's index.
        */
        virtual sal_Int32 GetStartIndex() const;

        /** Sets a vector of additional accessible states.

            The states are passed to every created child object
            (text paragraph). The state values are defined in
            com::sun::star::accessibility::AccessibleStateType.

            This function has to be called before querying for
            any children (e.g. with GetChild()).
         */
        void SetAdditionalChildStates( const VectorOfStates& rChildStates );

        /** Update the visible children

            @attention Might fire state change events, therefore,
            don't hold any mutex except solar mutex, which you are
            required to lock before. This method should only be called
            from the main office thread.

            This method reevaluates the visibility of all
Tor Lillqvist's avatar
Tor Lillqvist committed
285
            children. Call this method if your visibility state has
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
            changed somehow, e.g. if the visible area has changed and
            the AccessibleTextHelper isn't notified internally
            (e.g. via TEXT_HINT_VIEWSCROLLED). Normally, there should
            not be a need to call this method.
        */
        virtual void UpdateChildren() SAL_THROW((::com::sun::star::uno::RuntimeException));

        /** Drop all references and enter disposed state

            This method drops all references to external objects (also
            the event source reference set via SetEventSource()) and
            sets the object into the disposed state (i.e. the methods
            return default values or throw a uno::DisposedException
            exception).
         */
        virtual void Dispose();

        /** Set the focus state of the accessibility object

            Since this class handles children which also might get the
            focus, the user of this class is encouraged to delegate
            focus handling. Whenever the focus state of the
            surrounding object changes, this method has to be called.

            The protocol of focus handling for a user of this class is
            then to call SetFocus() with the appropriate focus state,
            and HaveFocus() to determine the focus state you tell the
            outside.

            @attention Might fire state change events, therefore,
            don't hold any mutex except solar mutex, which you are
            required to lock before. This method should only be called
            from the main office thread.

            @param bHaveFocus
            Whether we got or we lost the focus. Set to sal_True if
            focus is gotten, sal_False otherwise.

            @see HaveFocus()
         */
        virtual void SetFocus( sal_Bool bHaveFocus = sal_True ) SAL_THROW((::com::sun::star::uno::RuntimeException));

        /** Query the focus state of the surrounding object

            If focus handling is delegated to this class, determine
            focus state with this method. Be prepared that even if you
            set the focus with SetFocus(sal_True), this method might
            return sal_False. This is the case if one of the children
            actually got the focus.

            @return the state of the focus ownership
         */
        virtual sal_Bool HaveFocus() SAL_THROW((::com::sun::star::uno::RuntimeException));

        /** Call this method to invoke all event listeners with the given event

            @attention Fires state change events, therefore, don't hold any mutex

            @param nEventId
            Id of the event to send, @see AccessibleEventId

            @param rNewValue
            The value we've changed into

            @param rOldValue
            The old value before the change
        */
        virtual void FireEvent( const sal_Int16 nEventId,
                                const ::com::sun::star::uno::Any& rNewValue = ::com::sun::star::uno::Any(),
                                const ::com::sun::star::uno::Any& rOldValue = ::com::sun::star::uno::Any() ) const;

        /** Call this method to invoke all event listeners with the given event

            @attention Fires state change events, therefore, don't hold any mutex

            @param rEvent
            The event to send, @see AccessibleEventObject

        */
        // TODO: make that virtual next time
        void FireEvent( const ::com::sun::star::accessibility::AccessibleEventObject& rEvent ) const;

        /** Query select state of the text managed by this object

            @attention Don't call with locked mutexes. You may hold
            the solar mutex, but this method aquires it anyway.

            @return sal_True, if the text or parts of it are currently selected
        */
        virtual sal_Bool IsSelected() const;

        // XAccessibleContext child handling methods
        //-----------------------------------------------------------------
        /** Implements getAccessibleChildCount

            @attention Don't call with locked mutexes. You may hold
            the solar mutex, but this method aquires it anyway.
        */
        virtual sal_Int32 GetChildCount() SAL_THROW((::com::sun::star::uno::RuntimeException));
        /** Implements getAccessibleChild

            @attention Don't call with locked mutexes. You may hold
            the solar mutex, but this method aquires it anyway.
        */
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > GetChild( sal_Int32 i ) SAL_THROW((::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException));

        // XAccessibleEventBroadcaster child related methods
        //-----------------------------------------------------------------
        /** Implements addEventListener

            @attention Don't call with locked mutexes
        */
        virtual void AddEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) SAL_THROW((::com::sun::star::uno::RuntimeException));
        /** Implements removeEventListener

            @attention Don't call with locked mutexes
        */
        virtual void RemoveEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) SAL_THROW((::com::sun::star::uno::RuntimeException));

        // XAccessibleComponent child related methods
        //-----------------------------------------------------------------
        /** Implements getAccessibleAt

            @attention Don't call with locked mutexes. You may hold
            the solar mutex, but this method aquires it anyway.
        */
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL GetAt( const ::com::sun::star::awt::Point& aPoint ) SAL_THROW((::com::sun::star::uno::RuntimeException));

    private:

        /// @dyn
        const std::auto_ptr< AccessibleTextHelper_Impl > mpImpl;

    };

} // end of namespace accessibility

#endif /* _SVX_ACCESSILE_TEXT_HELPER_HXX_ */
424 425

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */