--- /dev/null
+#----------------------------------------------------------------------------
+# 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 = """\
+<html>
+<body>
+
+This demo demonstrates direct editing of all cells of a ListCtrl. To
+enable it just include the <b>TextEditMixin</b>. The ListCtrl can be
+navigated with the TAB and up/down cursor keys.
+
+<p>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 <b>ListCtrlAutoWidthMixin</b>:
+<code>listmix.ListCtrlAutoWidthMixin.__init__(self, startcol, endcol)</code>
+(Look at the general ListCtrl demo for more information about the
+ListCtrlAutoWidthMixin)
+
+<p>Finally, the ListCtrl is automatically scrolled, if needed, when
+TAB is pressed consecutively (Windows only).
+
+</body>
+</html>
+"""
+
+
+if __name__ == '__main__':
+ import sys,os
+ import run
+ run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
+
'StockButtons',
'Ticker',
'Choicebook',
+ 'ListCtrl_edit',
]),
# managed windows == things with a (optional) caption you can close
'ListBox',
'ListCtrl',
'ListCtrl_virtual',
+ 'ListCtrl_edit',
'Listbook',
'Menu',
'Notebook',
- 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)
# 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
#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()
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()
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()
''' 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)
# 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__)
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)
except:
pass
- self.ctx.kwargs[str(name)] = value
+ if self.ctx:
+ self.ctx.kwargs[str(name)] = value
return False