8 closedid
= struct
.pack('h', 468)
9 openid
= struct
.pack('h', 469)
10 closedsolidid
= struct
.pack('h', 470)
11 opensolidid
= struct
.pack('h', 471)
13 arrows
= (nullid
, closedid
, openid
, closedsolidid
, opensolidid
)
15 has_ctlcharsRE
= regex
.compile('[\000-\037\177-\377]')
17 def double_repr(key
, value
, truncvalue
= 0,
18 type = type, StringType
= types
.StringType
,
19 has_ctlchars
= has_ctlcharsRE
.search
, _repr
= repr, str = str):
20 if type(key
) == StringType
and has_ctlchars(key
) < 0:
24 if type(value
) == StringType
and has_ctlchars(value
) < 0:
26 elif key
== '__builtins__':
27 value
= "<" + type(value
).__name
__ + " '__builtin__'>"
28 elif key
== '__return__':
29 # bleh, when returning from a class codeblock we get infinite recursion in repr.
30 # Use safe repr instead.
32 value
= repr.repr(value
)
36 '' + value
# test to see if it is a string, in case a __repr__ method is buggy
38 value
= '€€€ exception in repr()'
40 return key
+ '\t' + value
[:255]
41 return key
+ '\t' + value
44 class BrowserWidget(W
.List
):
48 def __init__(self
, possize
, object = None, col
= 100, closechildren
= 0):
49 W
.List
.__init
__(self
, possize
, callback
= self
.listhit
)
52 self
.lastmaxindent
= 0
53 self
.closechildren
= closechildren
57 self
.bind('return', self
.openselection
)
58 self
.bind('enter', self
.openselection
)
59 if object is not None:
62 def set(self
, object):
63 if self
.object[0] <> object:
65 self
[:] = self
.unpack(object, 0)
66 elif self
._parentwindow
is not None and self
._parentwindow
.wid
:
69 def unpack(self
, object, indent
):
70 return unpack_object(object, indent
)
75 self
.setdrawingmode(0)
76 sel
= self
.getselectedobjects()
77 fold
= self
.getunfoldedobjects()
78 topcell
= self
.gettopcell()
79 self
[:] = self
.unpack(self
.object[0], 0)
80 self
.unfoldobjects(fold
)
81 self
.setselectedobjects(sel
)
82 self
.settopcell(topcell
)
83 self
.setdrawingmode(1)
85 def setcolumn(self
, col
):
87 self
.colstr
= struct
.pack('h', col
)
89 sel
= self
.getselection()
90 self
.setitems(self
.items
)
91 self
.setselection(sel
)
93 def key(self
, char
, event
):
94 if char
in (SpecialKeys
.leftarrowkey
, SpecialKeys
.rightarrowkey
):
95 sel
= self
.getselection()
97 self
.setdrawingmode(0)
99 self
.fold(index
, char
== SpecialKeys
.rightarrowkey
)
100 self
.setdrawingmode(1)
102 W
.List
.key(self
, char
, event
)
104 def rollover(self
, (x
, y
), onoff
):
106 if self
.incolumn((x
, y
)):
107 W
.SetCursor('hmover')
111 def inarrow(self
, (x
, y
)):
112 cl
, ct
, cr
, cb
= self
._list
.LRect((0, 0))
113 l
, t
, r
, b
= self
._bounds
116 index
= (y
- ct
) / cellheight
117 if index
< len(self
.items
):
121 def incolumn(self
, (x
, y
)):
122 l
, t
, r
, b
= self
._list
.LRect((0, 0))
123 abscol
= l
+ self
.col
124 return abs(abscol
- x
) < 3
126 def trackcolumn(self
, (x
, y
)):
127 import Qd
, QuickDraw
, Evt
129 l
, t
, r
, b
= self
._bounds
130 bounds
= l
, t
, r
, b
= l
+ 1, t
+ 1, r
- 16, b
- 1
131 abscol
= l
+ self
.col
132 mincol
= l
+ self
.mincol
135 Qd
.PenPat('\000\377\000\377\000\377\000\377')
136 Qd
.PenMode(QuickDraw
.srcXor
)
137 rect
= abscol
- 1, t
, abscol
, b
143 (x
, y
) = Evt
.GetMouse()
144 if (x
, y
) <> lastpoint
:
146 newcol
= max(newcol
, mincol
)
147 newcol
= min(newcol
, maxcol
)
149 rect
= newcol
- 1, t
, newcol
, b
153 Qd
.PenPat(Qd
.qd
.black
)
155 if newcol
> 0 and newcol
<> abscol
:
156 self
.setcolumn(newcol
- l
)
158 def click(self
, point
, modifiers
):
159 if point
== (-1, -1): # gross.
160 W
.List
.click(self
, point
,modifiers
)
162 hit
, index
= self
.inarrow(point
)
164 (key
, value
, arrow
, indent
) = self
.items
[index
]
165 self
.fold(index
, arrow
== 1)
166 elif self
.incolumn(point
):
167 self
.trackcolumn(point
)
169 W
.List
.click(self
, point
, modifiers
)
172 def findmatch(self
, tag
):
178 for i
in range(len(items
)):
179 item
= lower(str(items
[i
][0]))
180 if tag
<= item
< match
:
186 return len(items
) - 1
189 if self
.closechildren
:
190 for window
in self
.children
:
195 def fold(self
, index
, onoff
):
196 (key
, value
, arrow
, indent
) = self
.items
[index
]
197 if arrow
== 0 or (onoff
and arrow
== 2) or (not onoff
and arrow
== 1):
200 topcell
= self
.gettopcell()
202 self
[index
] = (key
, value
, 4, indent
)
203 self
.setdrawingmode(0)
204 self
[index
+1:index
+1] = self
.unpack(value
, indent
+ 1)
205 self
[index
] = (key
, value
, 2, indent
)
207 self
[index
] = (key
, value
, 3, indent
)
208 self
.setdrawingmode(0)
210 for i
in range(index
+ 1, len(self
.items
)):
211 (dummy
, dummy
, dummy
, subindent
) = self
.items
[i
]
212 if subindent
<= indent
:
215 self
[index
+1:index
+1+count
] = []
216 self
[index
] = (key
, value
, 1, indent
)
217 maxindent
= self
.getmaxindent()
218 if maxindent
<> self
.lastmaxindent
:
219 newabsindent
= self
.col
+ (maxindent
- self
.lastmaxindent
) * self
.indent
220 if newabsindent
>= self
.mincol
:
221 self
.setcolumn(newabsindent
)
222 self
.lastmaxindent
= maxindent
223 self
.settopcell(topcell
)
224 self
.setdrawingmode(1)
226 def unfoldobjects(self
, objects
):
229 index
= self
.items
.index(obj
)
235 def getunfoldedobjects(self
):
238 for index
in range(len(self
.items
)):
239 (key
, value
, arrow
, indent
) = self
.items
[index
]
240 if indent
> curindent
:
241 (k
, v
, a
, i
) = self
.items
[index
- 1]
242 objects
.append((k
, v
, 1, i
))
244 elif indent
< curindent
:
248 def listhit(self
, isdbl
):
252 def openselection(self
):
254 sel
= self
.getselection()
256 (key
, value
, arrow
, indent
) = self
[index
]
258 self
.children
.append(Browser(value
))
259 elif type(value
) == types
.StringType
and '\0' not in value
:
260 editor
= self
._parentwindow
.parent
.getscript(value
)
264 elif os
.path
.exists(value
) and os
.path
.isfile(value
):
266 fss
= macfs
.FSSpec(value
)
267 if fss
.GetCreatorType()[1] == 'TEXT':
268 W
.getapplication().openscript(value
)
270 def itemrepr(self
, (key
, value
, arrow
, indent
), str = str, double_repr
= double_repr
,
271 arrows
= arrows
, pack
= struct
.pack
):
272 arrow
= arrows
[arrow
]
273 return arrow
+ pack('h', self
.indent
* indent
) + self
.colstr
+ \
274 double_repr(key
, value
, 1)
276 def getmaxindent(self
, max = max):
278 for item
in self
.items
:
279 maxindent
= max(maxindent
, item
[3])
282 def domenu_copy(self
, *args
):
283 sel
= self
.getselectedobjects()
285 for key
, value
, dummy
, dummy
in sel
:
286 selitems
.append(double_repr(key
, value
))
287 text
= string
.join(selitems
, '\r')
291 Scrap
.PutScrap('TEXT', text
)
296 def __init__(self
, object = None, title
= None, closechildren
= 0):
297 if hasattr(object, '__name__'):
298 name
= object.__name
__
302 title
= 'Object browser'
304 title
= title
+ ': ' + name
305 self
.w
= w
= W
.Window((300, 400), title
, minsize
= (100, 100))
306 w
.info
= W
.TextBox((18, 8, -70, 15))
307 w
.updatebutton
= W
.Button((-64, 4, 50, 16), 'Update', self
.update
)
308 w
.browser
= BrowserWidget((-1, 24, 1, -14), None)
309 w
.bind('cmdu', w
.updatebutton
.push
)
311 self
.set(object, name
)
317 def set(self
, object, name
= ''):
319 tp
= type(object).__name
__
324 if not name
and hasattr(object, '__name__'):
325 name
= object.__name
__
327 info
= name
+ ': ' + tp
332 info
= info
+ ' (%d element)' % length
334 info
= info
+ ' (%d elements)' % length
335 self
.w
.info
.set(info
)
336 self
.w
.browser
.set(object)
339 self
.w
.browser
.update()
357 def unpack_object(object, indent
= 0):
359 if tp
in SIMPLE_TYPES
and tp
is not types
.NoneType
:
360 raise TypeError, 'can¹t browse simple type: %s' % tp
.__name
__
361 elif tp
== types
.DictionaryType
:
362 return unpack_dict(object, indent
)
363 elif tp
in (types
.TupleType
, types
.ListType
):
364 return unpack_sequence(object, indent
)
365 elif tp
== types
.InstanceType
:
366 return unpack_instance(object, indent
)
367 elif tp
== types
.ClassType
:
368 return unpack_class(object, indent
)
369 elif tp
== types
.ModuleType
:
370 return unpack_dict(object.__dict
__, indent
)
372 return unpack_other(object, indent
)
374 def unpack_sequence(seq
, indent
= 0):
375 items
= map(None, range(len(seq
)), seq
)
376 items
= map(lambda (k
, v
), type = type, simp
= SIMPLE_TYPES
, indent
= indent
:
377 (k
, v
, not type(v
) in simp
, indent
), items
)
380 def unpack_dict(dict, indent
= 0):
382 return pack_items(items
, indent
)
384 def unpack_instance(inst
, indent
= 0):
385 if hasattr(inst
, '__pybrowse_unpack__'):
386 return unpack_object(inst
.__pybrowse
_unpack
__(), indent
)
388 items
= [('__class__', inst
.__class
__)] + inst
.__dict
__.items()
389 return pack_items(items
, indent
)
391 def unpack_class(clss
, indent
= 0):
392 items
= [('__bases__', clss
.__bases
__), ('__name__', clss
.__name
__)] + clss
.__dict
__.items()
393 return pack_items(items
, indent
)
395 def unpack_other(object, indent
= 0):
397 if hasattr(object, '__members__'):
398 attrs
= attrs
+ object.__members
__
399 if hasattr(object, '__methods__'):
400 attrs
= attrs
+ object.__methods
__
403 items
.append((attr
, getattr(object, attr
)))
404 return pack_items(items
, indent
)
406 def pack_items(items
, indent
= 0):
407 items
= map(lambda (k
, v
), type = type, simp
= SIMPLE_TYPES
, indent
= indent
:
408 (k
, v
, not type(v
) in simp
, indent
),
410 return tuple_caselesssort(items
)
412 def caselesssort(alist
):
413 """Return a sorted copy of a list. If there are only strings in the list,
414 it will not consider case"""
417 # turn ['FOO', 'aaBc', 'ABcD'] into [('foo', 'FOO'), ('aabc', 'aaBc'), ('abcd', 'ABcD')], if possible
418 tupledlist
= map(lambda item
, lower
= string
.lower
: (lower(item
), item
), alist
)
420 # at least one element in alist is not a string, proceed the normal way...
426 # turn [('aabc', 'aaBc'), ('abcd', 'ABcD'), ('foo', 'FOO')] into ['aaBc', 'ABcD', 'FOO']
427 return map(lambda x
: x
[1], tupledlist
)
429 def tuple_caselesssort(items
):
431 tupledlist
= map(lambda tuple, lower
= string
.lower
: (lower(tuple[0]), tuple), items
)
438 return map(lambda (low
, tuple): tuple, tupledlist
)