Index: third_party/twisted_8_1/twisted/manhole/ui/spelunk_gnome.py |
diff --git a/third_party/twisted_8_1/twisted/manhole/ui/spelunk_gnome.py b/third_party/twisted_8_1/twisted/manhole/ui/spelunk_gnome.py |
deleted file mode 100644 |
index 72a509d6ea665d138fdada576220259d0c2551d0..0000000000000000000000000000000000000000 |
--- a/third_party/twisted_8_1/twisted/manhole/ui/spelunk_gnome.py |
+++ /dev/null |
@@ -1,665 +0,0 @@ |
-# -*- Python -*- |
-# Copyright (c) 2001-2004 Twisted Matrix Laboratories. |
-# See LICENSE for details. |
- |
- |
-"""Object browser GUI, GnomeCanvas implementation. |
-""" |
- |
-from twisted.python import log |
- |
-# TODO: |
-# gzigzag-style navigation |
- |
-class SillyModule: |
- def __init__(self, module, prefix): |
- self.__module = module |
- self.__prefix = prefix |
- |
- def __getattr__(self, attr): |
- try: |
- return getattr(self.__module, self.__prefix + attr) |
- except AttributeError: |
- return getattr(self.__module, attr) |
- |
- |
-# We use gnome.ui because that's what happens to have Python bindings |
-# for the Canvas. I think this canvas widget is available seperately |
-# in "libart", but nobody's given me Python bindings for just that. |
- |
-# The Gnome canvas is said to be modeled after the Tk canvas, so we |
-# could probably write this in Tk too. But my experience is with GTK, |
-# not with Tk, so this is what I use. |
- |
-import gnome.ui |
-gnome = SillyModule(gnome.ui, 'Gnome') |
- |
-import gtk |
-(True, False) = (gtk.TRUE, gtk.FALSE) |
-gtk = SillyModule(gtk, 'Gtk') |
- |
-import GDK |
- |
-from twisted.python import reflect, text |
-from twisted.spread import pb |
-from twisted.manhole import explorer |
- |
-import string, sys, types |
-import UserList |
-_PIXELS_PER_UNIT=10 |
- |
-#### Support class. |
- |
-class PairList(UserList.UserList): |
- """An ordered list of key, value pairs. |
- |
- Kinda like an ordered dictionary. Made with small data sets |
- in mind, as get() does a linear search, not hashing. |
- """ |
- def get(self, key): |
- i = 0 |
- for k, v in self.data: |
- if key == k: |
- return (i, v) |
- i = i + 1 |
- else: |
- return (None, None) |
- |
- def keys(self): |
- return map(lambda x: x[0], self.data) |
- |
- |
-#### Public |
- |
-class SpelunkDisplay(gnome.Canvas): |
- """Spelunk widget. |
- |
- The top-level widget for this module. This gtk.Widget is where the |
- explorer display will be, and this object is also your interface to |
- creating new visages. |
- """ |
- def __init__(self, aa=False): |
- gnome.Canvas.__init__(self, aa) |
- self.set_pixels_per_unit(_PIXELS_PER_UNIT) |
- self.visages = {} |
- |
- def makeDefaultCanvas(self): |
- """Make myself the default canvas which new visages are created on. |
- """ |
- # XXX: For some reason, the 'canvas' and 'parent' properties |
- # of CanvasItems aren't accessible thorugh pygnome. |
- Explorer.canvas = self |
- |
- def receiveExplorer(self, xplorer): |
- if self.visages.has_key(xplorer.id): |
- log.msg("Using cached visage for %d" % (xplorer.id, )) |
- # Ikk. Just because we just received this explorer, that |
- # doesn't necessarily mean its attributes are fresh. Fix |
- # that, either by having this side pull or the server |
- # side push. |
- visage = self.visages[xplorer.id] |
- #xplorer.give_properties(visage) |
- #xplorer.give_attributes(visage) |
- else: |
- log.msg("Making new visage for %d" % (xplorer.id, )) |
- self.visages[xplorer.id] = xplorer.newVisage(self.root(), |
- self) |
- |
-#### Base classes |
- |
-class Explorer(pb.RemoteCache): |
- """Base class for all RemoteCaches of explorer.Explorer cachables. |
- |
- Meaning that when an Explorer comes back over the wire, one of |
- these is created. From this, you can make a Visage for the |
- SpelunkDisplay, or a widget to display as an Attribute. |
- """ |
- canvas = None |
- # From our cache: |
- id = None |
- identifier = None |
- explorerClass = None |
- attributeGroups = None |
- |
- def newVisage(self, group, canvas=None): |
- """Make a new visage for the object I explore. |
- |
- Returns a Visage. |
- """ |
- canvas = canvas or self.canvas |
- klass = spelunkerClassTable.get(self.explorerClass, None) |
- if (not klass) or (klass[0] is None): |
- log.msg("%s not in table, using generic" % self.explorerClass) |
- klass = GenericVisage |
- else: |
- klass = klass[0] |
- spelunker = klass(self, group, canvas) |
- if hasattr(canvas, "visages") \ |
- and not canvas.visages.has_key(self.id): |
- canvas.visages[self.id] = spelunker |
- |
- self.give_properties(spelunker) |
- |
- self.give_attributes(spelunker) |
- |
- return spelunker |
- |
- def newAttributeWidget(self, group): |
- """Make a new attribute item for my object. |
- |
- Returns a gtk.Widget. |
- """ |
- klass = spelunkerClassTable.get(self.explorerClass, None) |
- if (not klass) or (klass[1] is None): |
- log.msg("%s not in table, using generic" % self.explorerClass) |
- klass = GenericAttributeWidget |
- else: |
- klass = klass[1] |
- |
- return klass(self, group) |
- |
- def give_properties(self, spelunker): |
- """Give a spelunker my properties in an ordered list. |
- """ |
- valuelist = PairList() |
- for p in spelunker.propertyLabels.keys(): |
- value = getattr(self, p, None) |
- valuelist.append((p,value)) |
- spelunker.fill_properties(valuelist) |
- |
- def give_attributes(self, spelunker): |
- for a in spelunker.groupLabels.keys(): |
- things = getattr(self, a) |
- spelunker.fill_attributeGroup(a, things) |
- |
-class _LooseBoxBorder: |
- box = None |
- color = 'black' |
- width = 1 |
- def __init__(self, box): |
- self.box = box |
- |
-class LooseBox(gnome.CanvasGroup): |
- def __init__(self): |
- self.border = _LooseBoxBorder(self) |
- |
-class Visage(gnome.CanvasGroup): |
- """A \"face\" of an object under exploration. |
- |
- A Visage is a representation of an object presented to the user. |
- The \"face\" in \"interface\". |
- |
- 'propertyLabels' and 'groupLabels' are lists of (key, name) |
- 2-ples, with 'key' being the string the property or group is |
- denoted by in the code, and 'name' being the pretty human-readable |
- string you want me to show on the Visage. These attributes are |
- accumulated from base classes as well. |
- |
- I am a gnome.CanvasItem (more specifically, CanvasGroup). |
- """ |
- color = {'border': '#006644'} |
- border_width = 8 |
- detail_level = 0 |
- # These are mappings from the strings the code calls these by |
- # and the pretty names you want to see on the screen. |
- # (e.g. Capitalized or localized) |
- propertyLabels = [] |
- groupLabels = [] |
- |
- drag_x0 = 0 |
- drag_y0 = 0 |
- |
- def __init__(self, explorer, rootGroup, canvas): |
- """Place a new Visage of an explorer in a canvas group. |
- |
- I also need a 'canvas' reference is for certain coordinate |
- conversions, and pygnome doesn't give access to my GtkObject's |
- .canvas attribute. :( |
- """ |
- # Ugh. PyGtk/GtkObject/GnomeCanvas interfacing grits. |
- gnome.CanvasGroup.__init__(self, |
- _obj = rootGroup.add('group')._o) |
- |
- self.propertyLabels = PairList() |
- reflect.accumulateClassList(self.__class__, 'propertyLabels', |
- self.propertyLabels) |
- self.groupLabels = PairList() |
- reflect.accumulateClassList(self.__class__, 'groupLabels', |
- self.groupLabels) |
- |
- self.explorer = explorer |
- self.identifier = explorer.identifier |
- self.objectId = explorer.id |
- |
- self.canvas = canvas |
- self.rootGroup = rootGroup |
- |
- self.ebox = gtk.EventBox() |
- self.ebox.set_name("Visage") |
- self.frame = gtk.Frame(self.identifier) |
- self.container = gtk.VBox() |
- self.ebox.add(self.frame) |
- self.frame.add(self.container) |
- |
- self.canvasWidget = self.add('widget', widget=self.ebox, |
- x=0, y=0, anchor=gtk.ANCHOR_NW, |
- size_pixels=0) |
- |
- self.border = self.add('rect', x1=0, y1=0, |
- x2=1, y2=1, |
- fill_color=None, |
- outline_color=self.color['border'], |
- width_pixels=self.border_width) |
- |
- self.subtable = {} |
- |
- self._setup_table() |
- |
- # TODO: |
- # Collapse me |
- # Movable/resizeable me |
- # Destroy me |
- # Set my detail level |
- |
- self.frame.connect("size_allocate", self.signal_size_allocate, |
- None) |
- self.connect("destroy", self.signal_destroy, None) |
- self.connect("event", self.signal_event) |
- |
- self.ebox.show_all() |
- |
- # Our creator will call our fill_ methods when she has the goods. |
- |
- def _setup_table(self): |
- """Called by __init__ to set up my main table. |
- |
- You can easily override me instead of clobbering __init__. |
- """ |
- |
- table = gtk.Table(len(self.propertyLabels), 2) |
- self.container.add(table) |
- table.set_name("PropertyTable") |
- self.subtable['properties'] = table |
- row = 0 |
- |
- for p, name in self.propertyLabels: |
- label = gtk.Label(name) |
- label.set_name("PropertyName") |
- label.set_data("property", p) |
- table.attach(label, 0, 1, row, row + 1) |
- label.set_alignment(0, 0) |
- row = row + 1 |
- |
- # XXX: make these guys collapsable |
- for g, name in self.groupLabels: |
- table = gtk.Table(1, 2) |
- self.container.add(table) |
- table.set_name("AttributeGroupTable") |
- self.subtable[g] = table |
- label = gtk.Label(name) |
- label.set_name("AttributeGroupTitle") |
- table.attach(label, 0, 2, 0, 1) |
- |
- def fill_properties(self, propValues): |
- """Fill in values for my properites. |
- |
- Takes a list of (name, value) pairs. 'name' should be one of |
- the keys in my propertyLabels, and 'value' either an Explorer |
- or a string. |
- """ |
- table = self.subtable['properties'] |
- |
- table.resize(len(propValues), 2) |
- |
- # XXX: Do I need to destroy previously attached children? |
- |
- for name, value in propValues: |
- self.fill_property(name, value) |
- |
- table.show_all() |
- |
- def fill_property(self, property, value): |
- """Set a value for a particular property. |
- |
- 'property' should be one of the keys in my propertyLabels. |
- """ |
- row, name = self.propertyLabels.get(property) |
- if type(value) is not types.InstanceType: |
- widget = gtk.Label(str(value)) |
- widget.set_alignment(0, 0) |
- else: |
- widget = value.newAttributeWidget(self) |
- widget.set_name("PropertyValue") |
- |
- self.subtable['properties'].attach(widget, 1, 2, row, row+1) |
- |
- def fill_attributeGroup(self, group, attributes): |
- """Provide members of an attribute group. |
- |
- 'group' should be one of the keys in my groupLabels, and |
- 'attributes' a list of (name, value) pairs, with each value as |
- either an Explorer or string. |
- """ |
- |
- # XXX: How to indicate detail level of members? |
- |
- table = self.subtable[group] |
- if not attributes: |
- table.hide() |
- return |
- |
- table.resize(len(attributes)+1, 2) |
- |
- # XXX: Do I need to destroy previously attached children? |
- |
- row = 1 # 0 is title |
- |
- for name, value in attributes.items(): |
- label = gtk.Label(name) |
- label.set_name("AttributeName") |
- label.set_alignment(0, 0) |
- |
- if type(value) is types.StringType: |
- widget = gtk.Label(value) |
- widget.set_alignment(0, 0) |
- else: |
- widget = value.newAttributeWidget(self) |
- |
- table.attach(label, 0, 1, row, row + 1) |
- table.attach(widget, 1, 2, row, row + 1) |
- row = row + 1 |
- |
- table.show_all() |
- |
- def signal_event(self, widget, event=None): |
- if not event: |
- log.msg("Huh? got event signal with no event.") |
- return |
- if event.type == GDK.BUTTON_PRESS: |
- if event.button == 1: |
- self.drag_x0, self.drag_y0 = event.x, event.y |
- return True |
- elif event.type == GDK.MOTION_NOTIFY: |
- if event.state & GDK.BUTTON1_MASK: |
- self.move(event.x - self.drag_x0, event.y - self.drag_y0) |
- self.drag_x0, self.drag_y0 = event.x, event.y |
- return True |
- return False |
- |
- def signal_size_allocate(self, frame_widget, |
- unusable_allocation, unused_data): |
- (x, y, w, h) = frame_widget.get_allocation() |
- |
- # XXX: allocation PyCObject is apparently unusable! |
- # (w, h) = allocation.width, allocation.height |
- |
- w, h = (float(w)/_PIXELS_PER_UNIT, float(h)/_PIXELS_PER_UNIT) |
- |
- x1, y1 = (self.canvasWidget['x'], self.canvasWidget['y']) |
- |
- b = self.border |
- (b['x1'], b['y1'], b['x2'], b['y2']) = (x1, y1, x1+w, y1+h) |
- |
- def signal_destroy(self, unused_object, unused_data): |
- del self.explorer |
- |
- del self.canvasWidget |
- del self.border |
- |
- del self.ebox |
- del self.frame |
- del self.container |
- |
- self.subtable.clear() |
- |
- |
-class AttributeWidget(gtk.Widget): |
- """A widget briefly describing an object. |
- |
- This is similar to a Visage, but has far less detail. This should |
- display only essential identifiying information, a gtk.Widget |
- suitable for including in a single table cell. |
- |
- (gtk.Widgets are used here instead of the more graphically |
- pleasing gnome.CanvasItems because I was too lazy to re-write |
- gtk.table for the canvas. A new table widget/item would be great |
- though, not only for canvas prettiness, but also because we could |
- use one with a mone pythonic API.) |
- |
- """ |
- def __init__(self, explorer, parent): |
- """A new AttributeWidget describing an explorer. |
- """ |
- self.parent = parent |
- |
- self.explorer = explorer |
- self.identifier = explorer.identifier |
- self.id = explorer.id |
- |
- widgetObj = self._makeWidgetObject() |
- gtk.Widget.__init__(self, _obj=widgetObj) |
- self.set_name("AttributeValue") |
- self.connect("destroy", self.signal_destroy, None) |
- self.connect("button-press-event", self.signal_buttonPressEvent, |
- None) |
- |
- def getTextForLabel(self): |
- """Returns text for my label. |
- |
- The default implementation of AttributeWidget is a gtk.Label |
- widget. You may override this method to change the text which |
- appears in the label. However, if you don't want to be a |
- label, override _makeWidgetObject instead. |
- """ |
- return self.identifier |
- |
- def _makeWidgetObject(self): |
- """Make the GTK widget object that is me. |
- |
- Called by __init__ to construct the GtkObject I wrap-- the ._o |
- member of a pygtk GtkObject. Isn't subclassing GtkObjects in |
- Python fun? |
- """ |
- ebox = gtk.EventBox() |
- label = gtk.Label(self.getTextForLabel()) |
- label.set_alignment(0,0) |
- ebox.add(label) |
- return ebox._o |
- |
- def signal_destroy(self, unused_object, unused_data): |
- del self.explorer |
- |
- def signal_buttonPressEvent(self, widget, eventButton, unused_data): |
- if eventButton.type == GDK._2BUTTON_PRESS: |
- if self.parent.canvas.visages.has_key(self.explorer.id): |
- visage = self.parent.canvas.visages[self.explorer.id] |
- else: |
- visage = self.explorer.newVisage(self.parent.rootGroup, |
- self.parent.canvas) |
- (x, y, w, h) = self.get_allocation() |
- wx, wy = self.parent.canvas.c2w(x, y) |
- |
- x1, y1, x2, y2 = self.parent.get_bounds() |
- |
- v_x1, v_y1, v_x2, v_y2 = visage.get_bounds() |
- |
- visage.move(x2 - v_x1, wy + y1 - v_y1) |
- |
- |
-#### Widget-specific subclasses of Explorer, Visage, and Attribute |
- |
-# Instance |
- |
-class ExplorerInstance(Explorer): |
- pass |
- |
-class InstanceVisage(Visage): |
- # Detail levels: |
- # Just me |
- # me and my class |
- # me and my whole class heirarchy |
- |
- propertyLabels = [('klass', "Class")] |
- groupLabels = [('data', "Data"), |
- ('methods', "Methods")] |
- |
- detail = 0 |
- |
- def __init__(self, explorer, group, canvas): |
- Visage.__init__(self, explorer, group, canvas) |
- |
- class_identifier = self.explorer.klass.name |
- # XXX: include partial module name in class? |
- self.frame.set_label("%s (%s)" % (self.identifier, |
- class_identifier)) |
- |
-class InstanceAttributeWidget(AttributeWidget): |
- def getTextForLabel(self): |
- return "%s instance" % (self.explorer.klass.name,) |
- |
- |
-# Class |
- |
-class ExplorerClass(Explorer): |
- pass |
- |
-class ClassVisage(Visage): |
- propertyLabels = [("name", "Name"), |
- ("module", "Module"), |
- ("bases", "Bases")] |
- groupLabels = [('data', "Data"), |
- ('methods', "Methods")] |
- |
- def fill_properties(self, propValues): |
- Visage.fill_properties(self, propValues) |
- basesExplorer = propValues.get('bases')[1] |
- basesExplorer.view.callRemote("get_elements").addCallback(self.fill_bases) |
- |
- def fill_bases(self, baseExplorers): |
- box = gtk.HBox() |
- for b in baseExplorers: |
- box.add(b.newAttributeWidget(self)) |
- row = self.propertyLabels.get('bases')[0] |
- self.subtable["properties"].attach(box, 1, 2, row, row+1) |
- box.show_all() |
- |
-class ClassAttributeWidget(AttributeWidget): |
- def getTextForLabel(self): |
- return self.explorer.name |
- |
- |
-# Function |
- |
-class ExplorerFunction(Explorer): |
- pass |
- |
-class FunctionAttributeWidget(AttributeWidget): |
- def getTextForLabel(self): |
- signature = self.explorer.signature |
- arglist = [] |
- for arg in xrange(len(signature)): |
- name = signature.name[arg] |
- hasDefault, default = signature.get_default(arg) |
- if hasDefault: |
- if default.explorerClass == "ExplorerImmutable": |
- default = default.value |
- else: |
- # XXX |
- pass |
- a = "%s=%s" % (name, default) |
- elif signature.is_varlist(arg): |
- a = "*%s" % (name,) |
- elif signature.is_keyword(arg): |
- a = "**%s" % (name,) |
- else: |
- a = name |
- arglist.append(a) |
- |
- return string.join(arglist, ", ") |
- |
- |
-# Method |
- |
-class ExplorerMethod(ExplorerFunction): |
- pass |
- |
-class MethodAttributeWidget(FunctionAttributeWidget): |
- pass |
- |
-class ExplorerBulitin(Explorer): |
- pass |
- |
-class ExplorerModule(Explorer): |
- pass |
- |
-class ExplorerSequence(Explorer): |
- pass |
- |
- |
-# Sequence |
- |
-class SequenceVisage(Visage): |
- propertyLabels = [('len', 'length')] |
- # XXX: add elements group |
- |
-class SequenceAttributeWidget(AttributeWidget): |
- def getTextForLabel(self): |
- # XXX: Differentiate between lists and tuples. |
- if self.explorer.len: |
- txt = "list of length %d" % (self.explorer.len,) |
- else: |
- txt = "[]" |
- return txt |
- |
- |
-# Mapping |
- |
-class ExplorerMapping(Explorer): |
- pass |
- |
-class MappingVisage(Visage): |
- propertyLabels = [('len', 'length')] |
- # XXX: add items group |
- |
-class MappingAttributeWidget(AttributeWidget): |
- def getTextForLabel(self): |
- if self.explorer.len: |
- txt = "dict with %d elements" % (self.explorer.len,) |
- else: |
- txt = "{}" |
- return txt |
- |
-class ExplorerImmutable(Explorer): |
- pass |
- |
- |
-# Immutable |
- |
-class ImmutableVisage(Visage): |
- def __init__(self, explorer, rootGroup, canvas): |
- Visage.__init__(self, explorer, rootGroup, canvas) |
- widget = explorer.newAttributeWidget(self) |
- self.container.add(widget) |
- self.container.show_all() |
- |
-class ImmutableAttributeWidget(AttributeWidget): |
- def getTextForLabel(self): |
- return repr(self.explorer.value) |
- |
- |
-#### misc. module definitions |
- |
-spelunkerClassTable = { |
- "ExplorerInstance": (InstanceVisage, InstanceAttributeWidget), |
- "ExplorerFunction": (None, FunctionAttributeWidget), |
- "ExplorerMethod": (None, MethodAttributeWidget), |
- "ExplorerImmutable": (ImmutableVisage, ImmutableAttributeWidget), |
- "ExplorerClass": (ClassVisage, ClassAttributeWidget), |
- "ExplorerSequence": (SequenceVisage, SequenceAttributeWidget), |
- "ExplorerMapping": (MappingVisage, MappingAttributeWidget), |
- } |
-GenericVisage = Visage |
-GenericAttributeWidget = AttributeWidget |
- |
-pb.setCopierForClassTree(sys.modules[__name__], |
- Explorer, 'twisted.manhole.explorer') |