]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/wx/lib/mixins/listctrl.py
OGL fixes from Davide Salomoni
[wxWidgets.git] / wxPython / wx / lib / mixins / listctrl.py
index fa9bd0291d555dcafaddc47c6483be3b80924cf8..7fec34285bcd2ee6e655f75469766b916c024d57 100644 (file)
 # 12/21/2003 - Jeff Grimmett (grimmtooth@softhome.net)
 #
 # o wxColumnSorterMixin -> ColumnSorterMixin 
-# o wxListCtrlAutoWidthMixin -> ListCtrlAutoWidthMixin 
+# o wxListCtrlAutoWidthMixin -> ListCtrlAutoWidthMixin
+# ...
+# 13/10/2004 - Pim Van Heuven (pim@think-wize.com)
+# o wxTextEditMixin: Support Horizontal scrolling when TAB is pressed on long
+#       ListCtrls, support for WXK_DOWN, WXK_UP, performance improvements on
+#       very long ListCtrls, Support for virtual ListCtrls
+#
+# 15-Oct-2004 - Robin Dunn
+# o wxTextEditMixin: Added Shift-TAB support
 #
 
 import  locale
@@ -168,12 +176,25 @@ class ListCtrlAutoWidthMixin:
     def __init__(self):
         """ Standard initialiser.
         """
-        self._lastColMinWidth = None
-
+        self._resizeColMinWidth = None
+        self._resizeColStyle = "LAST"
+        self._resizeCol = 0
         self.Bind(wx.EVT_SIZE, self._onResize)
         self.Bind(wx.EVT_LIST_COL_END_DRAG, self._onResize, self)
 
 
+    def setResizeColumn(self, col):
+        """
+        Specify which column that should be autosized.  Pass either
+        'LAST' or the column number.  Default is 'LAST'.
+        """
+        if col == "LAST":
+            self._resizeColStyle = "LAST"
+        else:
+            self._resizeColStyle = "COL"
+            self._resizeCol = col
+        
+
     def resizeLastColumn(self, minWidth):
         """ Resize the last column appropriately.
 
@@ -188,8 +209,13 @@ class ListCtrlAutoWidthMixin:
 
             'minWidth' is the preferred minimum width for the last column.
         """
-        self._lastColMinWidth = minWidth
+        self.resizeCloumn(self, minWidth)
+
+
+    def resizeColumn(self, minWidth):
+        self._resizeColMinWidth = minWidth
         self._doResize()
+        
 
     # =====================
     # == Private Methods ==
@@ -223,8 +249,13 @@ class ListCtrlAutoWidthMixin:
         numCols = self.GetColumnCount()
         if numCols == 0: return # Nothing to resize.
 
-        if self._lastColMinWidth == None:
-            self._lastColMinWidth = self.GetColumnWidth(numCols - 1)
+        if(self._resizeColStyle == "LAST"):
+            resizeCol = self.GetColumnCount()
+        else:
+            resizeCol = self._resizeCol
+
+        if self._resizeColMinWidth == None:
+            self._resizeColMinWidth = self.GetColumnWidth(resizeCol - 1)
 
         # We're showing the vertical scrollbar -> allow for scrollbar width
         # NOTE: on GTK, the scrollbar is included in the client size, but on
@@ -236,21 +267,23 @@ class ListCtrlAutoWidthMixin:
                 listWidth = listWidth - scrollWidth
 
         totColWidth = 0 # Width of all columns except last one.
-        for col in range(numCols-1):
-            totColWidth = totColWidth + self.GetColumnWidth(col)
+        for col in range(numCols):
+            if col != (resizeCol-1):
+                totColWidth = totColWidth + self.GetColumnWidth(col)
 
-        lastColWidth = self.GetColumnWidth(numCols - 1)
+        resizeColWidth = self.GetColumnWidth(resizeCol - 1)
 
-        if totColWidth + self._lastColMinWidth > listWidth:
+        if totColWidth + self._resizeColMinWidth > listWidth:
             # We haven't got the width to show the last column at its minimum
             # width -> set it to its minimum width and allow the horizontal
             # scrollbar to show.
-            self.SetColumnWidth(numCols-1, self._lastColMinWidth)
+            self.SetColumnWidth(resizeCol-1, self._resizeColMinWidth)
             return
 
         # Resize the last column to take up the remaining available space.
 
-        self.SetColumnWidth(numCols-1, listWidth - totColWidth)
+        self.SetColumnWidth(resizeCol-1, listWidth - totColWidth)
+
 
 
 
