[z3-checkins] r15449 - z3/zopejam/trunk/src/zopejam

hathawsh at codespeak.net hathawsh at codespeak.net
Sun Jul 31 00:12:34 CEST 2005


Author: hathawsh
Date: Sun Jul 31 00:12:29 2005
New Revision: 15449

Modified:
   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:
Made the filter controls functional.


Modified: z3/zopejam/trunk/src/zopejam/columns.py
==============================================================================
--- z3/zopejam/trunk/src/zopejam/columns.py	(original)
+++ z3/zopejam/trunk/src/zopejam/columns.py	Sun Jul 31 00:12:29 2005
@@ -33,7 +33,7 @@
         return (True, False, False)
 
     def resolve(self, d, name):
-        """Tries to resolve a package name,
+        """Tries to resolve a package name.
 
         Returns (name, error)
         """
@@ -66,7 +66,7 @@
 
 
 class DirectiveType(Column):
-    label = 'Directive'
+    label = 'Directive Type'
     default_width = 150
 
     def getText(self, d):

Modified: z3/zopejam/trunk/src/zopejam/main.py
==============================================================================
--- z3/zopejam/trunk/src/zopejam/main.py	(original)
+++ z3/zopejam/trunk/src/zopejam/main.py	Sun Jul 31 00:12:29 2005
@@ -408,7 +408,7 @@
         self.gui = gui
         self.panel = panel
 
-        self.filter = Filter(gui, xrc.XRCCTRL(panel, 'filter_panel'))
+        self.filter_panel = Filter(gui, xrc.XRCCTRL(panel, 'filter_panel'))
         # Replace the directive list with a DirectiveList instance
         old_dir_list = xrc.XRCCTRL(panel, 'dir_list')
         parent = old_dir_list.GetParent()
@@ -427,6 +427,8 @@
         self.gui = gui
         self.directives = []  # list of directives, not reordered by sorting
         self.indexes = []  # list of directive indexes, reordered by sorting
+        self.filter_func = None
+        self.state_mask = wx.LIST_STATE_SELECTED | wx.LIST_STATE_FOCUSED
 
         self.columns = columns.create_default_columns()
         self.SetImageList(self.gui.tiny_palette_images, wx.IMAGE_LIST_SMALL)
@@ -445,7 +447,7 @@
         self.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.onSelectChange)
 
         self.select_timer = wx.Timer()
-        self.select_timer.Bind(wx.EVT_TIMER, self.onSelectTimeout)
+        self.select_timer.Bind(wx.EVT_TIMER, self.propagateSelection)
 
     def onSelectChange(self, event):
         if self.suppress_select_event:
@@ -453,7 +455,9 @@
         self.select_timer.Stop()
         self.select_timer.Start(300, wx.TIMER_ONE_SHOT)
 
-    def onSelectTimeout(self, event):
+    def propagateSelection(self, event=None):
+        """Send the current selection to other widgets"""
+        self.select_timer.Stop()
         count = self.GetSelectedItemCount()
         self.gui.setStatus("%d directive%s selected" %
                            (count, (count != 1 and 's' or '')))
@@ -517,24 +521,47 @@
         files.sort()
         for sort_key, cfg in files:
             if cfg.root is not None:
-                self.directives.extend(
-                    [e.directive for e in cfg.root.flattened()])
+                dirs = [e.directive for e in cfg.root.flattened()]
+                if self.filter_func is not None:
+                    # apply a filter
+                    for d in dirs:
+                        if self.filter_func(d):
+                            self.directives.append(d)
+                else:
+                    # no filtering
+                    self.directives.extend(dirs)
+
         self.SetItemCount(len(self.directives))
-        self._doResize()
+        self._doResize()  # resize the column headers to fit the scroll bar
         try:
             self.SortItems()
         except:
             self.SetItemCount(0)
             raise
+
         self.Refresh()
 
+    def setFilter(self, filter_func):
+        if self.filter_func is None and filter_func is None:
+            # No change needed
+            return
+        self.filter_func = filter_func
+        state = self.saveSelectionState()
+        self.populate()
+        self.restoreSelectionState(state)
+        self.propagateSelection()
+
     def OnGetItemText(self, item, col):
         index = self.indexes[item]
         d = self.directives[index]
         col_obj = self.columns[col]
         text = col_obj.getText(d)
-        if col == self._col and col_obj.indent and d.element.depth:
-            # indent when sorting on an indentable column
+        if (self.filter_func is None
+            and col == self._col
+            and col_obj.indent
+            and d.element.depth):
+            # indent when sorting on an indentable column and no
+            # filter is in effect
             return '    ' * (d.element.depth) + text
         else:
             return text
@@ -546,6 +573,39 @@
         return (self.gui.tiny_palette_images['sort_up'],
                 self.gui.tiny_palette_images['sort_down'])
 
+    def clearSelection(self):
+        # clear state for all rows (undocumented API?)
+        self.SetItemState(-1, 0, self.state_mask)
+        self.Focus(-1)
+
+    def saveSelectionState(self):
+        selected = set()
+        item = self.GetFirstSelected()
+        while item >= 0:
+            index = self.indexes[item]
+            selected.add(self.directives[index])
+            item = self.GetNextSelected(item)
+        focused = None
+        item = self.GetFocusedItem()
+        if item is not None and item >= 0:
+            index = self.indexes[item]
+            focused = self.directives[index]
+        state = (selected, focused)
+        return state
+
+    def restoreSelectionState(self, state):
+        selected, focused = state
+        self.clearSelection()
+        for i, directive_index in enumerate(self.indexes):
+            d = self.directives[directive_index]
+            if d in selected:
+                self.SetItemState(
+                    i, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
+            if d is focused:
+                self.Focus(i)
+        if focused is None and len(self.directives) > 0:
+            self.EnsureVisible(0)
+
     def SortItems(self, sorter=None):
         """A SortItem implementation that works with virtual lists.
 
