[z3-checkins] r14900 - in z3/zopejam/trunk/src: . zcmledit zopejam

hathawsh at codespeak.net hathawsh at codespeak.net
Fri Jul 22 08:55:07 CEST 2005


Author: hathawsh
Date: Fri Jul 22 08:55:00 2005
New Revision: 14900

Added:
   z3/zopejam/trunk/src/debugjam   (contents, props changed)
   z3/zopejam/trunk/src/runjam   (contents, props changed)
Modified:
   z3/zopejam/trunk/src/zcmledit/configfile.py
   z3/zopejam/trunk/src/zcmledit/directives.py
   z3/zopejam/trunk/src/zcmledit/project.py
   z3/zopejam/trunk/src/zopejam/columns.py
   z3/zopejam/trunk/src/zopejam/main.py
   z3/zopejam/trunk/src/zopejam/propbook.py
   z3/zopejam/trunk/src/zopejam/resources.xrc
Log:
Property editing window (currently displays, but doesn't change anything)

Also added quick, hard coded, development-only launch scripts.


Added: z3/zopejam/trunk/src/debugjam
==============================================================================
--- (empty file)
+++ z3/zopejam/trunk/src/debugjam	Fri Jul 22 08:55:00 2005
@@ -0,0 +1,9 @@
+#!/bin/sh
+WX_BASE=/home/shane/wx26
+JAM_BASE=/home/shane/svn/zopejam
+ZOPE_BASE=/home/shane/svn/Zope3
+
+. $WX_BASE/profile
+export PYTHONPATH=$JAM_BASE/src:$ZOPE_BASE/src/:$WX_BASE/lib/python2.4/site-packages/wx-2.6-gtk2-ansi
+export ZOPEJAM_PROJECT=$ZOPE_BASE/site.zcml
+python $JAM_BASE/src/zopejam/main.py

Added: z3/zopejam/trunk/src/runjam
==============================================================================
--- (empty file)
+++ z3/zopejam/trunk/src/runjam	Fri Jul 22 08:55:00 2005
@@ -0,0 +1,6 @@
+#!/bin/sh
+JAM_BASE=/home/shane/svn/zopejam
+ZOPE_BASE=/home/shane/svn/Zope3
+export PYTHONPATH=$JAM_BASE/src:$ZOPE_BASE/src/
+export ZOPEJAM_PROJECT=$ZOPE_BASE/site.zcml
+python $JAM_BASE/src/zopejam/main.py

Modified: z3/zopejam/trunk/src/zcmledit/configfile.py
==============================================================================
--- z3/zopejam/trunk/src/zcmledit/configfile.py	(original)
+++ z3/zopejam/trunk/src/zcmledit/configfile.py	Fri Jul 22 08:55:00 2005
@@ -95,6 +95,18 @@
 
         return t(element)
 
+    def getAbbreviatedFilename(self):
+        if self.package_name:
+            basename = os.path.basename(self.filename)
+            if basename == 'configure.zcml':
+                text = self.package_name
+            else:
+                text = '%s "%s"' % (self.package_name, basename)
+        elif self.project is not None:
+            text = '"%s"' % self.project.shortenPath(self.filename)
+        else:
+            text = '"%s"' % self.filename
+        return text
 
     def generateXML(self):
         """Returns a list of XML lines."""

Modified: z3/zopejam/trunk/src/zcmledit/directives.py
==============================================================================
--- z3/zopejam/trunk/src/zcmledit/directives.py	(original)
+++ z3/zopejam/trunk/src/zcmledit/directives.py	Fri Jul 22 08:55:00 2005
@@ -14,6 +14,7 @@
 from zcmledit.exceptions import InvalidRelativeNameError, MissingPackageError
 
 meta_ns = u"http://namespaces.zope.org/meta"
+nzo_prefix = 'http://namespaces.zope.org/'
 
 
 class Directive(object):
@@ -71,6 +72,20 @@
         else:
             return project.definitions.get(self.element.name)
 
+    def getTypeName(self):
+        """Returns a type name like 'http://namespaces.zope.org/zope:view'"""
+        ns, localname = self.element.name
+        if interfaces.IGenericNamespaceDirective.providedBy(self):
+            return '*:%s' % localname
+        return '%s:%s' % (ns, localname)
+
+    def getAbbreviatedTypeName(self):
+        """Returns a shortened directive type name like 'zope:view'"""
+        name = self.getTypeName()
+        if name.startswith(nzo_prefix):
+            name = name[len(nzo_prefix):]
+        return name
+
 
 class ConfigureDirective(Directive):
     implements(interfaces.IConfigureDirective)
@@ -111,7 +126,7 @@
         self.errors = []
 
         # If there is bad data in the directive, add to self.errors
-        # rather than raise an exception so that the error can be
+        # rather than raise an exception, so that the error can be
         # presented in a helpful way at a later time.
 
         if self.files and self.file:
@@ -221,6 +236,17 @@
     def getSchemaInfo(self):
         return self.project.interfaces[self.abs_schema]
 
+    def getTypeName(self):
+        """Returns a type name like 'http://namespaces.zope.org/zope:view'"""
+        return '%s:%s' % self.fullname
+
+    def getAbbreviatedTypeName(self):
+        """Returns a shortened directive type name like 'zope:view'"""
+        name = self.getTypeName()
+        if name.startswith(nzo_prefix):
+            name = name[len(nzo_prefix):]
+        return name
+
 
 class CommonDirective(Directive):
     implements(interfaces.IDirective)

Modified: z3/zopejam/trunk/src/zcmledit/project.py
==============================================================================
--- z3/zopejam/trunk/src/zcmledit/project.py	(original)
+++ z3/zopejam/trunk/src/zcmledit/project.py	Fri Jul 22 08:55:00 2005
@@ -171,6 +171,7 @@
         self.sro = [all_interfaces[name] for name in self.sro_names]
 
     def getField(self, k):
+        """Returns a field by name, possibly inherited, or None"""
         v = self.fields.get(k)
         if v is not None:
             return v
@@ -180,3 +181,12 @@
                 return v
         return None
 
+    def getAllFields(self):
+        """Returns all fields, including inherited fields, in a map"""
+        res = self.fields.copy()
+        for info in self.sro:
+            for k, v in info.fields.items():
+                if not res.has_key(k):
+                    res[k] = v
+        return res
+

Modified: z3/zopejam/trunk/src/zopejam/columns.py
==============================================================================
--- z3/zopejam/trunk/src/zopejam/columns.py	(original)
+++ z3/zopejam/trunk/src/zopejam/columns.py	Fri Jul 22 08:55:00 2005
@@ -10,8 +10,6 @@
 from zcmledit.exceptions import NameResolutionError
 from zcmledit import interfaces
 
-nzo_prefix = 'http://namespaces.zope.org/'
-
 
 class Column:
     label = ''
@@ -58,18 +56,9 @@
     indent = True
 
     def getText(self, d):
-        cfg = d.element.config_file
-        if cfg.package_name:
-            basename = os.path.basename(cfg.filename)
-            if basename == 'configure.zcml':
-                text = cfg.package_name
-            else:
-                text = '%s "%s"' % (cfg.package_name, basename)
-        elif cfg.project is not None:
-            text = '"%s"' % cfg.project.shortenPath(cfg.filename)
-        else:
-            text = '"%s"' % cfg.filename
-        return text
+        if d.element is None:
+            return ''
+        return d.element.config_file.getAbbreviatedFilename()
 
     def getSortKey(self, d):
         cfg = d.element.config_file
@@ -81,18 +70,10 @@
     default_width = 150
 
     def getText(self, d):
-        ns, localname = d.element.name
-        if interfaces.IGenericNamespaceDirective.providedBy(d):
-            ns = '*'
-        elif ns.startswith(nzo_prefix):
-            ns = ns[len(nzo_prefix):]
-        return '%s:%s' % (ns, localname)
+        return d.getAbbreviatedTypeName()
 
     def getSortKey(self, d):
-        ns, localname = d.element.name
-        if interfaces.IGenericNamespaceDirective.providedBy(d):
-            ns = '*'
-        return (ns, localname)
+        return d.getTypeName()
 
 
 class NameOrId(Column):

Modified: z3/zopejam/trunk/src/zopejam/main.py
==============================================================================
--- z3/zopejam/trunk/src/zopejam/main.py	(original)
+++ z3/zopejam/trunk/src/zopejam/main.py	Fri Jul 22 08:55:00 2005
@@ -488,10 +488,14 @@
             index = self.indexes[item]
             selected.append(self.directives[index])
             item = self.GetNextSelected(item)
-        self.gui.book.onSelect(selected)
+        self.gui.book.populate(selected)
 
     def selectDirectives(self, selected):
-        """Selects a specific set of directives"""
+        """Selects a specific set of directives.
+
+        Selects items in the directive list and asks the property
+        notebook to do the same.
+        """
         self.suppress_select_event = True
         try:
             d = {}
@@ -506,7 +510,7 @@
                     self.SetItemState(i, flag, flag)
                 elif not want_sel and state:
                     self.SetItemState(i, 0, flag)
-            self.gui.book.onSelect(selected)
+            self.gui.book.populate(selected)
         finally:
             self.suppress_select_event = False
 

Modified: z3/zopejam/trunk/src/zopejam/propbook.py
==============================================================================
--- z3/zopejam/trunk/src/zopejam/propbook.py	(original)
+++ z3/zopejam/trunk/src/zopejam/propbook.py	Fri Jul 22 08:55:00 2005
@@ -8,34 +8,152 @@
 import wx
 import wx.grid
 from wx import xrc
+from wx.lib import scrolledpanel
 
 from zopejam import columns
 
+nzo_prefix = 'http://namespaces.zope.org/'
+
 
 class PropertiesNotebook:
 
     def __init__(self, gui, notebook):
         self.gui = gui
         self.notebook = notebook
-##        self.props_page = wx.ScrolledWindow(self.notebook)
-##        self.props_page.SetSizer(wx.BoxSizer(wx.VERTICAL))
-##        self.props_page.SetScrollRate(0, 20)
-        self.props_page = wx.Panel(self.notebook)
-        sizer = wx.BoxSizer(wx.VERTICAL)
-        self.props_page.SetSizer(sizer)
-        self.notebook.AddPage(self.props_page, "Properties")
+
+        self.edit_page = wx.Panel(self.notebook)
+        self.edit_page.SetSizer(wx.BoxSizer(wx.VERTICAL))
+        self.notebook.AddPage(self.edit_page, "Properties")
+        self.pedit = PropertyEditor(self.gui, self.edit_page)
 
         self.grid_page = wx.Panel(self.notebook)
-        sizer = wx.BoxSizer(wx.VERTICAL)
-        self.grid_page.SetSizer(sizer)
+        self.grid_page.SetSizer(wx.BoxSizer(wx.VERTICAL))
         self.notebook.AddPage(self.grid_page, "Grid")
         self.pgrid = PropertyGrid(self.gui, self.grid_page)
 
         self.source_page = wx.Panel(self.notebook)
         self.notebook.AddPage(self.source_page, "Source")
 
-    def onSelect(self, directives):
-        self.pgrid.onSelect(directives)
+    def populate(self, directives):
+        self.pedit.populate(directives)
+        self.pgrid.populate(directives)
+
+
+class PropertyEditor:
+
+    def __init__(self, gui, panel):
+        self.gui = gui
+        self.panel = panel
+        self.win = None
+        self.directive = None
+        self.info = None  # An InterfaceInfo or None
+
+    def populate(self, directives):
+        self.panel.DestroyChildren()
+        if len(directives) == 1:
+            self.directive = directives[0]
+            t = self.directive.getType()
+            if t is None:
+                self.addLabel(
+                    "Directive type '%s:%s' not found"
+                    % self.directive.element.name, error=True)
+            else:
+                self.win = scrolledpanel.ScrolledPanel(self.panel)
+                self.win.SetSizer(wx.BoxSizer(wx.VERTICAL))
+                self.panel.GetSizer().Add(
+                    self.win, proportion=1, flag=wx.EXPAND)
+                self.info = t.getSchemaInfo()
+                if self.info.error:
+                    self.addLabel(
+                        "Error loading schema %s:\n"
+                        "%s" % (self.info.name, self.info.error), error=True)
+                self.addHeader()
+                self.addFields()
+                self.panel.Layout()
+                self.win.SetupScrolling(scroll_x=False)
+        elif not directives:
+            self.directive = None
+            self.addLabel("No directives are selected.")
+        else:
+            self.directive = None
+            self.addLabel(
+                "More than one directive is selected.  "
+                "Use the grid tab to manage multiple directives.")
+        self.panel.Layout()
+
+    def addLabel(self, text, error=False):
+        label = wx.StaticText(self.panel, -1, text)
+        if error:
+            label.SetForegroundColour(wx.RED)
+        self.panel.GetSizer().Add(label, flag=wx.EXPAND|wx.ALL, border=4)
+
+    def addHeader(self):
+        win_bg = self.win.GetBackgroundColour()
+        bg = wx.Colour(
+            win_bg.Red() * 9 / 10,
+            win_bg.Green() * 9 / 10,
+            win_bg.Blue() * 9 / 10)
+
+        sizer = wx.FlexGridSizer(rows=0, cols=2, vgap=4, hgap=4)
+        self.win.GetSizer().Add(sizer, flag=wx.EXPAND|wx.ALL, border=4)
+        sizer.AddGrowableCol(1)
+
+        label = wx.StaticText(self.win, -1, "Source File")
+        sizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL)
+
+        if self.directive.element is not None:
+            cfg = self.directive.element.config_file
+            fn = cfg.getAbbreviatedFilename()
+            if cfg.filename not in fn:
+                fn += '  -  %s' % cfg.filename
+        else:
+            fn = ''
+        ctrl = wx.TextCtrl(
+            self.win, -1, fn, style=wx.NO_BORDER|wx.TE_READONLY)
+        ctrl.SetBackgroundColour(bg)
+        sizer.Add(ctrl, flag=wx.EXPAND)
+
+        label = wx.StaticText(self.win, -1, "Directive")
+        sizer.Add(label, flag=wx.ALIGN_CENTER_VERTICAL)
+
+        type_name = self.directive.getAbbreviatedTypeName()
+        full = self.directive.getTypeName()
+        if type_name != full:
+            type_name += '  -  %s' % full
+        ctrl = wx.TextCtrl(
+            self.win, -1, type_name, style=wx.NO_BORDER|wx.TE_READONLY)
+        ctrl.SetBackgroundColour(bg)
+        sizer.Add(ctrl, flag=wx.EXPAND)
+
+
+    def addFields(self):
+        sizer = wx.FlexGridSizer(rows=0, cols=4, vgap=4, hgap=8)
+        self.win.GetSizer().Add(sizer, flag=wx.EXPAND|wx.ALL, border=4)
+        sizer.AddGrowableCol(2)
+
+        fields = self.info.getAllFields().items()
+        # Show required fields first, then order by name
+        ordered = [(v.required and 1 or 2, k, v) for k, v in fields]
+        ordered.sort()
+        for sort_key, name, field in ordered:
+            xml_attr = name
+            if xml_attr.endswith('_'):
+                xml_attr = xml_attr[:-1]
+            value = self.directive.element.data.get(xml_attr, '')
+
+            label = wx.StaticText(
+                self.win, -1, field.required and '*' or '')
+            sizer.Add(label)
+
+            label = wx.StaticText(self.win, -1, xml_attr)
+            sizer.Add(label)
+
+            edit = wx.TextCtrl(self.win, -1, value)
+            sizer.Add(edit, flag=wx.EXPAND)
+
+            label = wx.StaticText(self.win, -1, field.title)
+            sizer.Add(label)
+            
 
 
 class PropertyGrid:
