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