X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5841276a802f0fc29a260fd4dde6710e450e1b0c..7276cbe3f07b66d8923cbadd71b684d08197acd0:/wxPython/wx/lib/mixins/listctrl.py diff --git a/wxPython/wx/lib/mixins/listctrl.py b/wxPython/wx/lib/mixins/listctrl.py index ddbb8b46a0..7fec34285b 100644 --- a/wxPython/wx/lib/mixins/listctrl.py +++ b/wxPython/wx/lib/mixins/listctrl.py @@ -17,7 +17,15 @@ # 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 == @@ -216,11 +242,20 @@ class ListCtrlAutoWidthMixin: or calculated a minimum width. This ensure that repeated calls to _doResize() don't cause the last column to size itself too large. """ + + if not self: # avoid a PyDeadObject error + return + 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 @@ -232,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) + @@ -258,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): @@ -370,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() @@ -393,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() @@ -427,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() @@ -456,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)