@@ -49,7 +167,7 @@
         self.resize_timer.Bind(wx.EVT_TIMER, self.resizeOneColumn)
         self.grid = None
         
-    def onSelect(self, directives):
+    def populate(self, directives):
         self.panel.DestroyChildren()
         sizer = self.panel.GetSizer()
         if directives:
@@ -67,7 +185,7 @@
                            self.onSelectCell)
         else:
             label = wx.StaticText(
-                self.panel, -1, "No directives selected.")
+                self.panel, -1, "No directives are selected.")
             sizer.Add(label, flag=wx.EXPAND|wx.ALL, border=4)
         self.panel.Layout()
 
@@ -89,58 +207,80 @@
             if self.next_resize_column < cols:
                 self.resize_timer.Start(100, oneShot=True)
 
+    def popup(self, menu, item_names, event):
+        for name in item_names:
+            id = xrc.XRCID(name)
+            menu.Bind(wx.EVT_MENU, getattr(self, 'on_menu_%s' % name), id=id)
+        x, y = event.GetPosition()
+        if event.GetRow() < 0 and y >= 0:
+            # bug workaround: user clicked a column header, but
+            # sometimes wx reports a mouse position outside the
+            # range of the column header.
+            y -= self.grid.GetColLabelSize()
+        if event.GetCol() < 0 and x >= 0:
+            # same bug applies to row headers
+            x -= self.grid.GetRowLabelSize()
+        self.grid.PopupMenu(menu, (x, y))
+        menu.Destroy()
+
     def onRightClickCell(self, event):
