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
22 from dbus.types import UInt32
28 "TEXT_BOUNDARY_WORD_START",
29 "TEXT_BOUNDARY_WORD_END",
30 "TEXT_BOUNDARY_SENTENCE_START",
31 "TEXT_BOUNDARY_SENTENCE_END",
32 "TEXT_BOUNDARY_LINE_START",
33 "TEXT_BOUNDARY_LINE_END",
41 #------------------------------------------------------------------------------
43 class TEXT_BOUNDARY_TYPE(Enum):
45 0:'TEXT_BOUNDARY_CHAR',
46 1:'TEXT_BOUNDARY_WORD_START',
47 2:'TEXT_BOUNDARY_WORD_END',
48 3:'TEXT_BOUNDARY_SENTENCE_START',
49 4:'TEXT_BOUNDARY_SENTENCE_END',
50 5:'TEXT_BOUNDARY_LINE_START',
51 6:'TEXT_BOUNDARY_LINE_END',
54 TEXT_BOUNDARY_CHAR = TEXT_BOUNDARY_TYPE(0)
55 TEXT_BOUNDARY_LINE_END = TEXT_BOUNDARY_TYPE(6)
56 TEXT_BOUNDARY_LINE_START = TEXT_BOUNDARY_TYPE(5)
57 TEXT_BOUNDARY_SENTENCE_END = TEXT_BOUNDARY_TYPE(4)
58 TEXT_BOUNDARY_SENTENCE_START = TEXT_BOUNDARY_TYPE(3)
59 TEXT_BOUNDARY_WORD_END = TEXT_BOUNDARY_TYPE(2)
60 TEXT_BOUNDARY_WORD_START = TEXT_BOUNDARY_TYPE(1)
62 #------------------------------------------------------------------------------
64 class TEXT_CLIP_TYPE(Enum):
72 TEXT_CLIP_BOTH = TEXT_CLIP_TYPE(3)
73 TEXT_CLIP_MAX = TEXT_CLIP_TYPE(2)
74 TEXT_CLIP_MIN = TEXT_CLIP_TYPE(1)
75 TEXT_CLIP_NONE = TEXT_CLIP_TYPE(0)
77 #------------------------------------------------------------------------------
79 class Text(Accessible):
81 The text interface should be implemented by objects which place
82 textual information onscreen as character strings or glyphs.
83 The text interface allows access to textual content, including
84 display attributes and semantic hints associated with runs of
85 text, and access to bounding box information for glyphs and substrings.
86 It also allows portions of textual content to be selected, if
87 the object's StateSet includes STATE_SELECTABLE_TEXT.
88 In some cases a Text object may have, as its content, an empty
89 string. In particular this can occur in the case of Hypertext
90 objects which do not display explicitly textual information onscreen,
91 as Hypertext is derived from the Text interface.
92 Typographic and semantic attributes of onscreen textual content,
93 for instance typeface, weight, language, and such qualities as
94 'emphasis' or 'blockquote', are represented as text attributes.
95 Contiguous sequences of characters over which these attributes
96 are unchanged are referred to as "attribute runs", and are available
97 via Text::getAttributeRun. Where possible, implementing clients
98 will report textual attributes which are the same over the entire
99 text object, for instance those inherited from a default or document-scope
100 style, via getDefaultAttributes instead of reporting them explicitly
101 for each character. Therefore, for any span of text, the attributes
102 in effect are the union of the set returned by Text::getDefaultAttributes,
103 and the set returned at a particular character offset via Text::getAttributeRun.
106 def addSelection(self, index):
108 The result of calling addSelection on objects which already have
109 one selection present, and which do not include STATE_MULTISELECTABLE,
110 is undefined, other than the return value.
111 @return True of the selection was successfully added, False otherwise.
112 Selection may fail if the object does not support selection of
113 text (see STATE_SELECTABLE_TEXT), if the object does not support
114 multiple selections and a selection is already defined, or for
115 other reasons (for instance if the user does not have permission
116 to copy the text into the relevant selection buffer).
118 func = self.get_dbus_method("addSelection", dbus_interface=ATSPI_TEXT)
121 def getAttributeRun(self, offset):
123 Query a particular text object for the text attributes defined
124 at a given offset, obtaining the start and end of the "attribute
125 run" over which these attributes are currently invariant. Text
126 attributes are those presentational, typographic, or semantic
127 attributes or qualitites which apply to a range of text specifyable
128 by starting and ending offsets. Attributes relevant to localization
129 should be provided in accordance with the w3c "Internationalization
130 and Localization Markup Requirements", http://www.w3.org/TR/2005/WD-itsreq-20051122/
131 Other text attributes should choose their names and value semantics
132 in accordance with relevant standards such as CSS level 2 (http://www.w3.org/TR/1998/REC-CSS2-19980512),
133 XHTML 1.0 (http://www.w3.org/TR/2002/REC-xhtml1-20020801), and
134 WICD (http://www.w3.org/TR/2005/WD-WICD-20051121/). Those attributes
135 from the aforementioned specifications and recommendations which
136 do not concern typographic, presentational, or semantic aspects
137 of text should be exposed via the more general Accessible::getAttributes()
139 For example, CSS attributes which should be exposed on text (either
140 as default attributes, or as explicitly-set attributes when non-default
141 values are specified in the content view) include the Font attributes
142 (i.e. "css2:font-weight", "css2:font-style"), the "css2:color"
143 and "css2:background-color" attributes, and "css2:text-decoration"
145 If includeDefaults is TRUE, then this AttributeSet should include
146 the default attributes as well as those which are explicitly
147 assigned to the attribute run in question. startOffset and endOffset
148 will be back-filled to indicate the start and end of the attribute
149 run which contains 'offset' - an attribute run is a contiguous
150 section of text whose attributes are homogeneous.
152 the offset of the character whose attributes will be reported.
154 backfilled with the starting offset of the character range over
155 which all text attributes match those of offset, i.e. the start
156 of the homogeneous attribute run including offset.
158 backfilled with the offset of the first character past the character
159 range over which all text attributes match those of offset, i.e.
160 the character immediately after the homogeneous attribute run
162 @param : includeDefaults
163 if False, the call should only return those attributes which
164 are explicitly set on the current attribute run, omitting any
165 attributes which are inherited from the default values. See also
166 Text::getDefaultAttributes.
167 @return the AttributeSet defined at offset, optionally including
168 the 'default' attributes.
170 func = self.get_dbus_method("getAttributeRun", dbus_interface=ATSPI_TEXT)
171 [attrs, startOffset, endOffset] = func(offset, includeDefaults)
172 dict = [key + ':' + value for key, value in attrs.values()]
173 return [dict, startOffset, endOffset]
175 def getAttributeValue(self, offset, attributeName):
177 Get the string value of a named attribute at a given offset,
180 the offset of the character for which the attribute run is to
182 @param : attributeName
183 the name of the attribute for which the value is to be returned,
186 back-filled with the offset of the first character in the attribute
187 run containing the character at offset.
189 back-filled with the offset of the first character past the end
190 of the attribute run containing the character at offset.
192 back-filled with True if the attributeName has a defined value
193 at offset, False otherwise.
194 @return the value of attribute (name-value pair) corresponding
195 to "name", if defined.
197 func = self.get_dbus_method("getAttributeValue", dbus_interface=ATSPI_TEXT)
198 return func(offset, attributeName)
200 def getAttributes(self, offset):
202 getAttributes is deprecated in favor of getAttributeRun.
203 @return the attributes at offset, as a semicolon-delimited set
204 of colon-delimited name-value pairs.
206 func = self.get_dbus_method("getAttributes", dbus_interface=ATSPI_TEXT)
207 [attrs, startOffset, endOffset] = func(dbus.Int32(offset))
208 dict = [key + ':' + value for key, value in attrs]
209 return [dict, startOffset, endOffset]
211 def getBoundedRanges(self, x, y, width, height, coordType, xClipType, yClipType):
212 #TODO Return a list of range structures
214 Return the text content within a bounding box, as a list of Range
215 structures. Depending on the TEXT_CLIP_TYPE parameters, glyphs
216 which are clipped by the bounding box (i.e. which lie partially
217 inside and partially outside it) may or may not be included in
220 the minimum x ( i.e. leftmost) coordinate of the bounding box.
222 the minimum y coordinate of the bounding box.
224 the horizontal size of the bounding box. The rightmost bound
225 of the bounding box is (x + width);
227 the vertical size of the bounding box. The maximum y value of
228 the bounding box is (y + height);
230 If 0, the above coordinates are interpreted as pixels relative
231 to corner of the screen; if 1, the coordinates are interpreted
232 as pixels relative to the corner of the containing toplevel window.
234 determines whether text which intersects the bounding box in
235 the x direction is included.
237 determines whether text which intersects the bounding box in
238 the y direction is included.
240 func = self.get_dbus_method("getBoundedRanges", dbus_interface=ATSPI_TEXT)
241 return func(x, y, width, height, UInt32(coordType), xClipType, yClipType)
243 def getCharacterAtOffset(self, offset):
247 @return an unsigned long integer whose value corresponds to the
248 UCS-4 representation of the character at the specified text offset,
249 or 0 if offset is out of range.
251 func = self.get_dbus_method("getCharacterAtOffset", dbus_interface=ATSPI_TEXT)
254 def getCharacterExtents(self, offset, x, y, width, height, coordType):
256 Obtain a the bounding box, as x, y, width, and height, of the
257 character or glyph at a particular character offset in this object's
258 text content. The coordinate system in which the results are
259 reported is specified by coordType. If an onscreen glyph corresponds
260 to multiple character offsets, for instance if the glyph is a
261 ligature, the bounding box reported will include the entire glyph
262 and therefore may apply to more than one character offset.
264 the character offset of the character or glyph being queried.
266 the minimum horizontal coordinate of the bounding box of the
267 glyph representing the character at offset.
269 the minimum vertical coordinate of the bounding box of the glyph
270 representing the character at offset.
272 the horizontal extent of the bounding box of the glyph representing
273 the character at offset.
275 the vertical extent of the bounding box of the glyph representing
276 the character at offset.
278 If 0, the results will be reported in screen coordinates, i.e.
279 in pixels relative to the upper-left corner of the screen, with
280 the x axis pointing right and the y axis pointing down. If 1,
281 the results will be reported relative to the containing toplevel
282 window, with the x axis pointing right and the y axis pointing
285 func = self.get_dbus_method("getCharacterExtents", dbus_interface=ATSPI_TEXT)
286 return func(offset, x, y, width, height, UInt32(coordType))
288 def getDefaultAttributeSet(self):
290 Return an AttributeSet containing the text attributes which apply
291 to all text in the object by virtue of the default settings of
292 the document, view, or user agent; e.g. those attributes which
293 are implied rather than explicitly applied to the text object.
294 For instance, an object whose entire text content has been explicitly
295 marked as 'bold' will report the 'bold' attribute via getAttributeRun(),
296 whereas an object whose text weight is inspecified may report
297 the default or implied text weight in the default AttributeSet.
299 func = self.get_dbus_method("getDefaultAttributeSet", dbus_interface=ATSPI_TEXT)
300 return [key + ':' + value for key, value in func().values()]
302 def getDefaultAttributes(self):
304 Deprecated in favor of getDefaultAttributeSet.
305 @return the attributes which apply to the entire text content,
306 but which were not explicitly specified by the content creator.
308 func = self.get_dbus_method("getDefaultAttributes", dbus_interface=ATSPI_TEXT)
309 return ';'.join([key + ':' + value for key, value in func().iteritems()])
311 def getNSelections(self):
313 Obtain the number of separate, contiguous selections in the current
314 Text object. Text objects which do not implement selection of
315 discontiguous text regions will always return '0' or '1'. Note
316 that "contiguous" is defined by continuity of the offsets, i.e.
317 a text 'selection' is defined by a start/end offset pair. In
318 the case of bidirectional text, this means that a continguous
319 selection may appear visually discontiguous, and vice-versa.
320 @return the number of contiguous selections in the current Text
323 func = self.get_dbus_method("getNSelections", dbus_interface=ATSPI_TEXT)
326 def getOffsetAtPoint(self, x, y, coordType):
328 Get the offset of the character at a given onscreen coordinate.
329 The coordinate system used to interpret x and y is determined
330 by parameter coordType.
334 if 0, the input coordinates are interpreted relative to the entire
335 screen, if 1, they are relative to the toplevel window containing
337 @return the text offset (as an offset into the character array)
338 of the glyph whose onscreen bounds contain the point x,y, or
339 -1 if the point is outside the bounds of any glyph.
341 func = self.get_dbus_method("getOffsetAtPoint", dbus_interface=ATSPI_TEXT)
342 return func(x, y, UInt32(coordType))
344 def getRangeExtents(self, startOffset, endOffset, coordType):
346 Obtain the bounding box which entirely contains a given text
347 range. Negative values may be returned for the bounding box parameters
348 in the event that all or part of the text range is offscreen
349 or not mapped to the screen.
351 the offset of the first character in the specified range.
353 the offset of the character immediately after the last character
354 in the specified range.
356 an integer parameter which is back-filled with the minimum horizontal
357 coordinate of the resulting bounding box.
359 an integer parameter which is back-filled with the minimum vertical
360 coordinate of the resulting bounding box.
362 an integer parameter which is back-filled with the horizontal
363 extent of the bounding box.
365 an integer parameter which is back-filled with the vertical extent
368 If 0, the above coordinates are reported in pixels relative to
369 corner of the screen; if 1, the coordinates are reported relative
370 to the corner of the containing toplevel window.
372 func = self.get_dbus_method("getRangeExtents", dbus_interface=ATSPI_TEXT)
373 return func(startOffset, endOffset, UInt32(coordType))
375 def getSelection(self, selectionNum):
377 The result of calling getSelection with an out-of-range selectionNum
378 (i.e. for a selection which does not exist) is not strictly defined,
379 but should set endOffset equal to startOffset.
380 @param : selectionNum
381 indicates which of a set of non-contiguous selections to modify.
383 back-filled with the starting offset of the resulting substring,
386 back-filled with the offset of the character immediately following
387 the resulting substring, if one exists.
389 func = self.get_dbus_method("getSelection", dbus_interface=ATSPI_TEXT)
390 return func(selectionNum)
392 def getText(self, startOffset, endOffset):
394 Obtain all or part of the onscreen textual content of a Text
395 object. If endOffset is specified as "-1", then this method will
396 return the entire onscreen textual contents of the Text object.
398 back-filled with the starting offset of the resulting substring,
401 back-filled with the offset of the character immediately following
402 the resulting substring, if one exists.
403 @return the textual content of the current Text object beginning
404 startOffset (inclusive) up to but not including the character
407 func = self.get_dbus_method("getText", dbus_interface=ATSPI_TEXT)
410 return func(dbus.Int32(startOffset), dbus.Int32(endOffset))
412 def getTextAfterOffset(self, offset, type):
414 Obtain a subset of the text content of an object which entirely
415 follows offset, delimited by character, word, line, or sentence
416 boundaries as specified by type. The starting and ending offsets
417 of the resulting substring are returned in startOffset and endOffset.
418 By definition, if such a substring exists, startOffset must be
421 the offset from which the substring search begins, and which
422 must lie before the returned substring.
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.
429 back-filled with the starting offset of the resulting substring,
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.
437 func = self.get_dbus_method("getTextAfterOffset", dbus_interface=ATSPI_TEXT)
438 return func(offset, type)
440 def getTextAtOffset(self, offset, type):
442 Obtain a subset of the text content of an object which includes
443 the specified offset, delimited by character, word, line, or
444 sentence boundaries as specified by type. The starting and ending
445 offsets of the resulting substring are returned in startOffset
448 the offset from which the substring search begins, and which
449 must lie within the returned substring.
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.
456 back-filled with the starting offset of the resulting substring,
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.
464 func = self.get_dbus_method("getTextAtOffset", dbus_interface=ATSPI_TEXT)
465 return func(offset, type)
467 def getTextBeforeOffset(self, offset, type):
469 Obtain a subset of the text content of an object which entirely
470 precedes offset, delimited by character, word, line, or sentence
471 boundaries as specified by type. The starting and ending offsets
472 of the resulting substring are returned in startOffset and endOffset.
473 By definition, if such a substring exists, endOffset is less
474 than or equal to offset.
476 the offset from which the substring search begins.
478 the text-boundary delimiter which determines whether the returned
479 text constitures a character, word, line, or sentence (and possibly
480 attendant whitespace), and whether the start or ending of such
481 a substring forms the boundary condition.
483 back-filled with the starting offset of the resulting substring,
486 back-filled with the offset of the character immediately following
487 the resulting substring, if one exists.
488 @return a string which is a substring of the text content of
489 the object, delimited by the specified boundary condition.
491 func = self.get_dbus_method("getTextBeforeOffset", dbus_interface=ATSPI_TEXT)
492 return func(offset, type)
494 def removeSelection(self, selectionNum):
496 Deselect the text contained in the specified selectionNum, if
497 such a selection exists, otherwise do nothing. Removal of a non-existant
498 selectionNum has no effect.
499 @param : selectionNum
500 indicates which of a set of non-contiguous selections to modify.
501 @return True if the selection was successfully removed, False
504 func = self.get_dbus_method("removeSelection", dbus_interface=ATSPI_TEXT)
505 return func(selectionNum)
507 def setCaretOffset(self, offset):
509 Programmatically move the text caret (visible or virtual, as
510 above) to a given position.
512 a long int indicating the desired character offset. Not all implementations
513 of Text will honor setCaretOffset requests, so the return value
514 below should be checked by the client.
515 @return TRUE if the request was carried out, or FALSE if the
516 caret could not be moved to the requested position.
518 func = self.get_dbus_method("setCaretOffset", dbus_interface=ATSPI_TEXT)
521 def setSelection(self, selectionNum, startOffset, endOffset):
523 Modify an existing selection's start or ending offset.
524 Calling setSelection for a selectionNum that is not already defined
525 has no effect. The result of calling setSelection with a selectionNum
526 greater than 0 for objects that do not include STATE_MULTISELECTABLE
528 @param : selectionNum
529 indicates which of a set of non-contiguous selections to modify.
531 the new starting offset for the selection
533 the new ending offset for the selection
534 @return True if the selection corresponding to selectionNum is
535 successfully modified, False otherwise.
537 func = self.get_dbus_method("setSelection", dbus_interface=ATSPI_TEXT)
538 return func(selectionNum, startOffset, endOffset)
540 def get_caretOffset(self):
541 return dbus.Int32(self._pgetter(self._dbus_interface, "caretOffset"))
544 The current offset of the text caret in the Text object. This
545 caret may be virtual, e.g. non-visual and notional-only, but
546 if an onscreen representation of the caret position is visible,
547 it will correspond to this offset. The caret offset is given
548 as a character offset, as opposed to a byte offset into a text
549 buffer or a column offset.
551 caretOffset = property(fget=get_caretOffset, doc=_caretOffsetDoc)
553 def get_characterCount(self):
554 return dbus.Int32(self._pgetter(self._dbus_interface, "characterCount"))
555 _characterCountDoc = \
557 The total current number of characters in the Text object, including
558 whitespace and non-spacing characters.
560 characterCount = property(fget=get_characterCount, doc=_characterCountDoc)
563 def __new__(cls, startOffset, endOffset, content, data):
564 list.__new__(cls, (startOffset, endOffset, content, data))
565 def __init__(self, startOffset, endOffset, content, data):
566 list.__init__(self, (startOffset, endOffset, content, data))
568 def _get_startOffset(self):
570 def _set_startOffset(self, val):
572 startOffset = property(fget=_get_startOffset, fset=_set_startOffset)
573 def _get_endOffset(self):
575 def _set_endOffset(self, val):
577 endOffset = property(fget=_get_endOffset, fset=_set_endOffset)
578 def _get_content(self):
580 def _set_content(self, val):
582 content = property(fget=_get_content, fset=_set_content)
585 def _set_data(self, val):
587 data = property(fget=_get_data, fset=_set_data)
589 # Register the accessible class with the factory.
590 accessible_factory.register_accessible_class(ATSPI_TEXT, Text)
592 #END----------------------------------------------------------------------------