9 closedid
= struct
.pack('h', 468)
10 openid
= struct
.pack('h', 469)
11 closedsolidid
= struct
.pack('h', 470)
12 opensolidid
= struct
.pack('h', 471)
14 arrows
= (nullid
, closedid
, openid
, closedsolidid
, opensolidid
)
16 has_ctlcharsRE
= regex
.compile('[\000-\037\177-\377]')
18 def double_repr(key
, value
, truncvalue
= 0,
19 type = type, StringType
= types
.StringType
,
20 has_ctlchars
= has_ctlcharsRE
.search
, _repr
= repr, str = str):
21 if type(key
) == StringType
and has_ctlchars(key
) < 0:
25 if type(value
) == StringType
and has_ctlchars(value
) < 0:
27 elif key
== '__builtins__':
28 value
= "<" + type(value
).__name
__ + " '__builtin__'>"
29 elif key
== '__return__':
30 # bleh, when returning from a class codeblock we get infinite recursion in repr.
31 # Use safe repr instead.
33 value
= repr.repr(value
)
37 '' + value
# test to see if it is a string, in case a __repr__ method is buggy
39 value
= '€€€ exception in repr()'
41 return key
+ '\t' + value
[:255]
42 return key
+ '\t' + value
45 class BrowserWidget(W
.List
):
49 def __init__(self
, possize
, object = None, col
= 100, closechildren
= 0):
50 W
.List
.__init
__(self
, possize
, callback
= self
.listhit
)
53 self
.lastmaxindent
= 0
54 self
.closechildren
= closechildren
58 self
.bind('return', self
.openselection
)
59 self
.bind('enter', self
.openselection
)
60 if object is not None:
63 def set(self
, object):
64 if self
.object[0] is not object:
66 self
[:] = self
.unpack(object, 0)
67 elif self
._parentwindow
is not None and self
._parentwindow
.wid
:
70 def unpack(self
, object, indent
):
71 return unpack_object(object, indent
)
76 self
.setdrawingmode(0)
77 sel
= self
.getselectedobjects()
78 fold
= self
.getunfoldedobjects()
79 topcell
= self
.gettopcell()
80 self
[:] = self
.unpack(self
.object[0], 0)
81 self
.unfoldobjects(fold
)
82 self
.setselectedobjects(sel
)
83 self
.settopcell(topcell
)
84 self
.setdrawingmode(1)
86 def setcolumn(self
, col
):
88 self
.colstr
= struct
.pack('h', col
)
90 sel
= self
.getselection()
91 self
.setitems(self
.items
)
92 self
.setselection(sel
)
94 def key(self
, char
, event
):
95 if char
in (Wkeys
.leftarrowkey
, Wkeys
.rightarrowkey
):
96 sel
= self
.getselection()
98 self
.setdrawingmode(0)
100 self
.fold(index
, char
== Wkeys
.rightarrowkey
)
101 self
.setdrawingmode(1)
103 W
.List
.key(self
, char
, event
)
105 def rollover(self
, (x
, y
), onoff
):
107 if self
.incolumn((x
, y
)):
108 W
.SetCursor('hmover')
112 def inarrow(self
, (x
, y
)):
113 cl
, ct
, cr
, cb
= self
._list
.LRect((0, 0))
114 l
, t
, r
, b
= self
._bounds
117 index
= (y
- ct
) / cellheight
118 if index
< len(self
.items
):
122 def incolumn(self
, (x
, y
)):
123 l
, t
, r
, b
= self
._list
.LRect((0, 0))
124 abscol
= l
+ self
.col
125 return abs(abscol
- x
) < 3
127 def trackcolumn(self
, (x
, y
)):
128 import Qd
, QuickDraw
, Evt
130 l
, t
, r
, b
= self
._bounds
131 bounds
= l
, t
, r
, b
= l
+ 1, t
+ 1, r
- 16, b
- 1
132 abscol
= l
+ self
.col
133 mincol
= l
+ self
.mincol
136 Qd
.PenPat('\000\377\000\377\000\377\000\377')
137 Qd
.PenMode(QuickDraw
.srcXor
)
138 rect
= abscol
- 1, t
, abscol
, b
144 (x
, y
) = Evt
.GetMouse()
145 if (x
, y
) <> lastpoint
:
147 newcol
= max(newcol
, mincol
)
148 newcol
= min(newcol
, maxcol
)
150 rect
= newcol
- 1, t
, newcol
, b
154 Qd
.PenPat(Qd
.qd
.black
)
156 if newcol
> 0 and newcol
<> abscol
:
157 self
.setcolumn(newcol
- l
)
159 def click(self
, point
, modifiers
):
160 if point
== (-1, -1): # gross.
161 W
.List
.click(self
, point
,modifiers
)
163 hit
, index
= self
.inarrow(point
)
165 (key
, value
, arrow
, indent
) = self
.items
[index
]
166 self
.fold(index
, arrow
== 1)
167 elif self
.incolumn(point
):
168 self
.trackcolumn(point
)
170 W
.List
.click(self
, point
, modifiers
)
173 def findmatch(self
, tag
):
179 for i
in range(len(items
)):
180 item
= lower(str(items
[i
][0]))
181 if tag
<= item
< match
:
187 return len(items
) - 1
190 if self
.closechildren
:
191 for window
in self
.children
:
196 def fold(self
, index
, onoff
):
197 (key
, value
, arrow
, indent
) = self
.items
[index
]
198 if arrow
== 0 or (onoff
and arrow
== 2) or (not onoff
and arrow
== 1):
201 topcell
= self
.gettopcell()
203 self
[index
] = (key
, value
, 4, indent
)
204 self
.setdrawingmode(0)
205 self
[index
+1:index
+1] = self
.unpack(value
, indent
+ 1)
206 self
[index
] = (key
, value
, 2, indent
)
208 self
[index
] = (key
, value
, 3, indent
)
209 self
.setdrawingmode(0)
211 for i
in range(index
+ 1, len(self
.items
)):
212 (dummy
, dummy
, dummy
, subindent
) = self
.items
[i
]
213 if subindent
<= indent
:
216 self
[index
+1:index
+1+count
] = []
217 self
[index
] = (key
, value
, 1, indent
)
218 maxindent
= self
.getmaxindent()
219 if maxindent
<> self
.lastmaxindent
:
220 newabsindent
= self
.col
+ (maxindent
- self
.lastmaxindent
) * self
.indent
221 if newabsindent
>= self
.mincol
:
222 self
.setcolumn(newabsindent
)
223 self
.lastmaxindent
= maxindent
224 self
.settopcell(topcell
)
225 self
.setdrawingmode(1)
227 def unfoldobjects(self
, objects
):
230 index
= self
.items
.index(obj
)
236 def getunfoldedobjects(self
):
239 for index
in range(len(self
.items
)):
240 (key
, value
, arrow
, indent
) = self
.items
[index
]
241 if indent
> curindent
:
242 (k
, v
, a
, i
) = self
.items
[index
- 1]
243 objects
.append((k
, v
, 1, i
))
245 elif indent
< curindent
:
249 def listhit(self
, isdbl
):
253 def openselection(self
):
255 sel
= self
.getselection()
257 (key
, value
, arrow
, indent
) = self
[index
]
259 self
.children
.append(Browser(value
))
260 elif type(value
) == types
.StringType
and '\0' not in value
:
261 editor
= self
._parentwindow
.parent
.getscript(value
)
265 elif os
.path
.exists(value
) and os
.path
.isfile(value
):
267 fss
= macfs
.FSSpec(value
)
268 if fss
.GetCreatorType()[1] == 'TEXT':
269 W
.getapplication().openscript(value
)
271 def itemrepr(self
, (key
, value
, arrow
, indent
), str = str, double_repr
= double_repr
,
272 arrows
= arrows
, pack
= struct
.pack
):
273 arrow
= arrows
[arrow
]
274 return arrow
+ pack('h', self
.indent
* indent
) + self
.colstr
+ \
275 double_repr(key
, value
, 1)
277 def getmaxindent(self
, max = max):
279 for item
in self
.items
:
280 maxindent
= max(maxindent
, item
[3])
283 def domenu_copy(self
, *args
):
284 sel
= self
.getselectedobjects()
286 for key
, value
, dummy
, dummy
in sel
:
287 selitems
.append(double_repr(key
, value
))
288 text
= string
.join(selitems
, '\r')
292 Scrap
.PutScrap('TEXT', text
)
297 def __init__(self
, object = None, title
= None, closechildren
= 0):
298 if hasattr(object, '__name__'):
299 name
= object.__name
__
303 title
= 'Object browser'
305 title
= title
+ ': ' + name
306 self
.w
= w
= W
.Window((300, 400), title
, minsize
= (100, 100))
307 w
.info
= W
.TextBox((18, 8, -70, 15))
308 w
.updatebutton
= W
.Button((-64, 4, 50, 16), 'Update', self
.update
)
309 w
.browser
= BrowserWidget((-1, 24, 1, -14), None)
310 w
.bind('cmdu', w
.updatebutton
.push
)
312 self
.set(object, name
)
318 def set(self
, object, name
= ''):
320 tp
= type(object).__name
__
325 if not name
and hasattr(object, '__name__'):
326 name
= object.__name
__
328 info
= name
+ ': ' + tp
333 info
= info
+ ' (%d element)' % length
335 info
= info
+ ' (%d elements)' % length
336 self
.w
.info
.set(info
)
337 self
.w
.browser
.set(object)
340 self
.w
.browser
.update()
358 def unpack_object(object, indent
= 0):
360 if tp
in SIMPLE_TYPES
and tp
is not types
.NoneType
:
361 raise TypeError, 'can¹t browse simple type: %s' % tp
.__name
__
362 elif tp
== types
.DictionaryType
:
363 return unpack_dict(object, indent
)
364 elif tp
in (types
.TupleType
, types
.ListType
):
365 return unpack_sequence(object, indent
)
366 elif tp
== types
.InstanceType
:
367 return unpack_instance(object, indent
)
368 elif tp
== types
.ClassType
:
369 return unpack_class(object, indent
)
370 elif tp
== types
.ModuleType
:
371 return unpack_dict(object.__dict
__, indent
)
373 return unpack_other(object, indent
)
375 def unpack_sequence(seq
, indent
= 0):
376 items
= map(None, range(len(seq
)), seq
)
377 items
= map(lambda (k
, v
), type = type, simp
= SIMPLE_TYPES
, indent
= indent
:
378 (k
, v
, not type(v
) in simp
, indent
), items
)
381 def unpack_dict(dict, indent
= 0):
383 return pack_items(items
, indent
)
385 def unpack_instance(inst
, indent
= 0):
386 if hasattr(inst
, '__pybrowse_unpack__'):
387 return unpack_object(inst
.__pybrowse
_unpack
__(), indent
)
389 items
= [('__class__', inst
.__class
__)] + inst
.__dict
__.items()
390 return pack_items(items
, indent
)
392 def unpack_class(clss
, indent
= 0):
393 items
= [('__bases__', clss
.__bases
__), ('__name__', clss
.__name
__)] + clss
.__dict
__.items()
394 return pack_items(items
, indent
)
396 def unpack_other(object, indent
= 0):
398 if hasattr(object, '__members__'):
399 attrs
= attrs
+ object.__members
__
400 if hasattr(object, '__methods__'):
401 attrs
= attrs
+ object.__methods
__
404 items
.append((attr
, getattr(object, attr
)))
405 return pack_items(items
, indent
)
407 def pack_items(items
, indent
= 0):
408 items
= map(lambda (k
, v
), type = type, simp
= SIMPLE_TYPES
, indent
= indent
:
409 (k
, v
, not type(v
) in simp
, indent
),
411 return tuple_caselesssort(items
)
413 def caselesssort(alist
):
414 """Return a sorted copy of a list. If there are only strings in the list,
415 it will not consider case"""
418 # turn ['FOO', 'aaBc', 'ABcD'] into [('foo', 'FOO'), ('aabc', 'aaBc'), ('abcd', 'ABcD')], if possible
419 tupledlist
= map(lambda item
, lower
= string
.lower
: (lower(item
), item
), alist
)
421 # at least one element in alist is not a string, proceed the normal way...
427 # turn [('aabc', 'aaBc'), ('abcd', 'ABcD'), ('foo', 'FOO')] into ['aaBc', 'ABcD', 'FOO']
428 return map(lambda x
: x
[1], tupledlist
)
430 def tuple_caselesssort(items
):
432 tupledlist
= map(lambda tuple, lower
= string
.lower
: (lower(tuple[0]), tuple), items
)
439 return map(lambda (low
, tuple): tuple, tupledlist
)