+        self.grid.SetGridCursor(event.GetRow(), event.GetCol())
         if not self.grid.IsInSelection(event.GetRow(), event.GetCol()):
-            self.grid.SetGridCursor(event.GetRow(), event.GetCol())
             self.grid.SelectBlock(
                 event.GetRow(), event.GetCol(),
                 event.GetRow(), event.GetCol(),
                 addToSelected=False)
         menu = self.gui.resources.LoadMenu('grid_popup')
-        for name in ['show_selected', 'resize', 'cut',
-                     'copy', 'paste', 'clear']:
-            id = xrc.XRCID(name)
-            menu.Bind(wx.EVT_MENU, getattr(self, 'on_menu_%s' % name), id=id)
-        self.grid.PopupMenu(menu, event.GetPosition())
-        menu.Destroy()
+        self.popup(menu, ['show_selected', 'filter', 'resize', 'cut',
+                          'copy', 'paste', 'clear'], event)
 
     def onRightClickLabel(self, event):
         row = event.GetRow()
         if row < 0:
-            return
-        if not self.grid.IsInSelection(event.GetRow(), 0):
-            self.grid.SelectRow(row)
-        menu = wx.Menu()
-        menu.Append(xrc.XRCID('show_selected'), "&Show selected directive(s)")
-        for name in ['show_selected']:
-            id = xrc.XRCID(name)
-            menu.Bind(wx.EVT_MENU, getattr(self, 'on_menu_%s' % name), id=id)
-        self.grid.PopupMenu(menu, event.GetPosition())
-        menu.Destroy()
+            # Clicked a column label
+            menu = wx.Menu()
+            menu.Append(xrc.XRCID('resize'),
+                        "&Resize columns")
+            self.popup(menu, ['resize'], event)
+        else:
+            # Clicked a row label
+            rows = self.getRowsWithASelection()
+            if not event.GetRow() in rows:
+                self.grid.SelectRow(row)
+            menu = wx.Menu()
+            menu.Append(xrc.XRCID('show_selected'),
+                        "&Show selected directive(s)")
+            self.popup(menu, ['show_selected'], event)
 
     def onSelectCell(self, event):
         directive = self.table.directives[event.GetRow()]
         self.gui.ensureDirectiveVisible(directive)
         event.Skip()
 
