Merge branch 'mdoff' of ssh://git.codethink.co.uk/git/atspi-dbus
[platform/core/uifw/at-spi2-atk.git] / pyatspi / text.py
1 #Copyright (C) 2008 Codethink Ltd
2
3 #This library is free software; you can redistribute it and/or
4 #modify it under the terms of the GNU Lesser General Public
5 #License version 2 as published by the Free Software Foundation.
6
7 #This program is distributed in the hope that it will be useful,
8 #but WITHOUT ANY WARRANTY; without even the implied warranty of
9 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 #GNU General Public License for more details.
11 #You should have received a copy of the GNU Lesser General Public License
12 #along with this program; if not, write to the Free Software
13 #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
14
15 import dbus
16
17 import interfaces
18 from base import BaseProxy, Enum
19 from factory import add_accessible_class
20
21 __all__ = [
22            "Text",
23            "TEXT_BOUNDARY_TYPE",
24            "TEXT_BOUNDARY_CHAR",
25            "TEXT_BOUNDARY_WORD_START",
26            "TEXT_BOUNDARY_WORD_END",
27            "TEXT_BOUNDARY_SENTENCE_START",
28            "TEXT_BOUNDARY_SENTENCE_END",
29            "TEXT_BOUNDARY_LINE_START",
30            "TEXT_BOUNDARY_LINE_END",
31            "TEXT_CLIP_TYPE",
32            "TEXT_CLIP_NONE",
33            "TEXT_CLIP_MIN",
34            "TEXT_CLIP_MAX",
35            "TEXT_CLIP_BOTH",
36           ]
37
38 #------------------------------------------------------------------------------
39
40 class TEXT_BOUNDARY_TYPE(Enum):
41     _enum_lookup = {
42         0:'TEXT_BOUNDARY_CHAR',
43         1:'TEXT_BOUNDARY_WORD_START',
44         2:'TEXT_BOUNDARY_WORD_END',
45         3:'TEXT_BOUNDARY_SENTENCE_START',
46         4:'TEXT_BOUNDARY_SENTENCE_END',
47         5:'TEXT_BOUNDARY_LINE_START',
48         6:'TEXT_BOUNDARY_LINE_END',
49     }
50
51 TEXT_BOUNDARY_CHAR = TEXT_BOUNDARY_TYPE(0)
52 TEXT_BOUNDARY_LINE_END = TEXT_BOUNDARY_TYPE(6)
53 TEXT_BOUNDARY_LINE_START = TEXT_BOUNDARY_TYPE(5)
54 TEXT_BOUNDARY_SENTENCE_END = TEXT_BOUNDARY_TYPE(4)
55 TEXT_BOUNDARY_SENTENCE_START = TEXT_BOUNDARY_TYPE(3)
56 TEXT_BOUNDARY_WORD_END = TEXT_BOUNDARY_TYPE(2)
57 TEXT_BOUNDARY_WORD_START = TEXT_BOUNDARY_TYPE(1)
58
59 #------------------------------------------------------------------------------
60
61 class TEXT_CLIP_TYPE(Enum):
62     _enum_lookup = {
63         0:'TEXT_CLIP_NONE',
64         1:'TEXT_CLIP_MIN',
65         2:'TEXT_CLIP_MAX',
66         3:'TEXT_CLIP_BOTH',
67     }
68
69 TEXT_CLIP_BOTH = TEXT_CLIP_TYPE(3)
70 TEXT_CLIP_MAX = TEXT_CLIP_TYPE(2)
71 TEXT_CLIP_MIN = TEXT_CLIP_TYPE(1)
72 TEXT_CLIP_NONE = TEXT_CLIP_TYPE(0)
73
74 #------------------------------------------------------------------------------
75
76 class Text(BaseProxy):
77     """
78     The text interface should be implemented by objects which place
79     textual information onscreen as character strings or glyphs.
80     The text interface allows access to textual content, including
81     display attributes and semantic hints associated with runs of
82     text, and access to bounding box information for glyphs and substrings.
83     It also allows portions of textual content to be selected, if
84     the object's StateSet includes STATE_SELECTABLE_TEXT.
85     In some cases a Text object may have, as its content, an empty
86     string. In particular this can occur in the case of Hypertext
87     objects which do not display explicitly textual information onscreen,
88     as Hypertext is derived from the Text interface. 
89     Typographic and semantic attributes of onscreen textual content,
90     for instance typeface, weight, language, and such qualities as
91     'emphasis' or 'blockquote', are represented as text attributes.
92     Contiguous sequences of characters over which these attributes
93     are unchanged are referred to as "attribute runs", and are available
94     via Text::getAttributeRun. Where possible, implementing clients
95     will report textual attributes which are the same over the entire
96     text object, for instance those inherited from a default or document-scope
97     style, via getDefaultAttributes instead of reporting them explicitly
98     for each character. Therefore, for any span of text, the attributes
99     in effect are the union of the set returned by Text::getDefaultAttributes,
100     and the set returned at a particular character offset via Text::getAttributeRun.
101     """
102     
103     
104     def addSelection(self, *args, **kwargs):
105         """
106         The result of calling addSelection on objects which already have
107         one selection present, and which do not include STATE_MULTISELECTABLE,
108         is undefined, other than the return value. 
109         @return True of the selection was successfully added, False otherwise.
110         Selection may fail if the object does not support selection of
111         text (see STATE_SELECTABLE_TEXT), if the object does not support
112         multiple selections and a selection is already defined, or for
113         other reasons (for instance if the user does not have permission
114         to copy the text into the relevant selection buffer).
115         """
116         func = self.get_dbus_method("addSelection")
117         return func(*args, **kwargs)
118     
119     def getAttributeRun(self, *args, **kwargs):
120         """
121         Query a particular text object for the text attributes defined
122         at a given offset, obtaining the start and end of the "attribute
123         run" over which these attributes are currently invariant. Text
124         attributes are those presentational, typographic, or semantic
125         attributes or qualitites which apply to a range of text specifyable
126         by starting and ending offsets. Attributes relevant to localization
127         should be provided in accordance with the w3c "Internationalization
128         and Localization Markup Requirements", http://www.w3.org/TR/2005/WD-itsreq-20051122/
129         Other text attributes should choose their names and value semantics
130         in accordance with relevant standards such as CSS level 2 (http://www.w3.org/TR/1998/REC-CSS2-19980512),
131         XHTML 1.0 (http://www.w3.org/TR/2002/REC-xhtml1-20020801), and
132         WICD (http://www.w3.org/TR/2005/WD-WICD-20051121/). Those attributes
133         from the aforementioned specifications and recommendations which
134         do not concern typographic, presentational, or semantic aspects
135         of text should be exposed via the more general Accessible::getAttributes()
136         API (if at all).
137         For example, CSS attributes which should be exposed on text (either
138         as default attributes, or as explicitly-set attributes when non-default
139         values are specified in the content view) include the Font attributes
140         (i.e. "css2:font-weight", "css2:font-style"), the "css2:color"
141         and "css2:background-color" attributes, and "css2:text-decoration"
142         attribute.
143         If includeDefaults is TRUE, then this AttributeSet should include
144         the default attributes as well as those which are explicitly
145         assigned to the attribute run in question. startOffset and endOffset
146         will be back-filled to indicate the start and end of the attribute
147         run which contains 'offset' - an attribute run is a contiguous
148         section of text whose attributes are homogeneous. 
149         @param : offset
150         the offset of the character whose attributes will be reported.
151         @param : startOffset
152         backfilled with the starting offset of the character range over
153         which all text attributes match those of offset, i.e. the start
154         of the homogeneous attribute run including offset. 
155         @param : endOffset
156         backfilled with the offset of the first character past the character
157         range over which all text attributes match those of offset, i.e.
158         the character immediately after the homogeneous attribute run
159         including offset. 
160         @param : includeDefaults
161         if False, the call should only return those attributes which
162         are explicitly set on the current attribute run, omitting any
163         attributes which are inherited from the default values. See also
164         Text::getDefaultAttributes.
165         @return the AttributeSet defined at offset, optionally including
166         the 'default' attributes.
167         """
168         func = self.get_dbus_method("getAttributeRun")
169         return func(*args, **kwargs)
170     
171     def getAttributeValue(self, *args, **kwargs):
172         """
173         Get the string value of a named attribute at a given offset,
174         if defined. 
175         @param : offset
176         the offset of the character for which the attribute run is to
177         be obtained. 
178         @param : attributeName
179         the name of the attribute for which the value is to be returned,
180         if defined. 
181         @param : startOffset
182         back-filled with the offset of the first character in the attribute
183         run containing the character at offset. 
184         @param : endOffset
185         back-filled with the offset of the first character past the end
186         of the attribute run containing the character at offset. 
187         @param : defined
188         back-filled with True if the attributeName has a defined value
189         at offset, False otherwise. 
190         @return the value of attribute (name-value pair) corresponding
191         to "name", if defined.
192         """
193         func = self.get_dbus_method("getAttributeValue")
194         return func(*args, **kwargs)
195     
196     def getAttributes(self, offset):
197         """
198         getAttributes is deprecated in favor of getAttributeRun. 
199         @return the attributes at offset, as a semicolon-delimited set
200         of colon-delimited name-value pairs.
201         """
202         func = self.get_dbus_method("getAttributes")
203         return func(dbus.Int32(offset))
204     
205     def getBoundedRanges(self, *args, **kwargs):
206         """
207         Return the text content within a bounding box, as a list of Range
208         structures. Depending on the TEXT_CLIP_TYPE parameters, glyphs
209         which are clipped by the bounding box (i.e. which lie partially
210         inside and partially outside it) may or may not be included in
211         the ranges returned. 
212         @param : x
213         the minimum x ( i.e. leftmost) coordinate of the bounding box.
214         @param : y
215         the minimum y coordinate of the bounding box. 
216         @param : width
217         the horizontal size of the bounding box. The rightmost bound
218         of the bounding box is (x + width); 
219         @param : height
220         the vertical size of the bounding box. The maximum y value of
221         the bounding box is (y + height); 
222         @param : coordType
223         If 0, the above coordinates are interpreted as pixels relative
224         to corner of the screen; if 1, the coordinates are interpreted
225         as pixels relative to the corner of the containing toplevel window.
226         @param : xClipType
227         determines whether text which intersects the bounding box in
228         the x direction is included. 
229         @param : yClipType
230         determines whether text which intersects the bounding box in
231         the y direction is included.
232         """
233         func = self.get_dbus_method("getBoundedRanges")
234         return func(*args, **kwargs)
235     
236     def getCharacterAtOffset(self, *args, **kwargs):
237         """
238         @return an unsigned long integer whose value corresponds to the
239         UCS-4 representation of the character at the specified text offset,
240         or 0 if offset is out of range.
241         """
242         func = self.get_dbus_method("getCharacterAtOffset")
243         return func(*args, **kwargs)
244     
245     def getCharacterExtents(self, *args, **kwargs):
246         """
247         Obtain a the bounding box, as x, y, width, and height, of the
248         character or glyph at a particular character offset in this object's
249         text content. The coordinate system in which the results are
250         reported is specified by coordType. If an onscreen glyph corresponds
251         to multiple character offsets, for instance if the glyph is a
252         ligature, the bounding box reported will include the entire glyph
253         and therefore may apply to more than one character offset. 
254         @param : offset
255         the character offset of the character or glyph being queried.
256         @param : x
257         the minimum horizontal coordinate of the bounding box of the
258         glyph representing the character at offset. 
259         @param : y
260         the minimum vertical coordinate of the bounding box of the glyph
261         representing the character at offset. 
262         @param : width
263         the horizontal extent of the bounding box of the glyph representing
264         the character at offset. 
265         @param : height
266         the vertical extent of the bounding box of the glyph representing
267         the character at offset. 
268         @param : coordType
269         If 0, the results will be reported in screen coordinates, i.e.
270         in pixels relative to the upper-left corner of the screen, with
271         the x axis pointing right and the y axis pointing down. If 1,
272         the results will be reported relative to the containing toplevel
273         window, with the x axis pointing right and the y axis pointing
274         down.
275         """
276         func = self.get_dbus_method("getCharacterExtents")
277         return func(*args, **kwargs)
278     
279     def getDefaultAttributeSet(self, *args, **kwargs):
280         """
281         Return an AttributeSet containing the text attributes which apply
282         to all text in the object by virtue of the default settings of
283         the document, view, or user agent; e.g. those attributes which
284         are implied rather than explicitly applied to the text object.
285         For instance, an object whose entire text content has been explicitly
286         marked as 'bold' will report the 'bold' attribute via getAttributeRun(),
287         whereas an object whose text weight is inspecified may report
288         the default or implied text weight in the default AttributeSet.
289         """
290         func = self.get_dbus_method("getDefaultAttributeSet")
291         return func(*args, **kwargs)
292     
293     def getDefaultAttributes(self, *args, **kwargs):
294         """
295         Deprecated in favor of getDefaultAttributeSet. 
296         @return the attributes which apply to the entire text content,
297         but which were not explicitly specified by the content creator.
298         """
299         func = self.get_dbus_method("getDefaultAttributes")
300         return func(*args, **kwargs)
301     
302     def getNSelections(self, *args, **kwargs):
303         """
304         Obtain the number of separate, contiguous selections in the current
305         Text object. Text objects which do not implement selection of
306         discontiguous text regions will always return '0' or '1'. Note
307         that "contiguous" is defined by continuity of the offsets, i.e.
308         a text 'selection' is defined by a start/end offset pair. In
309         the case of bidirectional text, this means that a continguous
310         selection may appear visually discontiguous, and vice-versa.
311         @return the number of contiguous selections in the current Text
312         object.
313         """
314         func = self.get_dbus_method("getNSelections")
315         return func(*args, **kwargs)
316     
317     def getOffsetAtPoint(self, *args, **kwargs):
318         """
319         Get the offset of the character at a given onscreen coordinate.
320         The coordinate system used to interpret x and y is determined
321         by parameter coordType. 
322         @param : x
323         @param : y
324         @param : coordType
325         if 0, the input coordinates are interpreted relative to the entire
326         screen, if 1, they are relative to the toplevel window containing
327         this Text object. 
328         @return the text offset (as an offset into the character array)
329         of the glyph whose onscreen bounds contain the point x,y, or
330         -1 if the point is outside the bounds of any glyph.
331         """
332         func = self.get_dbus_method("getOffsetAtPoint")
333         return func(*args, **kwargs)
334     
335     def getRangeExtents(self, *args, **kwargs):
336         """
337         Obtain the bounding box which entirely contains a given text
338         range. Negative values may be returned for the bounding box parameters
339         in the event that all or part of the text range is offscreen
340         or not mapped to the screen. 
341         @param : startOffset
342         the offset of the first character in the specified range. 
343         @param : endOffset
344         the offset of the character immediately after the last character
345         in the specified range. 
346         @param : x
347         an integer parameter which is back-filled with the minimum horizontal
348         coordinate of the resulting bounding box. 
349         @param : y
350         an integer parameter which is back-filled with the minimum vertical
351         coordinate of the resulting bounding box. 
352         @param : width
353         an integer parameter which is back-filled with the horizontal
354         extent of the bounding box. 
355         @param : height
356         an integer parameter which is back-filled with the vertical extent
357         of the bounding box. 
358         @param : coordType
359         If 0, the above coordinates are reported in pixels relative to
360         corner of the screen; if 1, the coordinates are reported relative
361         to the corner of the containing toplevel window.
362         """
363         func = self.get_dbus_method("getRangeExtents")
364         return func(*args, **kwargs)
365     
366     def getSelection(self, *args, **kwargs):
367         """
368         The result of calling getSelection with an out-of-range selectionNum
369         (i.e. for a selection which does not exist) is not strictly defined,
370         but should set endOffset equal to startOffset.
371         """
372         func = self.get_dbus_method("getSelection")
373         return func(*args, **kwargs)
374     
375     def getText(self, startOffset, endOffset):
376         """
377         Obtain all or part of the onscreen textual content of a Text
378         object. If endOffset is specified as "-1", then this method will
379         return the entire onscreen textual contents of the Text object.
380         @return the textual content of the current Text object beginning
381         startOffset (inclusive) up to but not including the character
382         at endOffset.
383         """
384         func = self.get_dbus_method("getText")
385         if not endOffset:
386                 endOffset = -1
387         return func(dbus.Int32(startOffset), dbus.Int32(endOffset))
388     
389     def getTextAfterOffset(self, *args, **kwargs):
390         """
391         Obtain a subset of the text content of an object which entirely
392         follows offset, delimited by character, word, line, or sentence
393         boundaries as specified by type. The starting and ending offsets
394         of the resulting substring are returned in startOffset and endOffset.
395         By definition, if such a substring exists, startOffset must be
396         greater than offset. 
397         @param : offset
398         the offset from which the substring search begins, and which
399         must lie before the returned substring. 
400         @param : type
401         the text-boundary delimiter which determines whether the returned
402         text constitures a character, word, line, or sentence (and possibly
403         attendant whitespace), and whether the start or ending of such
404         a substring forms the boundary condition. 
405         @param : startOffset
406         back-filled with the starting offset of the resulting substring,
407         if one exists. 
408         @param : endOffset
409         back-filled with the offset of the character immediately following
410         the resulting substring, if one exists. 
411         @return a string which is a substring of the text content of
412         the object, delimited by the specified boundary condition.
413         """
414         func = self.get_dbus_method("getTextAfterOffset")
415         return func(*args, **kwargs)
416     
417     def getTextAtOffset(self, *args, **kwargs):
418         """
419         Obtain a subset of the text content of an object which includes
420         the specified offset, delimited by character, word, line, or
421         sentence boundaries as specified by type. The starting and ending
422         offsets of the resulting substring are returned in startOffset
423         and endOffset. 
424         @param : offset
425         the offset from which the substring search begins, and which
426         must lie within the returned substring. 
427         @param : type
428         the text-boundary delimiter which determines whether the returned
429         text constitures a character, word, line, or sentence (and possibly
430         attendant whitespace), and whether the start or ending of such
431         a substring forms the boundary condition. 
432         @param : startOffset
433         back-filled with the starting offset of the resulting substring,
434         if one exists. 
435         @param : endOffset
436         back-filled with the offset of the character immediately following
437         the resulting substring, if one exists. 
438         @return a string which is a substring of the text content of
439         the object, delimited by the specified boundary condition.
440         """
441         func = self.get_dbus_method("getTextAtOffset")
442         return func(*args, **kwargs)
443     
444     def getTextBeforeOffset(self, *args, **kwargs):
445         """
446         Obtain a subset of the text content of an object which entirely
447         precedes offset, delimited by character, word, line, or sentence
448         boundaries as specified by type. The starting and ending offsets
449         of the resulting substring are returned in startOffset and endOffset.
450         By definition, if such a substring exists, endOffset is less
451         than or equal to offset. 
452         @param : offset
453         the offset from which the substring search begins. 
454         @param : type
455         the text-boundary delimiter which determines whether the returned
456         text constitures a character, word, line, or sentence (and possibly
457         attendant whitespace), and whether the start or ending of such
458         a substring forms the boundary condition. 
459         @param : startOffset
460         back-filled with the starting offset of the resulting substring,
461         if one exists. 
462         @param : endOffset
463         back-filled with the offset of the character immediately following
464         the resulting substring, if one exists. 
465         @return a string which is a substring of the text content of
466         the object, delimited by the specified boundary condition.
467         """
468         func = self.get_dbus_method("getTextBeforeOffset")
469         return func(*args, **kwargs)
470     
471     def removeSelection(self, *args, **kwargs):
472         """
473         Deselect the text contained in the specified selectionNum, if
474         such a selection exists, otherwise do nothing. Removal of a non-existant
475         selectionNum has no effect. 
476         @return True if the selection was successfully removed, False
477         otherwise.
478         """
479         func = self.get_dbus_method("removeSelection")
480         return func(*args, **kwargs)
481     
482     def setCaretOffset(self, *args, **kwargs):
483         """
484         Programmatically move the text caret (visible or virtual, as
485         above) to a given position. 
486         @param : offset
487         a long int indicating the desired character offset. Not all implementations
488         of Text will honor setCaretOffset requests, so the return value
489         below should be checked by the client. 
490         @return TRUE if the request was carried out, or FALSE if the
491         caret could not be moved to the requested position.
492         """
493         func = self.get_dbus_method("setCaretOffset")
494         return func(*args, **kwargs)
495     
496     def setSelection(self, *args, **kwargs):
497         """
498         Modify an existing selection's start or ending offset.
499         Calling setSelection for a selectionNum that is not already defined
500         has no effect. The result of calling setSelection with a selectionNum
501         greater than 0 for objects that do not include STATE_MULTISELECTABLE
502         is undefined. 
503         @param : selectionNum
504         indicates which of a set of non-contiguous selections to modify.
505         @param : startOffset
506         the new starting offset for the selection 
507         @param : endOffset
508         the new ending offset for the selection 
509         @return True if the selection corresponding to selectionNum is
510         successfully modified, False otherwise.
511         """
512         func = self.get_dbus_method("setSelection")
513         return func(*args, **kwargs)
514
515     def get_caretOffset(self):
516         return self._pgetter(self._dbus_interface, "caretOffset")
517     def set_caretOffset(self, value):
518         self._psetter(self._dbus_interface, "caretOffset", value)
519     _caretOffsetDoc = \
520         """
521         The current offset of the text caret in the Text object. This
522         caret may be virtual, e.g. non-visual and notional-only, but
523         if an onscreen representation of the caret position is visible,
524         it will correspond to this offset. The caret offset is given
525         as a character offset, as opposed to a byte offset into a text
526         buffer or a column offset.
527         """
528     caretOffset = property(fget=get_caretOffset, fset=set_caretOffset, doc=_caretOffsetDoc)
529     
530     def get_characterCount(self):
531         return self._pgetter(self._dbus_interface, "characterCount")
532     def set_characterCount(self, value):
533         self._psetter(self._dbus_interface, "characterCount", value)
534     _characterCountDoc = \
535         """
536         The total current number of characters in the Text object, including
537         whitespace and non-spacing characters.
538         """
539     characterCount = property(fget=get_characterCount, fset=set_characterCount, doc=_characterCountDoc)
540     
541     class Range(list):
542         def __new__(cls, startOffset, endOffset, content, data):
543             list.__new__(cls, (startOffset, endOffset, content, data))
544         def __init__(self, startOffset, endOffset, content, data):
545             list.__init__(self, (startOffset, endOffset, content, data))
546         
547         def _get_startOffset(self):
548             return self[0]
549         def _set_startOffset(self, val):
550             self[0] = val
551         startOffset = property(fget=_get_startOffset, fset=_set_startOffset)
552         def _get_endOffset(self):
553             return self[1]
554         def _set_endOffset(self, val):
555             self[1] = val
556         endOffset = property(fget=_get_endOffset, fset=_set_endOffset)
557         def _get_content(self):
558             return self[2]
559         def _set_content(self, val):
560             self[2] = val
561         content = property(fget=_get_content, fset=_set_content)
562         def _get_data(self):
563             return self[3]
564         def _set_data(self, val):
565             self[3] = val
566         data = property(fget=_get_data, fset=_set_data)
567
568 # ATTENTION - Register the Application class with the accessible factory.
569 add_accessible_class(interfaces.ATSPI_TEXT, Text)
570
571 #END----------------------------------------------------------------------------