From 15513a8066caaed1d1265cc06c47fc5c8ec1127e Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Fri, 15 Oct 2004 18:45:21 +0000 Subject: [PATCH] Applied patch from Pim Van Heuven that modifies 4 files: - wxPython/demo/ListCtrl_edit.py (new demo) - wxPython/demo/Main.py (include new demo in demo app) - wxPython/wx/lib/mixins/listctrl.py (several improvements to TextEditMixin) - wxPython/wx/lib/wxpTag.py (some small fixes) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@29883 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- wxPython/demo/ListCtrl_edit.py | 142 +++++++++++++++++++++++++++++ wxPython/demo/Main.py | 2 + wxPython/docs/CHANGES.txt | 10 ++ wxPython/wx/lib/mixins/listctrl.py | 121 +++++++++++++++++++++--- wxPython/wx/lib/wxpTag.py | 7 +- 5 files changed, 265 insertions(+), 17 deletions(-) create mode 100644 wxPython/demo/ListCtrl_edit.py diff --git a/wxPython/demo/ListCtrl_edit.py b/wxPython/demo/ListCtrl_edit.py new file mode 100644 index 0000000000..cba1e24007 --- /dev/null +++ b/wxPython/demo/ListCtrl_edit.py @@ -0,0 +1,142 @@ +#---------------------------------------------------------------------------- +# Name: ListCtrl_edit.py +# Purpose: Testing editing a ListCtrl +# +# Author: Pim van Heuven +# +# Created: 2004/10/15 +# Copyright: (c) Pim Van Heuven +# Licence: wxWindows license +#---------------------------------------------------------------------------- + +import sys +import wx +import wx.lib.mixins.listctrl as listmix + +#--------------------------------------------------------------------------- + +listctrldata = { +1 : ("Hey!", "You can edit", "me!"), +2 : ("Try changing the contents", "by", "clicking"), +3 : ("in", "a", "cell"), +4 : ("See how the length columns", "change", "?"), +5 : ("You can use", "TAB,", "cursor down,"), +6 : ("and cursor up", "to", "navigate"), +} + +#--------------------------------------------------------------------------- + +class TestListCtrl(wx.ListCtrl, + listmix.ListCtrlAutoWidthMixin, + listmix.TextEditMixin): + + def __init__(self, parent, ID, pos=wx.DefaultPosition, + size=wx.DefaultSize, style=0): + wx.ListCtrl.__init__(self, parent, ID, pos, size, style) + + # Divide remaining space over all columns + listmix.ListCtrlAutoWidthMixin.__init__(self, 0, 3) + self.Populate() + listmix.TextEditMixin.__init__(self) + + def Populate(self): + # for normal, simple columns, you can add them like this: + self.InsertColumn(0, "Column 1") + self.InsertColumn(1, "Column 2") + self.InsertColumn(2, "Column 3") + self.InsertColumn(3, "Len 1", wx.LIST_FORMAT_RIGHT) + self.InsertColumn(4, "Len 2", wx.LIST_FORMAT_RIGHT) + self.InsertColumn(5, "Len 3", wx.LIST_FORMAT_RIGHT) + + items = listctrldata.items() + for key, data in items: + index = self.InsertStringItem(sys.maxint, data[0]) + self.SetStringItem(index, 0, data[0]) + self.SetStringItem(index, 1, data[1]) + self.SetStringItem(index, 2, data[2]) + self.SetItemData(index, key) + + self.SetColumnWidth(0, wx.LIST_AUTOSIZE) + self.SetColumnWidth(1, wx.LIST_AUTOSIZE) + self.SetColumnWidth(2, 100) + + self.currentItem = 0 + + + def SetStringItem(self, index, col, data): + if col in range(3): + wx.ListCtrl.SetStringItem(self, index, col, data) + wx.ListCtrl.SetStringItem(self, index, 3+col, str(len(data))) + else: + try: + datalen = int(data) + except: + return + + wx.ListCtrl.SetStringItem(self, index, col, data) + + data = self.GetItem(index, col-3).GetText() + wx.ListCtrl.SetStringItem(self, index, col-3, data[0:datalen]) + + + + +class TestListCtrlPanel(wx.Panel): + def __init__(self, parent, log): + wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS) + + self.log = log + tID = wx.NewId() + + self.list = TestListCtrl(self, tID, + style=wx.LC_REPORT + | wx.BORDER_NONE + | wx.LC_SORT_ASCENDING + ) + + self.Bind(wx.EVT_SIZE, self.OnSize) + + + def OnSize(self, event): + w,h = self.GetClientSizeTuple() + self.list.SetDimensions(0, 0, w, h) + + + +#--------------------------------------------------------------------------- + +def runTest(frame, nb, log): + win = TestListCtrlPanel(nb, log) + return win + +#--------------------------------------------------------------------------- + + +overview = """\ + + + +This demo demonstrates direct editing of all cells of a ListCtrl. To +enable it just include the TextEditMixin. The ListCtrl can be +navigated with the TAB and up/down cursor keys. + +