@@ -554,14 +614,6 @@
         Based on code by Egor Zindy
         http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/426407
         """
-        # gather the focus and selection flags
-        flags = {}
-        mask = wx.LIST_STATE_SELECTED | wx.LIST_STATE_FOCUSED
-        for i, directive_index in enumerate(self.indexes):
-            state = self.GetItemState(i, mask)
-            if state:
-                flags[directive_index] = state
-
         # _col and _colSortFlag are defined in ColumnSorterMixin.
         # col is the column which was clicked on and
         # sf, the sort flag, is False for descending (Z->A)
@@ -592,17 +644,6 @@
         # store the directive indexes as self.indexes.
         self.indexes = k
 
-        # clear state for all rows (undocumented API?)
-        self.SetItemState(-1, 0, mask)
-
-        # reapply the selection and focus flags
-        for i, directive_index in enumerate(self.indexes):
-            state = flags.get(directive_index)
-            if state:
-                self.SetItemState(i, state, mask)
-                if state & wx.LIST_STATE_FOCUSED:
-                    self.EnsureVisible(i)
-
         # redraw the list
         self.Refresh()
 
@@ -618,7 +659,11 @@
         # but not when switching columns
         if col == oldCol:
             self._colSortFlag[col] = not self._colSortFlag[col]
-        self.GetListCtrl().SortItems(self.GetColumnSorter())
+
+        state = self.saveSelectionState()
+        self.GetListCtrl().SortItems()
+        self.restoreSelectionState(state)
+
         self._ColumnSorterMixin__updateImages(oldCol)
         evt.Skip()
 
@@ -705,51 +750,87 @@
         self.gui = gui
         self.panel = panel
 
+        self.filter_by = xrc.XRCCTRL(panel, 'filter_by')
+        self.filter_by.Bind(wx.EVT_CHOICE, self.applyFilter)
         self.expr = xrc.XRCCTRL(panel, 'filter_expr')
+        self.expr.Bind(wx.EVT_TEXT, self.onChangeText)
+        self.expr.Bind(wx.EVT_TEXT_ENTER, self.applyFilter)
         self.clear = xrc.XRCCTRL(panel, 'filter_clear')
-        self.clear.Bind(wx.EVT_LEFT_DOWN, self.onClear)
-        parent = self.expr.GetParent()
-        self.has_expr = False
-        self.suppress_event = False
-        self.expr.Bind(wx.EVT_SET_FOCUS, self.onFocus)
-        self.expr.Bind(wx.EVT_KILL_FOCUS, self.onBlur)
-        self.expr.Bind(wx.EVT_TEXT, self.onChange)
-
-    def onFocus(self, event):
-        if not self.has_expr:
-            self.suppress_event = True
-            try:
-                self.expr.SetValue('')
-            finally:
-                self.suppress_event = False
-
-    def onBlur(self, event):
-        if not self.has_expr:
-            self.suppress_event = True
-            try:
-                self.expr.SetValue('Entire Directive')
-            finally:
-                self.suppress_event = False
-
-    def onClear(self, event):
-        self.has_expr = False
-        self.clear.Hide()
-        self.panel.Layout()
-        self.suppress_event = True
-        try:
-            self.expr.SetValue('')
-        finally:
-            self.suppress_event = False
+        self.clear.Bind(wx.EVT_BUTTON, self.onClearButton)
+
+        self.expr_timer = wx.Timer()
+        self.expr_timer.Bind(wx.EVT_TIMER, self.applyFilter)
+
+        def create_filter_any_attr(text):
+            if not text:
+                return None
+            text = text.lower()
+            def filter(d):
+                e = d.element
+                if e is not None:
+                    for v in e.data.itervalues():
+                        if text in v.lower():
+                            return True
+                return False
+            return filter
+
+        def create_filter_condition(text):
+            text = text.lower()
+            def filter(d):
+                e = d.element
+                if e is not None:
+                    if not text:
+                        # any condition matches
+                        if e.condition:
+                            return True
+                    elif e.condition and text in e.condition.lower():
+                        # match condition text
+                        return True
+                return False
+            return filter
+
+        filter_types = [
+            ('Attribute Value', create_filter_any_attr),
+            ('Condition', create_filter_condition),
+            ]
+        for c in columns.create_default_columns():
+            def create_filter(text, getText=c.getText):
+                if not text:
+                    return None
+                text = text.lower()
+                def filter(d):
+                    return text in getText(d).lower()
+                return filter
+            filter_types.append((c.getLabel(), create_filter))
+
+        self.filter_by.Clear()
+        for label, factory in filter_types:
+            self.filter_by.Append(label, factory)
+        self.filter_by.SetSelection(0)
+
+    def onClearButton(self, event):
+        self.expr.SetValue('')
+        self.clear.Disable()
         self.expr.SetFocus()
+        self.applyFilter()
 
-    def onChange(self, event):
-        if self.suppress_event:
+    def onChangeText(self, event):
+        self.clear.Enable(bool(self.expr.GetValue()))
+        self.expr_timer.Stop()
+        self.expr_timer.Start(300, wx.TIMER_ONE_SHOT)
+
+    def applyFilter(self, event=None):
+        self.expr_timer.Stop()
+        dir_list = self.gui.fbook.all.dir_list
+
+        sel = self.filter_by.GetSelection()
+        if sel < 0:
+            dir_list.setFilter(None)
             return
-        had = self.has_expr
-        self.has_expr = bool(self.expr.GetValue())
-        if had != self.has_expr:
-            self.clear.Show(self.has_expr)
-            self.panel.Layout()
+        factory = self.filter_by.GetClientData(sel)
+        value = self.expr.GetValue()
+        filter = factory(value)
+        dir_list.setFilter(filter)
 
 
 class Command:

Modified: z3/zopejam/trunk/src/zopejam/propbook.py
==============================================================================
--- z3/zopejam/trunk/src/zopejam/propbook.py	(original)
+++ z3/zopejam/trunk/src/zopejam/propbook.py	Sun Jul 31 00:12:29 2005
@@ -172,6 +172,8 @@
             label.SetFont(self.gui.italic_font)
             sizer.Add(label)
 
+        # TODO: show errors and conditions, including inherited
+
     def addFields(self):
         sizer = wx.FlexGridSizer(rows=0, cols=3, vgap=4, hgap=8)
         self.win.GetSizer().Add(sizer, flag=wx.EXPAND|wx.ALL, border=4)

Modified: z3/zopejam/trunk/src/zopejam/resources.xrc
==============================================================================
--- z3/zopejam/trunk/src/zopejam/resources.xrc	(original)
+++ z3/zopejam/trunk/src/zopejam/resources.xrc	Sun Jul 31 00:12:29 2005
@@ -281,60 +281,53 @@
                     <item>Changed</item>
                     <item>Errors</item>
                   </content>
+                  <selection>0</selection>
                 </object>
                 <flag>wxALIGN_CENTRE_VERTICAL</flag>
               </object>
             </object>
           </object>
           <object class="sizeritem">
-            <object class="wxBoxSizer">
-              <object class="sizeritem">
-                <object class="wxStaticText">
-                  <label>Filter:</label>
+            <object class="wxPanel" name="filter_panel">
+              <object class="wxBoxSizer">
+                <object class="sizeritem">
+                  <object class="wxStaticText">
+                    <label>Filter by:</label>
                           </object>
-                <flag>wxLEFT|wxRIGHT|wxALIGN_CENTRE_VERTICAL</flag>
-                <border>4</border>
+                  <flag>wxLEFT|wxALIGN_CENTRE_VERTICAL</flag>
+                  <border>4</border>
                         </object>
-              <object class="sizeritem">
-                <object class="wxPanel" name="filter_panel">
-                  <object class="wxFlexGridSizer">
-                    <cols>3</cols>
-                    <object class="sizeritem">
-                      <object class="wxStaticBitmap" name="filter_type">
-                        <bitmap>icons/other/find.png</bitmap>
-                                </object>
-                      <flag>wxALL|wxALIGN_CENTRE</flag>
-                      <border>2</border>
-                              </object>
-                    <object class="sizeritem">
-                      <object class="wxTextCtrl" name="filter_expr">
-                        <value>Entire Directive</value>
-                        <style>wxTE_PROCESS_ENTER|wxNO_BORDER</style>
-                                </object>
-                      <flag>wxEXPAND|wxALIGN_CENTRE_VERTICAL</flag>
-                              </object>
-                    <object class="sizeritem">
-                      <object class="wxStaticBitmap" name="filter_clear">
-                        <bitmap>icons/other/clear_left.png</bitmap>
-                        <hidden>1</hidden>
-                                </object>
-                      <flag>wxALL|wxALIGN_CENTRE</flag>
-                      <border>2</border>
-                              </object>
-                    <growablecols>1</growablecols>
-                    <growablerows>0</growablerows>
+                <object class="sizeritem">
+                  <object class="wxChoice" name="filter_by">
+                    <content>
+                      <item>Any Attribute</item>
+                    </content>
+                    <selection>0</selection>
+                    <enabled></enabled>
                   </object>
-                  <style>wxSUNKEN_BORDER</style>
-                  <bg>#FFFFFF</bg>
+                  <flag>wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_CENTRE_VERTICAL</flag>
+                  <border>4</border>
+                  <minsize>150, 12</minsize>
                 </object>
-                <flag>wxBOTTOM|wxRIGHT|wxEXPAND</flag>
-                <border>1</border>
-                <minsize>300, 22</minsize>
-                        </object>
-              <orient>wxHORIZONTAL</orient>
+                <object class="sizeritem">
+                  <object class="wxTextCtrl" name="filter_expr">
+                    <style>wxTE_PROCESS_ENTER</style>
+                                </object>
+                  <flag>wxEXPAND|wxALIGN_CENTRE_VERTICAL</flag>
+                  <minsize>200, 12</minsize>
+                </object>
+                <object class="sizeritem">
+                  <object class="wxBitmapButton" name="filter_clear">
+                    <bitmap>icons/other/clear_left.png</bitmap>
+                    <style>wxNO_BORDER</style>
+                    <enabled>0</enabled>
+                  </object>
+                  <flag>wxALL|wxALIGN_CENTRE_VERTICAL</flag>
+                              </object>
+                <orient>wxHORIZONTAL</orient>
+              </object>
             </object>
-            <flag>wxALIGN_RIGHT|wxALIGN_CENTRE_VERTICAL</flag>
-                    </object>
+                        </object>
           <growablecols>0</growablecols>
           <growablecols>1</growablecols>
         </object>


More information about the z3-checkins mailing list