Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 1 | import W |
| 2 | import Wkeys |
| 3 | import struct |
| 4 | import string |
| 5 | import types |
Jack Jansen | 9ad2752 | 2001-02-21 13:54:31 +0000 | [diff] [blame] | 6 | import re |
Just van Rossum | 4e6d13c | 2002-03-26 12:06:11 +0000 | [diff] [blame] | 7 | from Carbon import Qd, Icn, Fm, QuickDraw |
| 8 | from Carbon.List import GetListPort |
| 9 | from Carbon.QuickDraw import hilitetransfermode |
| 10 | |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 11 | |
| 12 | nullid = '\0\0' |
| 13 | closedid = struct.pack('h', 468) |
| 14 | openid = struct.pack('h', 469) |
| 15 | closedsolidid = struct.pack('h', 470) |
| 16 | opensolidid = struct.pack('h', 471) |
| 17 | |
| 18 | arrows = (nullid, closedid, openid, closedsolidid, opensolidid) |
| 19 | |
Just van Rossum | 3eec762 | 2001-07-10 19:25:40 +0000 | [diff] [blame] | 20 | has_ctlcharsRE = re.compile(r'[\000-\037\177-\377]') |
Jack Jansen | 9ad2752 | 2001-02-21 13:54:31 +0000 | [diff] [blame] | 21 | def ctlcharsREsearch(str): |
Jack Jansen | dbd0c3a | 2001-03-01 23:15:54 +0000 | [diff] [blame] | 22 | if has_ctlcharsRE.search(str) is None: |
Jack Jansen | 9ad2752 | 2001-02-21 13:54:31 +0000 | [diff] [blame] | 23 | return -1 |
| 24 | return 1 |
| 25 | |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 26 | def double_repr(key, value, truncvalue = 0, |
| 27 | type = type, StringType = types.StringType, |
Jack Jansen | 9ad2752 | 2001-02-21 13:54:31 +0000 | [diff] [blame] | 28 | has_ctlchars = ctlcharsREsearch, _repr = repr, str = str): |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 29 | if type(key) == StringType and has_ctlchars(key) < 0: |
| 30 | key = str(key) |
| 31 | else: |
| 32 | key = _repr(key) |
Just van Rossum | 460ff20 | 1999-10-30 11:43:25 +0000 | [diff] [blame] | 33 | if key == '__builtins__': |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 34 | value = "<" + type(value).__name__ + " '__builtin__'>" |
| 35 | elif key == '__return__': |
| 36 | # bleh, when returning from a class codeblock we get infinite recursion in repr. |
| 37 | # Use safe repr instead. |
| 38 | import repr |
| 39 | value = repr.repr(value) |
| 40 | else: |
| 41 | try: |
| 42 | value = _repr(value) |
| 43 | '' + value # test to see if it is a string, in case a __repr__ method is buggy |
| 44 | except: |
Just van Rossum | dc3c617 | 2001-06-19 21:37:33 +0000 | [diff] [blame] | 45 | value = '\xa5\xa5\xa5 exception in repr()' |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 46 | if truncvalue: |
| 47 | return key + '\t' + value[:255] |
| 48 | return key + '\t' + value |
| 49 | |
| 50 | |
Just van Rossum | 4e6d13c | 2002-03-26 12:06:11 +0000 | [diff] [blame] | 51 | def truncString(s, maxwid): |
| 52 | if maxwid < 1: |
| 53 | return 1, "" |
| 54 | strlen = len(s) |
| 55 | strwid = Qd.TextWidth(s, 0, strlen); |
| 56 | if strwid <= maxwid: |
| 57 | return 0, s |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 58 | |
Just van Rossum | 4e6d13c | 2002-03-26 12:06:11 +0000 | [diff] [blame] | 59 | Qd.TextFace(QuickDraw.condense) |
| 60 | strwid = Qd.TextWidth(s, 0, strlen) |
| 61 | ellipsis = Qd.StringWidth('\xc9') |
| 62 | |
| 63 | if strwid <= maxwid: |
| 64 | Qd.TextFace(0) |
| 65 | return 1, s |
| 66 | if strwid < 1: |
| 67 | Qd.TextFace(0) |
| 68 | return 1, "" |
| 69 | |
| 70 | mid = int(strlen * maxwid / strwid) |
| 71 | while 1: |
| 72 | if mid <= 0: |
| 73 | mid = 0 |
| 74 | break |
| 75 | strwid = Qd.TextWidth(s, 0, mid) + ellipsis |
| 76 | strwid2 = Qd.TextWidth(s, 0, mid + 1) + ellipsis |
| 77 | if strwid <= maxwid and maxwid <= strwid2: |
| 78 | if maxwid == strwid2: |
| 79 | mid += 1 |
| 80 | break |
| 81 | if strwid > maxwid: |
| 82 | mid -= 1 |
| 83 | if mid <= 0: |
| 84 | mid = 0 |
| 85 | break |
| 86 | elif strwid2 < maxwid: |
| 87 | mid += 1 |
| 88 | Qd.TextFace(0) |
| 89 | return 1, s[:mid] + '\xc9' |
| 90 | |
| 91 | |
| 92 | def drawTextCell(text, cellRect, ascent, theList): |
| 93 | l, t, r, b = cellRect |
| 94 | cellwidth = r - l |
| 95 | Qd.MoveTo(l + 2, t + ascent) |
| 96 | condense, text = truncString(text, cellwidth - 3) |
| 97 | if condense: |
| 98 | Qd.TextFace(QuickDraw.condense) |
| 99 | Qd.DrawText(text, 0, len(text)) |
| 100 | Qd.TextFace(0) |
| 101 | |
| 102 | |
| 103 | PICTWIDTH = 16 |
| 104 | |
| 105 | |
| 106 | class BrowserWidget(W.CustomList): |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 107 | |
| 108 | def __init__(self, possize, object = None, col = 100, closechildren = 0): |
| 109 | W.List.__init__(self, possize, callback = self.listhit) |
| 110 | self.object = (None,) |
| 111 | self.indent = 16 |
| 112 | self.lastmaxindent = 0 |
| 113 | self.closechildren = closechildren |
| 114 | self.children = [] |
| 115 | self.mincol = 64 |
| 116 | self.setcolumn(col) |
| 117 | self.bind('return', self.openselection) |
| 118 | self.bind('enter', self.openselection) |
| 119 | if object is not None: |
| 120 | self.set(object) |
| 121 | |
| 122 | def set(self, object): |
| 123 | if self.object[0] is not object: |
| 124 | self.object = object, |
| 125 | self[:] = self.unpack(object, 0) |
| 126 | elif self._parentwindow is not None and self._parentwindow.wid: |
| 127 | self.update() |
| 128 | |
| 129 | def unpack(self, object, indent): |
| 130 | return unpack_object(object, indent) |
| 131 | |
| 132 | def update(self): |
| 133 | # for now... |
| 134 | W.SetCursor('watch') |
| 135 | self.setdrawingmode(0) |
| 136 | sel = self.getselectedobjects() |
| 137 | fold = self.getunfoldedobjects() |
| 138 | topcell = self.gettopcell() |
| 139 | self[:] = self.unpack(self.object[0], 0) |
| 140 | self.unfoldobjects(fold) |
| 141 | self.setselectedobjects(sel) |
| 142 | self.settopcell(topcell) |
| 143 | self.setdrawingmode(1) |
| 144 | |
| 145 | def setcolumn(self, col): |
| 146 | self.col = col |
| 147 | self.colstr = struct.pack('h', col) |
| 148 | if self._list: |
| 149 | sel = self.getselection() |
| 150 | self.setitems(self.items) |
| 151 | self.setselection(sel) |
| 152 | |
| 153 | def key(self, char, event): |
| 154 | if char in (Wkeys.leftarrowkey, Wkeys.rightarrowkey): |
| 155 | sel = self.getselection() |
| 156 | sel.reverse() |
| 157 | self.setdrawingmode(0) |
| 158 | for index in sel: |
| 159 | self.fold(index, char == Wkeys.rightarrowkey) |
| 160 | self.setdrawingmode(1) |
| 161 | else: |
| 162 | W.List.key(self, char, event) |
| 163 | |
| 164 | def rollover(self, (x, y), onoff): |
| 165 | if onoff: |
| 166 | if self.incolumn((x, y)): |
| 167 | W.SetCursor('hmover') |
| 168 | else: |
| 169 | W.SetCursor('arrow') |
| 170 | |
| 171 | def inarrow(self, (x, y)): |
| 172 | cl, ct, cr, cb = self._list.LRect((0, 0)) |
| 173 | l, t, r, b = self._bounds |
| 174 | if (x - cl) < 16: |
| 175 | cellheight = cb - ct |
| 176 | index = (y - ct) / cellheight |
| 177 | if index < len(self.items): |
| 178 | return 1, index |
| 179 | return None, None |
| 180 | |
| 181 | def incolumn(self, (x, y)): |
| 182 | l, t, r, b = self._list.LRect((0, 0)) |
| 183 | abscol = l + self.col |
| 184 | return abs(abscol - x) < 3 |
| 185 | |
| 186 | def trackcolumn(self, (x, y)): |
Jack Jansen | 5a6fdcd | 2001-08-25 12:15:04 +0000 | [diff] [blame] | 187 | from Carbon import Qd, QuickDraw, Evt |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 188 | self.SetPort() |
| 189 | l, t, r, b = self._bounds |
| 190 | bounds = l, t, r, b = l + 1, t + 1, r - 16, b - 1 |
| 191 | abscol = l + self.col |
| 192 | mincol = l + self.mincol |
| 193 | maxcol = r - 10 |
| 194 | diff = abscol - x |
| 195 | Qd.PenPat('\000\377\000\377\000\377\000\377') |
| 196 | Qd.PenMode(QuickDraw.srcXor) |
| 197 | rect = abscol - 1, t, abscol, b |
| 198 | Qd.PaintRect(rect) |
| 199 | lastpoint = (x, y) |
| 200 | newcol = -1 |
| 201 | #W.SetCursor('fist') |
| 202 | while Evt.Button(): |
Just van Rossum | f376ef0 | 2001-11-18 14:12:43 +0000 | [diff] [blame] | 203 | Evt.WaitNextEvent(0, 1, None) # needed for OSX |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 204 | (x, y) = Evt.GetMouse() |
| 205 | if (x, y) <> lastpoint: |
| 206 | newcol = x + diff |
| 207 | newcol = max(newcol, mincol) |
| 208 | newcol = min(newcol, maxcol) |
| 209 | Qd.PaintRect(rect) |
| 210 | rect = newcol - 1, t, newcol, b |
| 211 | Qd.PaintRect(rect) |
| 212 | lastpoint = (x, y) |
| 213 | Qd.PaintRect(rect) |
| 214 | Qd.PenPat(Qd.qd.black) |
| 215 | Qd.PenNormal() |
| 216 | if newcol > 0 and newcol <> abscol: |
| 217 | self.setcolumn(newcol - l) |
| 218 | |
| 219 | def click(self, point, modifiers): |
| 220 | if point == (-1, -1): # gross. |
| 221 | W.List.click(self, point ,modifiers) |
| 222 | return |
| 223 | hit, index = self.inarrow(point) |
| 224 | if hit: |
| 225 | (key, value, arrow, indent) = self.items[index] |
| 226 | self.fold(index, arrow == 1) |
| 227 | elif self.incolumn(point): |
| 228 | self.trackcolumn(point) |
| 229 | else: |
| 230 | W.List.click(self, point, modifiers) |
| 231 | |
| 232 | # for W.List.key |
| 233 | def findmatch(self, tag): |
| 234 | lower = string.lower |
| 235 | items = self.items |
| 236 | taglen = len(tag) |
| 237 | match = '\377' * 100 |
| 238 | match_i = -1 |
| 239 | for i in range(len(items)): |
| 240 | item = lower(str(items[i][0])) |
| 241 | if tag <= item < match: |
| 242 | match = item |
| 243 | match_i = i |
| 244 | if match_i >= 0: |
| 245 | return match_i |
| 246 | else: |
| 247 | return len(items) - 1 |
| 248 | |
| 249 | def close(self): |
| 250 | if self.closechildren: |
| 251 | for window in self.children: |
| 252 | window.close() |
| 253 | self.children = [] |
| 254 | W.List.close(self) |
| 255 | |
| 256 | def fold(self, index, onoff): |
| 257 | (key, value, arrow, indent) = self.items[index] |
| 258 | if arrow == 0 or (onoff and arrow == 2) or (not onoff and arrow == 1): |
| 259 | return |
| 260 | W.SetCursor('watch') |
| 261 | topcell = self.gettopcell() |
| 262 | if onoff: |
| 263 | self[index] = (key, value, 4, indent) |
| 264 | self.setdrawingmode(0) |
| 265 | self[index+1:index+1] = self.unpack(value, indent + 1) |
| 266 | self[index] = (key, value, 2, indent) |
| 267 | else: |
| 268 | self[index] = (key, value, 3, indent) |
| 269 | self.setdrawingmode(0) |
| 270 | count = 0 |
| 271 | for i in range(index + 1, len(self.items)): |
| 272 | (dummy, dummy, dummy, subindent) = self.items[i] |
| 273 | if subindent <= indent: |
| 274 | break |
| 275 | count = count + 1 |
| 276 | self[index+1:index+1+count] = [] |
| 277 | self[index] = (key, value, 1, indent) |
| 278 | maxindent = self.getmaxindent() |
| 279 | if maxindent <> self.lastmaxindent: |
| 280 | newabsindent = self.col + (maxindent - self.lastmaxindent) * self.indent |
| 281 | if newabsindent >= self.mincol: |
| 282 | self.setcolumn(newabsindent) |
| 283 | self.lastmaxindent = maxindent |
| 284 | self.settopcell(topcell) |
| 285 | self.setdrawingmode(1) |
| 286 | |
| 287 | def unfoldobjects(self, objects): |
| 288 | for obj in objects: |
| 289 | try: |
| 290 | index = self.items.index(obj) |
| 291 | except ValueError: |
| 292 | pass |
| 293 | else: |
| 294 | self.fold(index, 1) |
| 295 | |
| 296 | def getunfoldedobjects(self): |
| 297 | curindent = 0 |
| 298 | objects = [] |
| 299 | for index in range(len(self.items)): |
| 300 | (key, value, arrow, indent) = self.items[index] |
| 301 | if indent > curindent: |
| 302 | (k, v, a, i) = self.items[index - 1] |
| 303 | objects.append((k, v, 1, i)) |
| 304 | curindent = indent |
| 305 | elif indent < curindent: |
| 306 | curindent = indent |
| 307 | return objects |
| 308 | |
| 309 | def listhit(self, isdbl): |
| 310 | if isdbl: |
| 311 | self.openselection() |
| 312 | |
| 313 | def openselection(self): |
| 314 | import os |
| 315 | sel = self.getselection() |
| 316 | for index in sel: |
| 317 | (key, value, arrow, indent) = self[index] |
| 318 | if arrow: |
| 319 | self.children.append(Browser(value)) |
| 320 | elif type(value) == types.StringType and '\0' not in value: |
| 321 | editor = self._parentwindow.parent.getscript(value) |
| 322 | if editor: |
| 323 | editor.select() |
| 324 | return |
| 325 | elif os.path.exists(value) and os.path.isfile(value): |
| 326 | import macfs |
| 327 | fss = macfs.FSSpec(value) |
| 328 | if fss.GetCreatorType()[1] == 'TEXT': |
| 329 | W.getapplication().openscript(value) |
| 330 | |
| 331 | def itemrepr(self, (key, value, arrow, indent), str = str, double_repr = double_repr, |
| 332 | arrows = arrows, pack = struct.pack): |
| 333 | arrow = arrows[arrow] |
| 334 | return arrow + pack('h', self.indent * indent) + self.colstr + \ |
| 335 | double_repr(key, value, 1) |
| 336 | |
| 337 | def getmaxindent(self, max = max): |
| 338 | maxindent = 0 |
| 339 | for item in self.items: |
| 340 | maxindent = max(maxindent, item[3]) |
| 341 | return maxindent |
| 342 | |
| 343 | def domenu_copy(self, *args): |
| 344 | sel = self.getselectedobjects() |
| 345 | selitems = [] |
| 346 | for key, value, dummy, dummy in sel: |
| 347 | selitems.append(double_repr(key, value)) |
| 348 | text = string.join(selitems, '\r') |
| 349 | if text: |
Just van Rossum | 01c9805 | 2001-11-02 19:21:34 +0000 | [diff] [blame] | 350 | from Carbon import Scrap |
Jack Jansen | 6529368 | 2001-12-31 15:08:04 +0000 | [diff] [blame] | 351 | if hasattr(Scrap, 'PutScrap'): |
| 352 | Scrap.ZeroScrap() |
| 353 | Scrap.PutScrap('TEXT', text) |
| 354 | else: |
| 355 | Scrap.ClearCurrentScrap() |
| 356 | sc = Scrap.GetCurrentScrap() |
| 357 | sc.PutScrapFlavor('TEXT', 0, text) |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 358 | |
Just van Rossum | 4e6d13c | 2002-03-26 12:06:11 +0000 | [diff] [blame] | 359 | def listDefDraw(self, selected, cellRect, theCell, |
| 360 | dataOffset, dataLen, theList): |
| 361 | self.myDrawCell(0, selected, cellRect, theCell, |
| 362 | dataOffset, dataLen, theList) |
| 363 | |
| 364 | def listDefHighlight(self, selected, cellRect, theCell, |
| 365 | dataOffset, dataLen, theList): |
| 366 | self.myDrawCell(1, selected, cellRect, theCell, |
| 367 | dataOffset, dataLen, theList) |
| 368 | |
| 369 | def myDrawCell(self, onlyHilite, selected, cellRect, theCell, |
| 370 | dataOffset, dataLen, theList): |
| 371 | savedPort = Qd.GetPort() |
| 372 | Qd.SetPort(GetListPort(theList)) |
| 373 | savedClip = Qd.NewRgn() |
| 374 | Qd.GetClip(savedClip) |
| 375 | Qd.ClipRect(cellRect) |
| 376 | savedPenState = Qd.GetPenState() |
| 377 | Qd.PenNormal() |
| 378 | |
| 379 | l, t, r, b = cellRect |
| 380 | |
| 381 | if not onlyHilite: |
| 382 | Qd.EraseRect(cellRect) |
| 383 | |
| 384 | ascent, descent, leading, size, hm = Fm.FontMetrics() |
| 385 | linefeed = ascent + descent + leading |
| 386 | |
| 387 | if dataLen >= 6: |
| 388 | data = theList.LGetCell(dataLen, theCell) |
| 389 | iconId, indent, tab = struct.unpack("hhh", data[:6]) |
Just van Rossum | 3c4dee4 | 2002-09-16 21:18:49 +0000 | [diff] [blame] | 390 | try: |
| 391 | key, value = data[6:].split("\t", 1) |
| 392 | except ValueError: |
| 393 | # bogus data, at least don't crash. |
| 394 | indent = 0 |
| 395 | tab = 0 |
| 396 | iconId = 0 |
| 397 | key = "" |
| 398 | value = data[6:] |
Just van Rossum | 4e6d13c | 2002-03-26 12:06:11 +0000 | [diff] [blame] | 399 | |
| 400 | if iconId: |
Just van Rossum | 3c4dee4 | 2002-09-16 21:18:49 +0000 | [diff] [blame] | 401 | try: |
| 402 | theIcon = Icn.GetCIcon(iconId) |
| 403 | except Icn.Error: |
| 404 | pass |
| 405 | else: |
| 406 | rect = (0, 0, 16, 16) |
| 407 | rect = Qd.OffsetRect(rect, l, t) |
| 408 | rect = Qd.OffsetRect(rect, 0, (theList.cellSize[1] - (rect[3] - rect[1])) / 2) |
| 409 | Icn.PlotCIcon(rect, theIcon) |
Just van Rossum | 4e6d13c | 2002-03-26 12:06:11 +0000 | [diff] [blame] | 410 | |
| 411 | if len(key) >= 0: |
| 412 | cl, ct, cr, cb = cellRect |
| 413 | vl, vt, vr, vb = self._viewbounds |
| 414 | cl = vl + PICTWIDTH + indent |
| 415 | cr = vl + tab |
| 416 | if cr > vr: |
| 417 | cr = vr |
| 418 | if cl < cr: |
| 419 | drawTextCell(key, (cl, ct, cr, cb), ascent, theList) |
| 420 | cl = vl + tab |
| 421 | cr = vr |
| 422 | if cl < cr: |
| 423 | drawTextCell(value, (cl, ct, cr, cb), ascent, theList) |
| 424 | #elif dataLen != 0: |
| 425 | # drawTextCell("???", 3, cellRect, ascent, theList) |
Just van Rossum | 3c4dee4 | 2002-09-16 21:18:49 +0000 | [diff] [blame] | 426 | else: |
| 427 | return # we have bogus data |
Just van Rossum | 4e6d13c | 2002-03-26 12:06:11 +0000 | [diff] [blame] | 428 | |
| 429 | # draw nice dotted line |
| 430 | l, t, r, b = cellRect |
| 431 | l = self._viewbounds[0] + tab |
| 432 | r = l + 1; |
| 433 | if not (theList.cellSize[1] & 0x01) or (t & 0x01): |
| 434 | myPat = "\xff\x00\xff\x00\xff\x00\xff\x00" |
| 435 | else: |
| 436 | myPat = "\x00\xff\x00\xff\x00\xff\x00\xff" |
| 437 | Qd.PenPat(myPat) |
| 438 | Qd.PenMode(QuickDraw.srcCopy) |
| 439 | Qd.PaintRect((l, t, r, b)) |
| 440 | Qd.PenNormal() |
| 441 | |
| 442 | if selected or onlyHilite: |
| 443 | l, t, r, b = cellRect |
| 444 | l = self._viewbounds[0] + PICTWIDTH |
| 445 | r = self._viewbounds[2] |
| 446 | Qd.PenMode(hilitetransfermode) |
| 447 | Qd.PaintRect((l, t, r, b)) |
| 448 | |
| 449 | # restore graphics environment |
| 450 | Qd.SetPort(savedPort) |
| 451 | Qd.SetClip(savedClip) |
| 452 | Qd.DisposeRgn(savedClip) |
| 453 | Qd.SetPenState(savedPenState) |
| 454 | |
| 455 | |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 456 | |
| 457 | class Browser: |
| 458 | |
| 459 | def __init__(self, object = None, title = None, closechildren = 0): |
| 460 | if hasattr(object, '__name__'): |
| 461 | name = object.__name__ |
| 462 | else: |
| 463 | name = '' |
| 464 | if title is None: |
| 465 | title = 'Object browser' |
| 466 | if name: |
| 467 | title = title + ': ' + name |
| 468 | self.w = w = W.Window((300, 400), title, minsize = (100, 100)) |
| 469 | w.info = W.TextBox((18, 8, -70, 15)) |
Just van Rossum | f376ef0 | 2001-11-18 14:12:43 +0000 | [diff] [blame] | 470 | w.updatebutton = W.BevelButton((-64, 4, 50, 16), 'Update', self.update) |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 471 | w.browser = BrowserWidget((-1, 24, 1, -14), None) |
| 472 | w.bind('cmdu', w.updatebutton.push) |
| 473 | w.open() |
| 474 | self.set(object, name) |
| 475 | |
| 476 | def close(self): |
| 477 | if self.w.wid: |
| 478 | self.w.close() |
| 479 | |
| 480 | def set(self, object, name = ''): |
| 481 | W.SetCursor('watch') |
| 482 | tp = type(object).__name__ |
| 483 | try: |
| 484 | length = len(object) |
| 485 | except: |
| 486 | length = -1 |
| 487 | if not name and hasattr(object, '__name__'): |
| 488 | name = object.__name__ |
| 489 | if name: |
| 490 | info = name + ': ' + tp |
| 491 | else: |
| 492 | info = tp |
| 493 | if length >= 0: |
| 494 | if length == 1: |
| 495 | info = info + ' (%d element)' % length |
| 496 | else: |
| 497 | info = info + ' (%d elements)' % length |
| 498 | self.w.info.set(info) |
| 499 | self.w.browser.set(object) |
| 500 | |
| 501 | def update(self): |
| 502 | self.w.browser.update() |
| 503 | |
| 504 | |
| 505 | SIMPLE_TYPES = ( |
| 506 | types.NoneType, |
| 507 | types.IntType, |
| 508 | types.LongType, |
| 509 | types.FloatType, |
| 510 | types.ComplexType, |
| 511 | types.StringType |
| 512 | ) |
| 513 | |
| 514 | INDEXING_TYPES = ( |
| 515 | types.TupleType, |
| 516 | types.ListType, |
| 517 | types.DictionaryType |
| 518 | ) |
| 519 | |
| 520 | def unpack_object(object, indent = 0): |
| 521 | tp = type(object) |
| 522 | if tp in SIMPLE_TYPES and tp is not types.NoneType: |
Just van Rossum | dc3c617 | 2001-06-19 21:37:33 +0000 | [diff] [blame] | 523 | raise TypeError, "can't browse simple type: %s" % tp.__name__ |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 524 | elif tp == types.DictionaryType: |
| 525 | return unpack_dict(object, indent) |
| 526 | elif tp in (types.TupleType, types.ListType): |
| 527 | return unpack_sequence(object, indent) |
| 528 | elif tp == types.InstanceType: |
| 529 | return unpack_instance(object, indent) |
| 530 | elif tp == types.ClassType: |
| 531 | return unpack_class(object, indent) |
| 532 | elif tp == types.ModuleType: |
| 533 | return unpack_dict(object.__dict__, indent) |
| 534 | else: |
| 535 | return unpack_other(object, indent) |
| 536 | |
| 537 | def unpack_sequence(seq, indent = 0): |
| 538 | items = map(None, range(len(seq)), seq) |
| 539 | items = map(lambda (k, v), type = type, simp = SIMPLE_TYPES, indent = indent: |
| 540 | (k, v, not type(v) in simp, indent), items) |
| 541 | return items |
| 542 | |
| 543 | def unpack_dict(dict, indent = 0): |
| 544 | items = dict.items() |
| 545 | return pack_items(items, indent) |
| 546 | |
| 547 | def unpack_instance(inst, indent = 0): |
| 548 | if hasattr(inst, '__pybrowse_unpack__'): |
| 549 | return unpack_object(inst.__pybrowse_unpack__(), indent) |
| 550 | else: |
| 551 | items = [('__class__', inst.__class__)] + inst.__dict__.items() |
| 552 | return pack_items(items, indent) |
| 553 | |
| 554 | def unpack_class(clss, indent = 0): |
| 555 | items = [('__bases__', clss.__bases__), ('__name__', clss.__name__)] + clss.__dict__.items() |
| 556 | return pack_items(items, indent) |
| 557 | |
| 558 | def unpack_other(object, indent = 0): |
| 559 | attrs = [] |
| 560 | if hasattr(object, '__members__'): |
| 561 | attrs = attrs + object.__members__ |
| 562 | if hasattr(object, '__methods__'): |
| 563 | attrs = attrs + object.__methods__ |
Just van Rossum | bdb9d48 | 2001-12-31 08:57:57 +0000 | [diff] [blame] | 564 | if hasattr(object, '__dict__'): |
| 565 | attrs = attrs + object.__dict__.keys() |
| 566 | if hasattr(object, '__slots__'): |
| 567 | # XXX?? |
| 568 | attrs = attrs + object.__slots__ |
| 569 | if hasattr(object, "__class__") and "__class__" not in attrs: |
| 570 | attrs.append("__class__") |
| 571 | if hasattr(object, "__doc__") and "__doc__" not in attrs: |
| 572 | attrs.append("__doc__") |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 573 | items = [] |
| 574 | for attr in attrs: |
| 575 | items.append((attr, getattr(object, attr))) |
| 576 | return pack_items(items, indent) |
| 577 | |
| 578 | def pack_items(items, indent = 0): |
| 579 | items = map(lambda (k, v), type = type, simp = SIMPLE_TYPES, indent = indent: |
| 580 | (k, v, not type(v) in simp, indent), |
| 581 | items) |
| 582 | return tuple_caselesssort(items) |
| 583 | |
| 584 | def caselesssort(alist): |
| 585 | """Return a sorted copy of a list. If there are only strings in the list, |
| 586 | it will not consider case""" |
| 587 | |
| 588 | try: |
| 589 | # turn ['FOO', 'aaBc', 'ABcD'] into [('foo', 'FOO'), ('aabc', 'aaBc'), ('abcd', 'ABcD')], if possible |
| 590 | tupledlist = map(lambda item, lower = string.lower: (lower(item), item), alist) |
| 591 | except TypeError: |
| 592 | # at least one element in alist is not a string, proceed the normal way... |
| 593 | alist = alist[:] |
| 594 | alist.sort() |
| 595 | return alist |
| 596 | else: |
| 597 | tupledlist.sort() |
| 598 | # turn [('aabc', 'aaBc'), ('abcd', 'ABcD'), ('foo', 'FOO')] into ['aaBc', 'ABcD', 'FOO'] |
| 599 | return map(lambda x: x[1], tupledlist) |
| 600 | |
| 601 | def tuple_caselesssort(items): |
| 602 | try: |
| 603 | tupledlist = map(lambda tuple, lower = string.lower: (lower(tuple[0]), tuple), items) |
Just van Rossum | 6508c7c | 2000-10-20 06:34:57 +0000 | [diff] [blame] | 604 | except (AttributeError, TypeError): |
Just van Rossum | 40f9b7b | 1999-01-30 22:39:17 +0000 | [diff] [blame] | 605 | items = items[:] |
| 606 | items.sort() |
| 607 | return items |
| 608 | else: |
| 609 | tupledlist.sort() |
| 610 | return map(lambda (low, tuple): tuple, tupledlist) |
| 611 | |