1 #Copyright (C) 2008 Codethink Ltd
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.
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.
17 from interfaces import *
18 from accessible import Accessible
20 from factory import accessible_factory
26 "TEXT_BOUNDARY_WORD_START",
27 "TEXT_BOUNDARY_WORD_END",
28 "TEXT_BOUNDARY_SENTENCE_START",
29 "TEXT_BOUNDARY_SENTENCE_END",
30 "TEXT_BOUNDARY_LINE_START",
31 "TEXT_BOUNDARY_LINE_END",
39 #------------------------------------------------------------------------------
41 class TEXT_BOUNDARY_TYPE(Enum):
43 0:'TEXT_BOUNDARY_CHAR',
44 1:'TEXT_BOUNDARY_WORD_START',
45 2:'TEXT_BOUNDARY_WORD_END',
46 3:'TEXT_BOUNDARY_SENTENCE_START',
47 4:'TEXT_BOUNDARY_SENTENCE_END',
48 5:'TEXT_BOUNDARY_LINE_START',
49 6:'TEXT_BOUNDARY_LINE_END',
52 TEXT_BOUNDARY_CHAR = TEXT_BOUNDARY_TYPE(0)
53 TEXT_BOUNDARY_LINE_END = TEXT_BOUNDARY_TYPE(6)
54 TEXT_BOUNDARY_LINE_START = TEXT_BOUNDARY_TYPE(5)
55 TEXT_BOUNDARY_SENTENCE_END = TEXT_BOUNDARY_TYPE(4)
56 TEXT_BOUNDARY_SENTENCE_START = TEXT_BOUNDARY_TYPE(3)
57 TEXT_BOUNDARY_WORD_END = TEXT_BOUNDARY_TYPE(2)
58 TEXT_BOUNDARY_WORD_START = TEXT_BOUNDARY_TYPE(1)
60 #------------------------------------------------------------------------------
62 class TEXT_CLIP_TYPE(Enum):
70 TEXT_CLIP_BOTH = TEXT_CLIP_TYPE(3)
71 TEXT_CLIP_MAX = TEXT_CLIP_TYPE(2)
72 TEXT_CLIP_MIN = TEXT_CLIP_TYPE(1)
73 TEXT_CLIP_NONE = TEXT_CLIP_TYPE(0)
75 #------------------------------------------------------------------------------
77 class Text(Accessible):
79 The text interface should be implemented by objects which place
80 textual information onscreen as character strings or glyphs.
81 The text interface allows access to textual content, including
82 display attributes and semantic hints associated with runs of
83 text, and access to bounding box information for glyphs and substrings.
84 It also allows portions of textual content to be selected, if
85 the object's StateSet includes STATE_SELECTABLE_TEXT.
86 In some cases a Text object may have, as its content, an empty
87 string. In particular this can occur in the case of Hypertext
88 objects which do not display explicitly textual information onscreen,
89 as Hypertext is derived from the Text interface.
90 Typographic and semantic attributes of onscreen textual content,
91 for instance typeface, weight, language, and such qualities as
92 'emphasis' or 'blockquote', are represented as text attributes.
93 Contiguous sequences of characters over which these attributes
94 are unchanged are referred to as "attribute runs", and are available
95 via Text::getAttributeRun. Where possible, implementing clients
96 will report textual attributes which are the same over the entire
97 text object, for instance those inherited from a default or document-scope
98 style, via getDefaultAttributes instead of reporting them explicitly
99 for each character. Therefore, for any span of text, the attributes
100 in effect are the union of the set returned by Text::getDefaultAttributes,
101 and the set returned at a particular character offset via Text::getAttributeRun.
104 def addSelection(self, index):
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).
116 func = self.get_dbus_method("addSelection", dbus_interface=ATSPI_TEXT)
119 def getAttributeRun(self, offset):
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()
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"
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.
150 the offset of the character whose attributes will be reported.
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.
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
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.
168 func = self.get_dbus_method("getAttributeRun", dbus_interface=ATSPI_TEXT)
169 [attrs, startOffset, endOffset] = func(offset, includeDefaults)
170 dict = [key + ':' + value for key, value in attrs.values()]
171 return [dict, startOffset, endOffset]
173 def getAttributeValue(self, offset, attributeName):
175 Get the string value of a named attribute at a given offset,
178 the offset of the character for which the attribute run is to
180 @param : attributeName
181 the name of the attribute for which the value is to be returned,
184 back-filled with the offset of the first character in the attribute
185 run containing the character at offset.
187 back-filled with the offset of the first character past the end
188 of the attribute run containing the character at offset.
190 back-filled with True if the attributeName has a defined value
191 at offset, False otherwise.
192 @return the value of attribute (name-value pair) corresponding
193 to "name", if defined.
195 func = self.get_dbus_method("getAttributeValue", dbus_interface=ATSPI_TEXT)
196 return func(offset, attributeName)
198 def getAttributes(self, offset):
200 getAttributes is deprecated in favor of getAttributeRun.
201 @return the attributes at offset, as a semicolon-delimited set
202 of colon-delimited name-value pairs.
204 func = self.get_dbus_method("getAttributes", dbus_interface=ATSPI_TEXT)
205 [attrs, startOffset, endOffset] = func(dbus.Int32(offset))
206 dict = [key + ':' + value for key, value in attrs]
207 return [dict, startOffset, endOffset]
209 def getBoundedRanges(self, x, y, width, height, coordType, xClipType, yClipType):
210 #TODO Return a list of range structures
212 Return the text content within a bounding box, as a list of Range
213 structures. Depending on the TEXT_CLIP_TYPE parameters, glyphs
214 which are clipped by the bounding box (i.e. which lie partially
215 inside and partially outside it) may or may not be included in
218 the minimum x ( i.e. leftmost) coordinate of the bounding box.
220 the minimum y coordinate of the bounding box.
222 the horizontal size of the bounding box. The rightmost bound
223 of the bounding box is (x + width);
225 the vertical size of the bounding box. The maximum y value of
226 the bounding box is (y + height);
228 If 0, the above coordinates are interpreted as pixels relative
229 to corner of the screen; if 1, the coordinates are interpreted
230 as pixels relative to the corner of the containing toplevel window.
232 determines whether text which intersects the bounding box in
233 the x direction is included.
235 determines whether text which intersects the bounding box in
236 the y direction is included.
238 func = self.get_dbus_method("getBoundedRanges", dbus_interface=ATSPI_TEXT)
239 return func(x, y, width, height, coordType, xClipType, yClipType)
241 def getCharacterAtOffset(self, offset):
245 @return an unsigned long integer whose value corresponds to the
246 UCS-4 representation of the character at the specified text offset,
247 or 0 if offset is out of range.
249 func = self.get_dbus_method("getCharacterAtOffset", dbus_interface=ATSPI_TEXT)
252 def getCharacterExtents(self, offset, x, y, width, height, coordType):
254 Obtain a the bounding box, as x, y, width, and height, of the
255 character or glyph at a particular character offset in this object's
256 text content. The coordinate system in which the results are
257 reported is specified by coordType. If an onscreen glyph corresponds
258 to multiple character offsets, for instance if the glyph is a
259 ligature, the bounding box reported will include the entire glyph
260 and therefore may apply to more than one character offset.
262 the character offset of the character or glyph being queried.
264 the minimum horizontal coordinate of the bounding box of the
265 glyph representing the character at offset.
267 the minimum vertical coordinate of the bounding box of the glyph
268 representing the character at offset.
270 the horizontal extent of the bounding box of the glyph representing
271 the character at offset.
273 the vertical extent of the bounding box of the glyph representing
274 the character at offset.
276 If 0, the results will be reported in screen coordinates, i.e.
277 in pixels relative to the upper-left corner of the screen, with
278 the x axis pointing right and the y axis pointing down. If 1,
279 the results will be reported relative to the containing toplevel
280 window, with the x axis pointing right and the y axis pointing
283 func = self.get_dbus_method("getCharacterExtents", dbus_interface=ATSPI_TEXT)
284 return func(offset, x, y, width, height, coordType)
286 def getDefaultAttributeSet(self):
288 Return an AttributeSet containing the text attributes which apply
289 to all text in the object by virtue of the default settings of
290 the document, view, or user agent; e.g. those attributes which
291 are implied rather than explicitly applied to the text object.
292 For instance, an object whose entire text content has been explicitly
293 marked as 'bold' will report the 'bold' attribute via getAttributeRun(),
294 whereas an object whose text weight is inspecified may report
295 the default or implied text weight in the default AttributeSet.
297 func = self.get_dbus_method("getDefaultAttributeSet", dbus_interface=ATSPI_TEXT)
298 return [key + ':' + value for key, value in func().values()]
300 def getDefaultAttributes(self):
302 Deprecated in favor of getDefaultAttributeSet.
303 @return the attributes which apply to the entire text content,
304 but which were not explicitly specified by the content creator.
306 func = self.get_dbus_method("getDefaultAttributes", dbus_interface=ATSPI_TEXT)
307 return ';'.join([key + ':' + value for key, value in func().iteritems()])
309 def getNSelections(self):
311 Obtain the number of separate, contiguous selections in the current
312 Text object. Text objects which do not implement selection of
313 discontiguous text regions will always return '0' or '1'. Note
314 that "contiguous" is defined by continuity of the offsets, i.e.
315 a text 'selection' is defined by a start/end offset pair. In
316 the case of bidirectional text, this means that a continguous
317 selection may appear visually discontiguous, and vice-versa.
318 @return the number of contiguous selections in the current Text
321 func = self.get_dbus_method("getNSelections", dbus_interface=ATSPI_TEXT)
324 def getOffsetAtPoint(self, x, y, coordType):
326 Get the offset of the character at a given onscreen coordinate.
327 The coordinate system used to interpret x and y is determined
328 by parameter coordType.
332 if 0, the input coordinates are interpreted relative to the entire
333 screen, if 1, they are relative to the toplevel window containing
335 @return the text offset (as an offset into the character array)
336 of the glyph whose onscreen bounds contain the point x,y, or
337 -1 if the point is outside the bounds of any glyph.
339 func = self.get_dbus_method("getOffsetAtPoint", dbus_interface=ATSPI_TEXT)
340 return func(x, y, coordType)
342 def getRangeExtents(self, startOffset, endOffset, x, y, width, height, coordType):
344 Obtain the bounding box which entirely contains a given text
345 range. Negative values may be returned for the bounding box parameters
346 in the event that all or part of the text range is offscreen
347 or not mapped to the screen.
349 the offset of the first character in the specified range.
351 the offset of the character immediately after the last character
352 in the specified range.
354 an integer parameter which is back-filled with the minimum horizontal
355 coordinate of the resulting bounding box.
357 an integer parameter which is back-filled with the minimum vertical
358 coordinate of the resulting bounding box.
360 an integer parameter which is back-filled with the horizontal
361 extent of the bounding box.
363 an integer parameter which is back-filled with the vertical extent
366 If 0, the above coordinates are reported in pixels relative to
367 corner of the screen; if 1, the coordinates are reported relative
368 to the corner of the containing toplevel window.
370 func = self.get_dbus_method("getRangeExtents", dbus_interface=ATSPI_TEXT)
371 return func(startOffset, endOffset, x, y, width, height, coordType)
373 def getSelection(self, selectionNum):
375 The result of calling getSelection with an out-of-range selectionNum
376 (i.e. for a selection which does not exist) is not strictly defined,
377 but should set endOffset equal to startOffset.
378 @param : selectionNum
379 indicates which of a set of non-contiguous selections to modify.
381 back-filled with the starting offset of the resulting substring,
384 back-filled with the offset of the character immediately following
385 the resulting substring, if one exists.
387 func = self.get_dbus_method("getSelection", dbus_interface=ATSPI_TEXT)
388 return func(selectionNum)
390 def getText(self, startOffset, endOffset):
392 Obtain all or part of the onscreen textual content of a Text
393 object. If endOffset is specified as "-1", then this method will
394 return the entire onscreen textual contents of the Text object.
396 back-filled with the starting offset of the resulting substring,
399 back-filled with the offset of the character immediately following
400 the resulting substring, if one exists.
401 @return the textual content of the current Text object beginning
402 startOffset (inclusive) up to but not including the character
405 func = self.get_dbus_method("getText", dbus_interface=ATSPI_TEXT)
408 return func(dbus.Int32(startOffset), dbus.Int32(endOffset))
410 def getTextAfterOffset(self, offset, type):
412 Obtain a subset of the text content of an object which entirely
413 follows offset, delimited by character, word, line, or sentence
414 boundaries as specified by type. The starting and ending offsets
415 of the resulting substring are returned in startOffset and endOffset.
416 By definition, if such a substring exists, startOffset must be
419 the offset from which the substring search begins, and which
420 must lie before the returned substring.
422 the text-boundary delimiter which determines whether the returned
423 text constitures a character, word, line, or sentence (and possibly
424 attendant whitespace), and whether the start or ending of such
425 a substring forms the boundary condition.
427 back-filled with the starting offset of the resulting substring,
430 back-filled with the offset of the character immediately following
431 the resulting substring, if one exists.
432 @return a string which is a substring of the text content of
433 the object, delimited by the specified boundary condition.
435 func = self.get_dbus_method("getTextAfterOffset", dbus_interface=ATSPI_TEXT)
436 return func(offset, type)
438 def getTextAtOffset(self, offset, type):
440 Obtain a subset of the text content of an object which includes
441 the specified offset, delimited by character, word, line, or
442 sentence boundaries as specified by type. The starting and ending
443 offsets of the resulting substring are returned in startOffset
446 the offset from which the substring search begins, and which
447 must lie within the returned substring.
449 the text-boundary delimiter which determines whether the returned
450 text constitures a character, word, line, or sentence (and possibly
451 attendant whitespace), and whether the start or ending of such
452 a substring forms the boundary condition.
454 back-filled with the starting offset of the resulting substring,
457 back-filled with the offset of the character immediately following
458 the resulting substring, if one exists.
459 @return a string which is a substring of the text content of
460 the object, delimited by the specified boundary condition.
462 func = self.get_dbus_method("getTextAtOffset", dbus_interface=ATSPI_TEXT)
463 return func(offset, type)
465 def getTextBeforeOffset(self, offset, type):
467 Obtain a subset of the text content of an object which entirely
468 precedes offset, delimited by character, word, line, or sentence
469 boundaries as specified by type. The starting and ending offsets
470 of the resulting substring are returned in startOffset and endOffset.
471 By definition, if such a substring exists, endOffset is less
472 than or equal to offset.
474 the offset from which the substring search begins.
476 the text-boundary delimiter which determines whether the returned
477 text constitures a character, word, line, or sentence (and possibly
478 attendant whitespace), and whether the start or ending of such
479 a substring forms the boundary condition.
481 back-filled with the starting offset of the resulting substring,
484 back-filled with the offset of the character immediately following
485 the resulting substring, if one exists.
486 @return a string which is a substring of the text content of
487 the object, delimited by the specified boundary condition.
489 func = self.get_dbus_method("getTextBeforeOffset", dbus_interface=ATSPI_TEXT)
490 return func(offset, type)
492 def removeSelection(self, selectionNum):
494 Deselect the text contained in the specified selectionNum, if
495 such a selection exists, otherwise do nothing. Removal of a non-existant
496 selectionNum has no effect.
497 @param : selectionNum
498 indicates which of a set of non-contiguous selections to modify.
499 @return True if the selection was successfully removed, False
502 func = self.get_dbus_method("removeSelection", dbus_interface=ATSPI_TEXT)
503 return func(selectionNum)
505 def setCaretOffset(self, offset):
507 Programmatically move the text caret (visible or virtual, as
508 above) to a given position.
510 a long int indicating the desired character offset. Not all implementations
511 of Text will honor setCaretOffset requests, so the return value
512 below should be checked by the client.
513 @return TRUE if the request was carried out, or FALSE if the
514 caret could not be moved to the requested position.
516 func = self.get_dbus_method("setCaretOffset", dbus_interface=ATSPI_TEXT)
519 def setSelection(self, selectionNum, startOffset, endOffset):
521 Modify an existing selection's start or ending offset.
522 Calling setSelection for a selectionNum that is not already defined
523 has no effect. The result of calling setSelection with a selectionNum
524 greater than 0 for objects that do not include STATE_MULTISELECTABLE
526 @param : selectionNum
527 indicates which of a set of non-contiguous selections to modify.
529 the new starting offset for the selection
531 the new ending offset for the selection
532 @return True if the selection corresponding to selectionNum is
533 successfully modified, False otherwise.
535 func = self.get_dbus_method("setSelection", dbus_interface=ATSPI_TEXT)
536 return func(selectionNum, startOffset, endOffset)
538 def get_caretOffset(self):
539 return dbus.Int32(self._pgetter(self._dbus_interface, "caretOffset"))
542 The current offset of the text caret in the Text object. This
543 caret may be virtual, e.g. non-visual and notional-only, but
544 if an onscreen representation of the caret position is visible,
545 it will correspond to this offset. The caret offset is given
546 as a character offset, as opposed to a byte offset into a text
547 buffer or a column offset.
549 caretOffset = property(fget=get_caretOffset, doc=_caretOffsetDoc)
551 def get_characterCount(self):
552 return dbus.Int32(self._pgetter(self._dbus_interface, "characterCount"))
553 _characterCountDoc = \
555 The total current number of characters in the Text object, including
556 whitespace and non-spacing characters.
558 characterCount = property(fget=get_characterCount, doc=_characterCountDoc)
561 def __new__(cls, startOffset, endOffset, content, data):
562 list.__new__(cls, (startOffset, endOffset, content, data))
563 def __init__(self, startOffset, endOffset, content, data):
564 list.__init__(self, (startOffset, endOffset, content, data))
566 def _get_startOffset(self):
568 def _set_startOffset(self, val):
570 startOffset = property(fget=_get_startOffset, fset=_set_startOffset)
571 def _get_endOffset(self):
573 def _set_endOffset(self, val):
575 endOffset = property(fget=_get_endOffset, fset=_set_endOffset)
576 def _get_content(self):
578 def _set_content(self, val):
580 content = property(fget=_get_content, fset=_set_content)
583 def _set_data(self, val):
585 data = property(fget=_get_data, fset=_set_data)
587 # Register the accessible class with the factory.
588 accessible_factory.register_accessible_class(ATSPI_TEXT, Text)
590 #END----------------------------------------------------------------------------