-    def on_menu_show_selected(self, event):
-        # Make a dictionary containing all rows with anything selected
-        rows = {}
+    def getRowsWithASelection(self):
+        """Returns the set of rows with some cell selected"""
+        rows = set()
         for (top, left), (bottom, right) in zip(
             self.grid.GetSelectionBlockTopLeft(),
             self.grid.GetSelectionBlockBottomRight()):
             for row in range(top, bottom + 1):
-                rows[row] = True
+                rows.add(row)
         for row, col in self.grid.GetSelectedCells():
-            rows[row] = True
+            rows.add(row)
         for row in self.grid.GetSelectedRows():
-            rows[row] = True
+            rows.add(row)
+        return rows
 
+    def on_menu_show_selected(self, event):
+        rows = self.getRowsWithASelection()
         selected = []
-        for row in rows.keys():
+        for row in rows:
             selected.append(self.table.directives[row])
         self.gui.selectDirectives(selected)
 
+    def on_menu_filter(self, event):
+        pass
+
     def on_menu_resize(self, event):
         self.resizeColumns()
 

Modified: z3/zopejam/trunk/src/zopejam/resources.xrc
==============================================================================
--- z3/zopejam/trunk/src/zopejam/resources.xrc	(original)
+++ z3/zopejam/trunk/src/zopejam/resources.xrc	Fri Jul 22 08:55:00 2005
@@ -738,6 +738,10 @@
     <object class="wxMenuItem" name="show_selected">
       <label>&amp;Show selected directive(s)</label>
     </object>
+    <object class="wxMenuItem" name="filter">
+      <label>&amp;Filter by this value</label>
+    </object>
+    <object class="separator"/>
     <object class="wxMenuItem" name="resize">
       <label>&amp;Resize columns</label>
     </object>


More information about the z3-checkins mailing list