@@ -262,7 +295,7 @@ def selectBeforePopup(event):
 
     Works with both single-select and multi-select lists."""
     ctrl = event.GetEventObject()
-    if isinstance(ctrl, wxListCtrl):
+    if isinstance(ctrl, wx.ListCtrl):
         n, flags = ctrl.HitTest(event.GetPosition())
         if n >= 0:
             if not ctrl.GetItemState(n, wx.LIST_STATE_SELECTED):
@@ -374,22 +407,38 @@ class TextEditMixin:
         #editor = wx.TextCtrl(self, -1, pos=(-1,-1), size=(-1,-1),
         #                     style=wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB \
         #                     |wx.TE_RICH2)
+
+        self.make_editor()
+        self.Bind(wx.EVT_TEXT_ENTER, self.CloseEditor)
+        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+        self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
+        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
+
+
+    def make_editor(self, col_style=wx.LIST_FORMAT_LEFT):
         editor = wx.PreTextCtrl()
-        editor.Hide()
-        editor.Create(self, -1, style=wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB|wx.TE_RICH2)
+        
+        style =wx.TE_PROCESS_ENTER|wx.TE_PROCESS_TAB|wx.TE_RICH2
+        style |= {wx.LIST_FORMAT_LEFT: wx.TE_LEFT,
+                  wx.LIST_FORMAT_RIGHT: wx.TE_RIGHT,
+                  wx.LIST_FORMAT_CENTRE : wx.TE_CENTRE
+                  }[col_style]
+        
+        editor.Create(self, -1, style=style)
         editor.SetBackgroundColour(wx.Colour(red=255,green=255,blue=175)) #Yellow
         font = self.GetFont()
         editor.SetFont(font)
 
+        self.curRow = 0
+        self.curCol = 0
+
+        editor.Hide()
         self.editor = editor
-        self.Bind(wx.EVT_TEXT_ENTER, self.CloseEditor)
+
+        self.col_style = col_style
         self.editor.Bind(wx.EVT_CHAR, self.OnChar)
         self.editor.Bind(wx.EVT_KILL_FOCUS, self.CloseEditor)
-        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
-        self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
-        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
-        self.curRow = -1
-
+        
         
     def OnItemSelected(self, evt):
         self.curRow = evt.GetIndex()
@@ -397,11 +446,35 @@ class TextEditMixin:
         
 
     def OnChar(self, event):
-        ''' Catch the TAB key code so we can open the editor at the next column (if any).'''
-        if event.GetKeyCode() == wx.WXK_TAB:
+        ''' Catch the TAB, Shift-TAB, cursor DOWN/UP key code
+            so we can open the editor at the next column (if any).'''
+
+        keycode = event.GetKeyCode()
+        if keycode == wx.WXK_TAB and event.ShiftDown():
+            self.CloseEditor()
+            if self.curCol-1 >= 0:
+                self.OpenEditor(self.curCol-1, self.curRow)
+            
+        elif keycode == wx.WXK_TAB:
             self.CloseEditor()
             if self.curCol+1 < self.GetColumnCount():
                 self.OpenEditor(self.curCol+1, self.curRow)
+
+        elif keycode == wx.WXK_ESCAPE:
+            self.CloseEditor()
+
+        elif keycode == wx.WXK_DOWN:
+            self.CloseEditor()
+            if self.curRow+1 < self.GetItemCount():
+                self._SelectIndex(self.curRow+1)
+                self.OpenEditor(self.curCol, self.curRow)
+
+        elif keycode == wx.WXK_UP:
+            self.CloseEditor()
+            if self.curRow > 0:
+                self._SelectIndex(self.curRow-1)
+                self.OpenEditor(self.curCol, self.curRow)
+            
         else:
             event.Skip()
 
@@ -431,21 +504,53 @@ class TextEditMixin:
         for n in range(self.GetColumnCount()):
             loc = loc + self.GetColumnWidth(n)
             self.col_locs.append(loc)
+
         
-        col = bisect(self.col_locs, x) - 1
+        col = bisect(self.col_locs, x+self.GetScrollPos(wx.HORIZONTAL)) - 1
         self.OpenEditor(col, row)
 
 
     def OpenEditor(self, col, row):
         ''' Opens an editor at the current position. '''
+
+        if self.GetColumn(col).m_format != self.col_style:
+            self.make_editor(self.GetColumn(col).m_format)
     
         x0 = self.col_locs[col]
         x1 = self.col_locs[col+1] - x0
 
+        scrolloffset = self.GetScrollPos(wx.HORIZONTAL)
+
+        # scroll forward
+        if x0+x1-scrolloffset > self.GetSize()[0]:
+            if wx.Platform == "__WXMSW__":
+                # don't start scrolling unless we really need to
+                offset = x0+x1-self.GetSize()[0]-scrolloffset
+                # scroll a bit more than what is minimum required
+                # so we don't have to scroll everytime the user presses TAB
+                # which is very tireing to the eye
+                addoffset = self.GetSize()[0]/4
+                # but be careful at the end of the list
+                if addoffset + scrolloffset < self.GetSize()[0]:
+                    offset += addoffset
+
+                self.ScrollList(offset, 0)
+                scrolloffset = self.GetScrollPos(wx.HORIZONTAL)
+            else:
+                # Since we can not programmatically scroll the ListCtrl
+                # close the editor so the user can scroll and open the editor
+                # again
+                self.editor.SetValue(self.GetItem(row, col).GetText())
+                self.curRow = row
+                self.curCol = col
+                self.CloseEditor()
+                return
+
         y0 = self.GetItemRect(row)[1]
         
         editor = self.editor
-        editor.SetDimensions(x0,y0, x1,-1)
+        editor.SetDimensions(x0-scrolloffset,y0, x1,-1)
+        
         editor.SetValue(self.GetItem(row, col).GetText()) 
         editor.Show()
         editor.Raise()
@@ -460,7 +565,26 @@ class TextEditMixin:
         ''' Close the editor and save the new value to the ListCtrl. '''
         text = self.editor.GetValue()
         self.editor.Hide()
-        self.SetStringItem(self.curRow, self.curCol, text)
+        if self.IsVirtual():
+            # replace by whather you use to populate the virtual ListCtrl
+            # data source
+            self.SetVirtualData(self.curRow, self.curCol, text)
+        else:
+            self.SetStringItem(self.curRow, self.curCol, text)
+        self.RefreshItem(self.curRow)
+
+    def _SelectIndex(self, row):
+        listlen = self.GetItemCount()
+        if row < 0 and not listlen:
+            return
+        if row > (listlen-1):
+            row = listlen -1
+            
+        self.SetItemState(self.curRow, ~wx.LIST_STATE_SELECTED,
+                          wx.LIST_STATE_SELECTED)
+        self.EnsureVisible(row)
+        self.SetItemState(row, wx.LIST_STATE_SELECTED,
+                          wx.LIST_STATE_SELECTED)