1 '''
2 Defines L{AccAdapt.Adapter}s for AT-SPI tree accessibles. Trees implement both
3 the Table and the Selection interfaces.
4
5 @author: Peter Parente
6 @author: Eirikur Hallgrimsson
7 @organization: IBM Corporation
8 @copyright: Copyright (c) 2005, 2007 IBM Corporation
9 @license: The BSD License
10
11 All rights reserved. This program and the accompanying materials are made
12 available under the terms of the BSD license which accompanies
13 this distribution, and is available at
14 U{http://www.opensource.org/licenses/bsd-license.php}
15 '''
16
17 import pyLinAcc
18 from ContainerAdapter import *
19 from TableAdapter import *
20 from DefaultNav import *
21 from AEInterfaces import *
22 from pyLinAcc import Interfaces, Constants
23
25 '''
26 Overrides L{TableAccInfoAdapter} to generate selector events on focus
27 and on selection. Expects the subject to be a L{pyLinAcc.Accessible}.
28
29 Adapts subject accessibles that provide the L{pyLinAcc.Interfaces.ITable}
30 interface and have ROLE_TREE_TABLE.
31 '''
32 provides = [IAccessibleInfo]
33
34 @staticmethod
36 '''
37 Tests if the given subject can be adapted by this class.
38
39 @param por: Point of regard to test
40 @type por: L{POR}
41 @return: True when the subject meets the condition named in the docstring
42 for this class, False otherwise
43 @rtype: boolean
44 '''
45 acc = por.accessible
46 r = acc.getRole()
47
48 if r != Constants.ROLE_TREE_TABLE:
49 return False
50
51 tab = Interfaces.ITable(acc)
52 return True
53
54 @pyLinAcc.errorToLookupError
56 '''
57 Gets the level of a node in a tree where zero is the root.
58
59 @return: Level of the node
60 @rtype: integer
61 @raise NotImplementedError: When a tree doesn't support the NODE_OF
62 accessible relation
63 '''
64
65 if self.item_offset is None:
66 raise NotImplementedError
67
68 count = 0
69 node = self.accessible.getChildAtIndex(self.item_offset)
70 relations = node.getRelationSet()
71 if not relations:
72
73
74 table = Interfaces.ITable(self.accessible)
75 row = table.getRowAtIndex(self.item_offset)
76 node = table.getAccessibleAt(row, 0)
77 relations = node.getRelationSet()
78
79 if not relations:
80
81 raise NotImplementedError
82
83 def parent(relations):
84 for rel in relations:
85 if rel.getRelationType() == Constants.RELATION_NODE_CHILD_OF:
86 return rel.getTarget(0).getRelationSet()
87 return None
88
89 while True:
90 temp = parent(relations)
91 if temp:
92 count +=1
93 relations = temp
94 else:
95 return count
96
98 '''
99 Overrides L{DefaultNavAdapter} to provide navigation over tree cells as items.
100 Expects the subject to be a L{POR}.
101
102 Adapts subject accessibles that provide the L{pyLinAcc.Interfaces.ITable}
103 interface and have ROLE_TREE_TABLE.
104 '''
105 provides = [IAccessibleNav, IItemNav]
106
107 @staticmethod
109 '''
110 Tests if the given subject can be adapted by this class.
111
112 @param subject: L{POR} containing an accessible to test
113 @type subject: L{POR}
114 @return: True when the subject meets the condition named in the docstring
115 for this class, False otherwise
116 @rtype: boolean
117 '''
118 acc = subject.accessible
119 r = acc.getRole()
120 return (r == Constants.ROLE_TREE_TABLE and Interfaces.ITable(acc))
121
122 @pyLinAcc.errorToLookupError
124 '''
125 Gets the item offsets of the first and last items in a tree of cells.
126
127 @param only_visible: Only consider the first and last cells visible in
128 the tree (True) or the absolute first and last cells (False)?
129 @return: First and last item offsets
130 @rtype: 2-tuple of integer
131 @raise LookupError: When the first or last item or parent accessible is
132 not available
133 '''
134 acc = self.accessible
135 if only_visible:
136 comp = Interfaces.IComponent(acc)
137 e = comp.getExtents(Constants.DESKTOP_COORDS)
138
139 x, y = e.x+FUDGE_PX, e.y+FUDGE_PX
140 first = comp.getAccessibleAtPoint(x, y, Constants.DESKTOP_COORDS)
141
142 x, y = e.x+e.width-FUDGE_PX, e.y+e.height-FUDGE_PX
143 last = comp.getAccessibleAtPoint(x, y, Constants.DESKTOP_COORDS)
144 else:
145 first = None
146 last = None
147
148 if first:
149 i = first.getIndexInParent()
150 else:
151 i = 0
152 if last:
153 j = last.getIndexInParent()
154 else:
155 t = Interfaces.ITable(acc)
156 j = t.getIndexAt(t.nRows-1, t.nColumns-1)
157 return i, j
158
159 @pyLinAcc.errorToLookupError
161 '''
162 Gets the next item relative to the one indicated by the L{POR}
163 providing this interface.
164
165 @param only_visible: True when Item in the returned L{POR} must be visible
166 @type only_visible: boolean
167 @return: Point of regard to the next item in the same accessible
168 @rtype: L{POR}
169 @raise IndexError: When there is no next item
170 @raise LookupError: When lookup for the next item fails even though it may
171 exist
172 '''
173 acc = self.accessible
174 off = self.item_offset
175
176 i, j = self._getVisibleItemExtents(only_visible)
177
178
179
180
181
182 if off is None or off < i:
183
184 return POR(acc, i, 0)
185 elif off+1 >= i and off+1 <= j:
186
187 t = Interfaces.ITable(acc)
188 r, c = t.getRowAtIndex(off), t.getColumnAtIndex(off)
189
190 if c < t.nColumns-1:
191 c += 1
192 else:
193 r += 1
194 c = 0
195
196 n_off = t.getIndexAt(r, c)
197 return POR(acc, n_off, 0)
198 else:
199
200 raise IndexError
201
202 @pyLinAcc.errorToLookupError
204 '''
205 Gets the previous item relative to the one indicated by the L{POR}
206 providing this interface.
207
208 @param only_visible: True when Item in the returned L{POR} must be visible
209 @type only_visible: boolean
210 @return: Point of regard to the previous item in the same accessible
211 @rtype: L{POR}
212 @raise IndexError: When there is no previous item
213 @raise LookupError: When lookup for the previous item fails even though it
214 may exist
215 '''
216 acc = self.accessible
217 off = self.item_offset
218 comp = Interfaces.IComponent(acc)
219
220 i, j = self._getVisibleItemExtents(only_visible)
221
222
223 if off is None:
224
225 raise IndexError
226 elif off > j:
227
228 return POR(acc, j, 0)
229 elif off-1 >= i and off-1 <= j:
230
231 t = Interfaces.ITable(acc)
232 r, c = t.getRowAtIndex(off), t.getColumnAtIndex(off)
233
234 if c:
235 c -= 1
236 else:
237 r -= 1
238 c = t.nColumns-1
239
240 p_off = t.getIndexAt(r, c)
241 return POR(acc, p_off, 0)
242
243
244
245 else:
246
247 return POR(acc, None, 0)
248
249 @pyLinAcc.errorToLookupError
251 '''
252 Gets the last item relative to the one indicated by the L{POR}
253 providing this interface.
254
255 @param only_visible: True when Item in the returned L{POR} must be visible
256 @type only_visible: boolean
257 @return: Point of regard to the last item in the same accessible
258 @rtype: L{POR}
259 @raise LookupError: When lookup for the last item fails even though it may
260 exist
261 '''
262 acc = self.accessible
263 comp = Interfaces.IComponent(acc)
264
265 child = acc.getChildAtIndex(acc.childCount-1)
266 if IAccessibleInfo(POR(child)).isAccVisible() or not only_visible:
267 return POR(acc, acc.childCount-1, 0)
268
269 i, j = self._getVisibleItemExtents(only_visible)
270 return POR(acc, j, 0)
271
272 @pyLinAcc.errorToLookupError
274 '''
275 Gets the first item relative to the one indicated by the L{POR}
276 providing this interface.
277
278 @param only_visible: True when Item in the returned L{POR} must be visible
279 @type only_visible: boolean
280 @return: Point of regard to the last item in the same accessible
281 @rtype: L{POR}
282 @raise LookupError: When lookup for the last item fails even though it may
283 exist
284 '''
285 acc = self.accessible
286 comp = Interfaces.IComponent(acc)
287
288 child = acc.getChildAtIndex(0)
289 if IAccessibleInfo(POR(child)).isAccVisible() or not only_visible:
290 return POR(acc, 0, 0)
291
292 i, j = self._getVisibleItemExtents(only_visible)
293 return POR(acc, i, 0)
294
295 @pyLinAcc.errorToLookupError
297 '''
298 Always raises LookupError. Tables have items but no children.
299
300 @raise LookupError: Always
301 '''
302 raise LookupError
303
304 @pyLinAcc.errorToLookupError
306 '''
307 Always raises LookupError. Tables have items but no children.
308
309 @raise LookupError: Always
310 '''
311 raise LookupError
312
313 @pyLinAcc.errorToLookupError
315 '''
316 Always raises LookupError. Tables have items but no children.
317
318 @raise LookupError: Always
319 '''
320 raise LookupError
321