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 [attributes, startOffset, endOffset] = func(values)
308 return [[key + ':' + value for key, value in func().values()], startOffset, endOffset]
310 def getNSelections(self):
312 Obtain the number of separate, contiguous selections in the current
313 Text object. Text objects which do not implement selection of
314 discontiguous text regions will always return '0' or '1'. Note
315 that "contiguous" is defined by continuity of the offsets, i.e.
316 a text 'selection' is defined by a start/end offset pair. In
317 the case of bidirectional text, this means that a continguous
318 selection may appear visually discontiguous, and vice-versa.
319 @return the number of contiguous selections in the current Text
322 func = self.get_dbus_method("getNSelections", dbus_interface=ATSPI_TEXT)
325 def getOffsetAtPoint(self, x, y, coordType):
327 Get the offset of the character at a given onscreen coordinate.
328 The coordinate system used to interpret x and y is determined
329 by parameter coordType.
333 if 0, the input coordinates are interpreted relative to the entire
334 screen, if 1, they are relative to the toplevel window containing
336 @return the text offset (as an offset into the character array)
337 of the glyph whose onscreen bounds contain the point x,y, or
338 -1 if the point is outside the bounds of any glyph.
340 func = self.get_dbus_method("getOffsetAtPoint", dbus_interface=ATSPI_TEXT)
341 return func(x, y, coordType)
343 def getRangeExtents(self, startOffset, endOffset, x, y, width, height, coordType):
345 Obtain the bounding box which entirely contains a given text
346 range. Negative values may be returned for the bounding box parameters
347 in the event that all or part of the text range is offscreen
348 or not mapped to the screen.
350 the offset of the first character in the specified range.
352 the offset of the character immediately after the last character
353 in the specified range.
355 an integer parameter which is back-filled with the minimum horizontal
356 coordinate of the resulting bounding box.
358 an integer parameter which is back-filled with the minimum vertical
359 coordinate of the resulting bounding box.
361 an integer parameter which is back-filled with the horizontal
362 extent of the bounding box.
364 an integer parameter which is back-filled with the vertical extent
367 If 0, the above coordinates are reported in pixels relative to
368 corner of the screen; if 1, the coordinates are reported relative
369 to the corner of the containing toplevel window.
371 func = self.get_dbus_method("getRangeExtents", dbus_interface=ATSPI_TEXT)
372 return func(startOffset, endOffset, x, y, width, height, coordType)
374 def getSelection(self, selectionNum):
376 The result of calling getSelection with an out-of-range selectionNum
377 (i.e. for a selection which does not exist) is not strictly defined,
378 but should set endOffset equal to startOffset.
379 @param : selectionNum
380 indicates which of a set of non-contiguous selections to modify.
382 back-filled with the starting offset of the resulting substring,
385 back-filled with the offset of the character immediately following
386 the resulting substring, if one exists.
388 func = self.get_dbus_method("getSelection", dbus_interface=ATSPI_TEXT)
389 return func(selectionNum)
391 def getText(self, startOffset, endOffset):
393 Obtain all or part of the onscreen textual content of a Text
394 object. If endOffset is specified as "-1", then this method will
395 return the entire onscreen textual contents of the Text object.
397 back-filled with the starting offset of the resulting substring,
400 back-filled with the offset of the character immediately following
401 the resulting substring, if one exists.
402 @return the textual content of the current Text object beginning
403 startOffset (inclusive) up to but not including the character
406 func = self.get_dbus_method("getText", dbus_interface=ATSPI_TEXT)
409 return func(dbus.Int32(startOffset), dbus.Int32(endOffset))
411 def getTextAfterOffset(self, offset, type):
413 Obtain a subset of the text content of an object which entirely
414 follows offset, delimited by character, word, line, or sentence
415 boundaries as specified by type. The starting and ending offsets
416 of the resulting substring are returned in startOffset and endOffset.
417 By definition, if such a substring exists, startOffset must be
420 the offset from which the substring search begins, and which
421 must lie before the returned substring.
423 the text-boundary delimiter which determines whether the returned
424 text constitures a character, word, line, or sentence (and possibly
425 attendant whitespace), and whether the start or ending of such
426 a substring forms the boundary condition.
428 back-filled with the starting offset of the resulting substring,
431 back-filled with the offset of the character immediately following
432 the resulting substring, if one exists.
433 @return a string which is a substring of the text content of
434 the object, delimited by the specified boundary condition.
436 func = self.get_dbus_method("getTextAfterOffset", dbus_interface=ATSPI_TEXT)
437 return func(offset, type)
439 def getTextAtOffset(self, offset, type):
441 Obtain a subset of the text content of an object which includes
442 the specified offset, delimited by character, word, line, or
443 sentence boundaries as specified by type. The starting and ending
444 offsets of the resulting substring are returned in startOffset
447 the offset from which the substring search begins, and which
448 must lie within the returned substring.
450 the text-boundary delimiter which determines whether the returned
451 text constitures a character, word, line, or sentence (and possibly
452 attendant whitespace), and whether the start or ending of such
453 a substring forms the boundary condition.
455 back-filled with the starting offset of the resulting substring,
458 back-filled with the offset of the character immediately following
459 the resulting substring, if one exists.
460 @return a string which is a substring of the text content of
461 the object, delimited by the specified boundary condition.
463 func = self.get_dbus_method("getTextAtOffset", dbus_interface=ATSPI_TEXT)
464 return func(offset, type)
466 def getTextBeforeOffset(self, offset, type):
468 Obtain a subset of the text content of an object which entirely
469 precedes offset, delimited by character, word, line, or sentence
470 boundaries as specified by type. The starting and ending offsets
471 of the resulting substring are returned in startOffset and endOffset.
472 By definition, if such a substring exists, endOffset is less
473 than or equal to offset.
475 the offset from which the substring search begins.
477 the text-boundary delimiter which determines whether the returned
478 text constitures a character, word, line, or sentence (and possibly
479 attendant whitespace), and whether the start or ending of such
480 a substring forms the boundary condition.
482 back-filled with the starting offset of the resulting substring,
485 back-filled with the offset of the character immediately following
486 the resulting substring, if one exists.
487 @return a string which is a substring of the text content of
488 the object, delimited by the specified boundary condition.
490 func = self.get_dbus_method("getTextBeforeOffset", dbus_interface=ATSPI_TEXT)
491 return func(offset, type)
493 def removeSelection(self, selectionNum):
495 Deselect the text contained in the specified selectionNum, if
496 such a selection exists, otherwise do nothing. Removal of a non-existant
497 selectionNum has no effect.
498 @param : selectionNum
499 indicates which of a set of non-contiguous selections to modify.
500 @return True if the selection was successfully removed, False
503 func = self.get_dbus_method("removeSelection", dbus_interface=ATSPI_TEXT)
504 return func(selectionNum)
506 def setCaretOffset(self, offset):
508 Programmatically move the text caret (visible or virtual, as
509 above) to a given position.
511 a long int indicating the desired character offset. Not all implementations
512 of Text will honor setCaretOffset requests, so the return value
513 below should be checked by the client.
514 @return TRUE if the request was carried out, or FALSE if the
515 caret could not be moved to the requested position.
517 func = self.get_dbus_method("setCaretOffset", dbus_interface=ATSPI_TEXT)
520 def setSelection(self, selectionNum, startOffset, endOffset):
522 Modify an existing selection's start or ending offset.
523 Calling setSelection for a selectionNum that is not already defined
524 has no effect. The result of calling setSelection with a selectionNum
525 greater than 0 for objects that do not include STATE_MULTISELECTABLE
527 @param : selectionNum
528 indicates which of a set of non-contiguous selections to modify.
530 the new starting offset for the selection
532 the new ending offset for the selection
533 @return True if the selection corresponding to selectionNum is
534 successfully modified, False otherwise.
536 func = self.get_dbus_method("setSelection", dbus_interface=ATSPI_TEXT)
537 return func(selectionNum, startOffset, endOffset)
539 def get_caretOffset(self):
540 return dbus.Int32(self._pgetter(self._dbus_interface, "caretOffset"))
543 The current offset of the text caret in the Text object. This
544 caret may be virtual, e.g. non-visual and notional-only, but
545 if an onscreen representation of the caret position is visible,
546 it will correspond to this offset. The caret offset is given
547 as a character offset, as opposed to a byte offset into a text
548 buffer or a column offset.
550 caretOffset = property(fget=get_caretOffset, doc=_caretOffsetDoc)
552 def get_characterCount(self):
553 return dbus.Int32(self._pgetter(self._dbus_interface, "characterCount"))
554 _characterCountDoc = \
556 The total current number of characters in the Text object, including
557 whitespace and non-spacing characters.
559 characterCount = property(fget=get_characterCount, doc=_characterCountDoc)
562 def __new__(cls, startOffset, endOffset, content, data):
563 list.__new__(cls, (startOffset, endOffset, content, data))
564 def __init__(self, startOffset, endOffset, content, data):
565 list.__init__(self, (startOffset, endOffset, content, data))
567 def _get_startOffset(self):
569 def _set_startOffset(self, val):
571 startOffset = property(fget=_get_startOffset, fset=_set_startOffset)
572 def _get_endOffset(self):
574 def _set_endOffset(self, val):
576 endOffset = property(fget=_get_endOffset, fset=_set_endOffset)
577 def _get_content(self):
579 def _set_content(self, val):
581 content = property(fget=_get_content, fset=_set_content)
584 def _set_data(self, val):
586 data = property(fget=_get_data, fset=_set_data)
588 # Register the accessible class with the factory.
589 accessible_factory.register_accessible_class(ATSPI_TEXT, Text)
591 #END----------------------------------------------------------------------------