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
This commit is contained in:
parent
6537ccf8cd
commit
15513a8066
142
wxPython/demo/ListCtrl_edit.py
Normal file
142
wxPython/demo/ListCtrl_edit.py
Normal file
@ -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 = """\
|
||||
<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:])
|
||||
|
@ -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',
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user