Another facet of this demo is that the remaining space of the +ListCtrls is divided over the first three columns. This is achieved +with the extended syntax of ListCtrlAutoWidthMixin: +listmix.ListCtrlAutoWidthMixin.__init__(self, startcol, endcol) +(Look at the general ListCtrl demo for more information about the +ListCtrlAutoWidthMixin) + +

Finally, the ListCtrl is automatically scrolled, if needed, when +TAB is pressed consecutively (Windows only). + + + +""" + + +if __name__ == '__main__': + import sys,os + import run + run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:]) + diff --git a/wxPython/demo/Main.py b/wxPython/demo/Main.py index be0cd0a4f9..d2570166e7 100644 --- a/wxPython/demo/Main.py +++ b/wxPython/demo/Main.py @@ -50,6 +50,7 @@ _treeList = [ 'StockButtons', 'Ticker', 'Choicebook', + 'ListCtrl_edit', ]), # managed windows == things with a (optional) caption you can close @@ -98,6 +99,7 @@ _treeList = [ 'ListBox', 'ListCtrl', 'ListCtrl_virtual', + 'ListCtrl_edit', 'Listbook', 'Menu', 'Notebook', diff --git a/wxPython/docs/CHANGES.txt b/wxPython/docs/CHANGES.txt index 2e3ecaaf9f..98aa78a35e 100644 --- a/wxPython/docs/CHANGES.txt +++ b/wxPython/docs/CHANGES.txt @@ -165,6 +165,16 @@ MaskedEdit updates from Will Sadkin: - lots of doc string improvements and function hiding to better reflect package's public contents. +Restructured the installer packages slightly to help facilitate having +multiple versions of wxPython installed at the same time. See the +Migrarion Guide for more information. + +Applied patch from Pim Van Heuven that modifies 4 files: + - wxPython/demo/ListCtrl_edit.py (new demo) + - wxPython/demo/Main.py (include new demo in demo app) + - wxPython/wx/lib/mixins/listctrl.py (several improvements to + TextEditMixin) + - wxPython/wx/lib/wxpTag.py (some small fixes) diff --git a/wxPython/wx/lib/mixins/listctrl.py b/wxPython/wx/lib/mixins/listctrl.py index 77e49112de..3e5c73a802 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 @@ -374,22 +382,35 @@ 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 +418,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 +476,50 @@ 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 foreward + 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.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 +534,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) diff --git a/wxPython/wx/lib/wxpTag.py b/wxPython/wx/lib/wxpTag.py index d93a9fa9b1..65e1b58ad2 100644 --- a/wxPython/wx/lib/wxpTag.py +++ b/wxPython/wx/lib/wxpTag.py @@ -195,7 +195,7 @@ class wxpTagHandler(wx.html.HtmlWinTagHandler): # check for something that should be evaluated - elif value[0] in '[{(' or value[:2] == 'wx': + elif value and value[0] in '[{(' or value[:2] == 'wx': saveVal = value try: value = eval(value, self.ctx.classMod.__dict__) @@ -203,7 +203,7 @@ class wxpTagHandler(wx.html.HtmlWinTagHandler): value = saveVal # convert to wx.Colour - elif value[0] == '#': + elif value and value[0] == '#': try: red = int('0x'+value[1:3], 16) green = int('0x'+value[3:5], 16) @@ -212,7 +212,8 @@ class wxpTagHandler(wx.html.HtmlWinTagHandler): except: pass - self.ctx.kwargs[str(name)] = value + if self.ctx: + self.ctx.kwargs[str(name)] = value return False -- 2.47.2