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 key
== '__builtins__':
26 value
= "<" + type(value
).__name
__ + " '__builtin__'>"
27 elif key
== '__return__':
28 # bleh, when returning from a class codeblock we get infinite recursion in repr.
29 # Use safe repr instead.
31 value
= repr.repr(value
)
35 '' + value
# test to see if it is a string, in case a __repr__ method is buggy
37 value
= '€€€ exception in repr()'
39 return key
+ '\t' + value
[:255]
40 return key
+ '\t' + value
43 class BrowserWidget(W
.List
):
47 def __init__(self
, possize
, object = None, col
= 100, closechildren
= 0):
48 W
.List
.__init
__(self
, possize
, callback
= self
.listhit
)
51 self
.lastmaxindent
= 0
52 self
.closechildren
= closechildren
56 self
.bind('return', self
.openselection
)
57 self
.bind('enter', self
.openselection
)
58 if object is not None:
61 def set(self
, object):
62 if self
.object[0] is not object:
64 self
[:] = self
.unpack(object, 0)
65 elif self
._parentwindow
is not None and self
._parentwindow
.wid
:
68 def unpack(self
, object, indent
):
69 return unpack_object(object, indent
)
74 self
.setdrawingmode(0)
75 sel
= self
.getselectedobjects()
76 fold
= self
.getunfoldedobjects()
77 topcell
= self
.gettopcell()
78 self
[:] = self
.unpack(self
.object[0], 0)
79 self
.unfoldobjects(fold
)
80 self
.setselectedobjects(sel
)
81 self
.settopcell(topcell
)
82 self
.setdrawingmode(1)
84 def setcolumn(self
, col
):
86 self
.colstr
= struct
.pack('h', col
)
88 sel
= self
.getselection()
89 self
.setitems(self
.items
)
90 self
.setselection(sel
)
92 def key(self
, char
, event
):
93 if char
in (Wkeys
.leftarrowkey
, Wkeys
.rightarrowkey
):
94 sel
= self
.getselection()
96 self
.setdrawingmode(0)
98 self
.fold(index
, char
== Wkeys
.rightarrowkey
)
99 self
.setdrawingmode(1)
101 W
.List
.key(self
, char
, event
)
103 def rollover(self
, (x
, y
), onoff
):
105 if self
.incolumn((x
, y
)):
106 W
.SetCursor('hmover')
110 def inarrow(self
, (x
, y
)):
111 cl
, ct
, cr
, cb
= self
._list
.LRect((0, 0))
112 l
, t
, r
, b
= self
._bounds
115 index
= (y
- ct
) / cellheight
116 if index
< len(self
.items
):
120 def incolumn(self
, (x
, y
)):
121 l
, t
, r
, b
= self
._list
.LRect((0, 0))
122 abscol
= l
+ self
.col
123 return abs(abscol
- x
) < 3
125 def trackcolumn(self
, (x
, y
)):
126 import Qd
, QuickDraw
, Evt
128 l
, t
, r
, b
= self
._bounds
129 bounds
= l
, t
, r
, b
= l
+ 1, t
+ 1, r
- 16, b
- 1
130 abscol
= l
+ self
.col
131 mincol
= l
+ self
.mincol
134 Qd
.PenPat('\000\377\000\377\000\377\000\377')
135 Qd
.PenMode(QuickDraw
.srcXor
)
136 rect
= abscol
- 1, t
, abscol
, b
142 (x
, y
) = Evt
.GetMouse()
143 if (x
, y
) <> lastpoint
:
145 newcol
= max(newcol
, mincol
)
146 newcol
= min(newcol
, maxcol
)
148 rect
= newcol
- 1, t
, newcol
, b
152 Qd
.PenPat(Qd
.qd
.black
)
154 if newcol
> 0 and newcol
<> abscol
:
155 self
.setcolumn(newcol
- l
)
157 def click(self
, point
, modifiers
):
158 if point
== (-1, -1): # gross.
159 W
.List
.click(self
, point
,modifiers
)
161 hit
, index
= self
.inarrow(point
)
163 (key
, value
, arrow
, indent
) = self
.items
[index
]
164 self
.fold(index
, arrow
== 1)
165 elif self
.incolumn(point
):
166 self
.trackcolumn(point
)
168 W
.List
.click(self
, point
, modifiers
)
171 def findmatch(self
, tag
):
177 for i
in range(len(items
)):
178 item
= lower(str(items
[i
][0]))
179 if tag
<= item
< match
:
185 return len(items
) - 1
188 if self
.closechildren
:
189 for window
in self
.children
:
194 def fold(self
, index
, onoff
):
195 (key
, value
, arrow
, indent
) = self
.items
[index
]
196 if arrow
== 0 or (onoff
and arrow
== 2) or (not onoff
and arrow
== 1):
199 topcell
= self
.gettopcell()
201 self
[index
] = (key
, value
, 4, indent
)
202 self
.setdrawingmode(0)
203 self
[index
+1:index
+1] = self
.unpack(value
, indent
+ 1)
204 self
[index
] = (key
, value
, 2, indent
)
206 self
[index
] = (key
, value
, 3, indent
)
207 self
.setdrawingmode(0)
209 for i
in range(index
+ 1, len(self
.items
)):
210 (dummy
, dummy
, dummy
, subindent
) = self
.items
[i
]
211 if subindent
<= indent
:
214 self
[index
+1:index
+1+count
] = []
215 self
[index
] = (key
, value
, 1, indent
)
216 maxindent
= self
.getmaxindent()
217 if maxindent
<> self
.lastmaxindent
:
218 newabsindent
= self
.col
+ (maxindent
- self
.lastmaxindent
) * self
.indent
219 if newabsindent
>= self
.mincol
:
220 self
.setcolumn(newabsindent
)
221 self
.lastmaxindent
= maxindent
222 self
.settopcell(topcell
)
223 self
.setdrawingmode(1)
225 def unfoldobjects(self
, objects
):
228 index
= self
.items
.index(obj
)
234 def getunfoldedobjects(self
):
237 for index
in range(len(self
.items
)):
238 (key
, value
, arrow
, indent
) = self
.items
[index
]
239 if indent
> curindent
:
240 (k
, v
, a
, i
) = self
.items
[index
- 1]
241 objects
.append((k
, v
, 1, i
))
243 elif indent
< curindent
:
247 def listhit(self
, isdbl
):
251 def openselection(self
):
253 sel
= self
.getselection()
255 (key
, value
, arrow
, indent
) = self
[index
]
257 self
.children
.append(Browser(value
))
258 elif type(value
) == types
.StringType
and '\0' not in value
:
259 editor
= self
._parentwindow
.parent
.getscript(value
)
263 elif os
.path
.exists(value
) and os
.path
.isfile(value
):
265 fss
= macfs
.FSSpec(value
)
266 if fss
.GetCreatorType()[1] == 'TEXT':
267 W
.getapplication().openscript(value
)
269 def itemrepr(self
, (key
, value
, arrow
, indent
), str = str, double_repr
= double_repr
,
270 arrows
= arrows
, pack
= struct
.pack
):
271 arrow
= arrows
[arrow
]
272 return arrow
+ pack('h', self
.indent
* indent
) + self
.colstr
+ \
273 double_repr(key
, value
, 1)
275 def getmaxindent(self
, max = max):
277 for item
in self
.items
:
278 maxindent
= max(maxindent
, item
[3])
281 def domenu_copy(self
, *args
):
282 sel
= self
.getselectedobjects()
284 for key
, value
, dummy
, dummy
in sel
:
285 selitems
.append(double_repr(key
, value
))
286 text
= string
.join(selitems
, '\r')
290 Scrap
.PutScrap('TEXT', text
)
295 def __init__(self
, object = None, title
= None, closechildren
= 0):
296 if hasattr(object, '__name__'):
297 name
= object.__name
__
301 title
= 'Object browser'
303 title
= title
+ ': ' + name
304 self
.w
= w
= W
.Window((300, 400), title
, minsize
= (100, 100))
305 w
.info
= W
.TextBox((18, 8, -70, 15))
306 w
.updatebutton
= W
.Button((-64, 4, 50, 16), 'Update', self
.update
)
307 w
.browser
= BrowserWidget((-1, 24, 1, -14), None)
308 w
.bind('cmdu', w
.updatebutton
.push
)
310 self
.set(object, name
)
316 def set(self
, object, name
= ''):
318 tp
= type(object).__name
__
323 if not name
and hasattr(object, '__name__'):
324 name
= object.__name
__
326 info
= name
+ ': ' + tp
331 info
= info
+ ' (%d element)' % length
333 info
= info
+ ' (%d elements)' % length
334 self
.w
.info
.set(info
)
335 self
.w
.browser
.set(object)
338 self
.w
.browser
.update()
356 def unpack_object(object, indent
= 0):
358 if tp
in SIMPLE_TYPES
and tp
is not types
.NoneType
:
359 raise TypeError, 'can¹t browse simple type: %s' % tp
.__name
__
360 elif tp
== types
.DictionaryType
:
361 return unpack_dict(object, indent
)
362 elif tp
in (types
.TupleType
, types
.ListType
):
363 return unpack_sequence(object, indent
)
364 elif tp
== types
.InstanceType
:
365 return unpack_instance(object, indent
)
366 elif tp
== types
.ClassType
:
367 return unpack_class(object, indent
)
368 elif tp
== types
.ModuleType
:
369 return unpack_dict(object.__dict
__, indent
)
371 return unpack_other(object, indent
)
373 def unpack_sequence(seq
, indent
= 0):
374 items
= map(None, range(len(seq
)), seq
)
375 items
= map(lambda (k
, v
), type = type, simp
= SIMPLE_TYPES
, indent
= indent
:
376 (k
, v
, not type(v
) in simp
, indent
), items
)
379 def unpack_dict(dict, indent
= 0):
381 return pack_items(items
, indent
)
383 def unpack_instance(inst
, indent
= 0):
384 if hasattr(inst
, '__pybrowse_unpack__'):
385 return unpack_object(inst
.__pybrowse
_unpack
__(), indent
)
387 items
= [('__class__', inst
.__class
__)] + inst
.__dict
__.items()
388 return pack_items(items
, indent
)
390 def unpack_class(clss
, indent
= 0):
391 items
= [('__bases__', clss
.__bases
__), ('__name__', clss
.__name
__)] + clss
.__dict
__.items()
392 return pack_items(items
, indent
)
394 def unpack_other(object, indent
= 0):
396 if hasattr(object, '__members__'):
397 attrs
= attrs
+ object.__members
__
398 if hasattr(object, '__methods__'):
399 attrs
= attrs
+ object.__methods
__
402 items
.append((attr
, getattr(object, attr
)))
403 return pack_items(items
, indent
)
405 def pack_items(items
, indent
= 0):
406 items
= map(lambda (k
, v
), type = type, simp
= SIMPLE_TYPES
, indent
= indent
:
407 (k
, v
, not type(v
) in simp
, indent
),
409 return tuple_caselesssort(items
)
411 def caselesssort(alist
):
412 """Return a sorted copy of a list. If there are only strings in the list,
413 it will not consider case"""
416 # turn ['FOO', 'aaBc', 'ABcD'] into [('foo', 'FOO'), ('aabc', 'aaBc'), ('abcd', 'ABcD')], if possible
417 tupledlist
= map(lambda item
, lower
= string
.lower
: (lower(item
), item
), alist
)
419 # at least one element in alist is not a string, proceed the normal way...
425 # turn [('aabc', 'aaBc'), ('abcd', 'ABcD'), ('foo', 'FOO')] into ['aaBc', 'ABcD', 'FOO']
426 return map(lambda x
: x
[1], tupledlist
)
428 def tuple_caselesssort(items
):
430 tupledlist
= map(lambda tuple, lower
= string
.lower
: (lower(tuple[0]), tuple), items
)
437 return map(lambda (low
, tuple): tuple, tupledlist
)