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