fixes and updates that have been sitting on my disk for a while...

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@34305 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2005-05-23 22:30:59 +00:00
parent c580b5db1f
commit 5f1d47f3ee
6 changed files with 1446 additions and 838 deletions

View File

@@ -27,6 +27,13 @@
# Instead set set_x_mrg and set_y_mrg
# o Changed default X and Y Margin to 1.
# o Added wxCalendar.SetMargin.
#
# 17/03/2004 - Joerg "Adi" Sieker adi@sieker.info
# o Added keyboard navigation to the control.
# Use the cursor keys to navigate through the ages. :)
# The Home key function as go to today
# o select day is now a filled rect instead of just an outline
from wxPython.wx import *
@@ -82,8 +89,8 @@ def DefaultColors():
colors[COLOR_FONT] = wxSystemSettings_GetColour(wxSYS_COLOUR_WINDOWTEXT)
colors[COLOR_3D_LIGHT] = wxSystemSettings_GetColour(wxSYS_COLOUR_BTNHIGHLIGHT)
colors[COLOR_3D_DARK] = wxSystemSettings_GetColour(wxSYS_COLOUR_BTNSHADOW)
colors[COLOR_HIGHLIGHT_FONT] = 'PINK'
colors[COLOR_HIGHLIGHT_BACKGROUND] = 'RED'
colors[COLOR_HIGHLIGHT_FONT] = wxSystemSettings_GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT)
colors[COLOR_HIGHLIGHT_BACKGROUND] = wxSystemSettings_GetColour(wxSYS_COLOUR_HIGHLIGHT)
return colors
# calendar drawing routing
@@ -202,14 +209,26 @@ class CalDraw:
for val in list:
self.cal_sel[val] = (cfont, cbackgrd)
def DrawBorder(self, DC): # draw border around the outside of the main display rectangle
brush = wxBrush(MakeColor(self.colors[COLOR_BACKGROUND]), wxSOLID)
DC.SetBrush(brush)
DC.SetPen(wxPen(MakeColor(self.colors[COLOR_BORDER]), 1))
# draw border around the outside of the main display rectangle
def DrawBorder(self, DC, transparent = False):
if self.outer_border is True:
rect = wxRect(self.cx_st, self.cy_st, self.sizew, self.sizeh) # full display window area
DC.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
if transparent == False:
brush = wxBrush(MakeColor(self.colors[COLOR_BACKGROUND]), wxSOLID)
else:
brush = wxTRANSPARENT_BRUSH
DC.SetBrush(brush)
DC.SetPen(wxPen(MakeColor(self.colors[COLOR_BORDER])))
# full display window area
rect = wxRect(self.cx_st, self.cy_st, self.sizew, self.sizeh)
DC.DrawRectangleRect(rect)
def DrawFocusIndicator(self, DC):
if self.outer_border is True:
DC.SetBrush(wxTRANSPARENT_BRUSH)
DC.SetPen(wxPen(MakeColor(self.colors[COLOR_HIGHLIGHT_BACKGROUND]), style=wxDOT))
# full display window area
rect = wxRect(self.cx_st, self.cy_st, self.sizew, self.sizeh)
DC.DrawRectangleRect(rect)
def DrawNumVal(self):
self.DrawNum()
@@ -263,6 +282,9 @@ class CalDraw:
def GetRect(self): # get the display rectange list of the day grid
cnt = 0
h = 0
w = 0
for y in self.gridy[1:-1]:
if y == self.gridy[-2]:
h = h + self.restH
@@ -411,9 +433,7 @@ class CalDraw:
DC.DrawText(day, x+diffx, y+diffy)
cnt_x = cnt_x + 1
def DrawNum(self, DC): # draw the day numbers
f = wxFont(10, self.font, wxNORMAL, self.bold) # initial font setting
def _CalcFontSize(self, DC, f):
if self.num_auto == True:
test_size = self.max_num_size # max size
test_day = ' 99 '
@@ -431,13 +451,18 @@ class CalDraw:
f.SetPointSize(self.num_size) # set fixed size
DC.SetFont(f)
# draw the day numbers
def DrawNum(self, DC):
f = wxFont(10, self.font, wxNORMAL, self.bold) # initial font setting
self._CalcFontSize(DC, f)
cnt_x = 0
cnt_y = 1
for val in self.cal_days:
x = self.gridx[cnt_x]
y = self.gridy[cnt_y]
self.DrawDayText(x, y, val, f, DC)
self._DrawDayText(x, y, val, f, DC)
if cnt_x < 6:
cnt_x = cnt_x + 1
@@ -445,7 +470,7 @@ class CalDraw:
cnt_x = 0
cnt_y = cnt_y + 1
def DrawDayText(self, x, y, text, font, DC):
def _DrawDayText(self, x, y, text, font, DC):
try:
num_val = int(text)
num_color = self.cal_sel[num_val][0]
@@ -456,7 +481,7 @@ class CalDraw:
DC.SetFont(font)
tw,th = DC.GetTextExtent(text)
if self.num_align_horz == wxALIGN_CENTRE:
adj_h = (self.cellW - tw)/2
elif self.num_align_horz == wxALIGN_RIGHT:
@@ -477,6 +502,17 @@ class CalDraw:
DC.DrawText(text, x+adj_h, y+adj_v)
def DrawDayText(self, DC, key):
f = wxFont(10, self.font, wxNORMAL, self.bold) # initial font setting
self._CalcFontSize(DC, f)
val = self.cal_days[key]
cnt_x = key % 7
cnt_y = int(key / 7)+1
x = self.gridx[cnt_x]
y = self.gridy[cnt_y]
self._DrawDayText(x, y, val, f, DC)
def Center(self): # calculate the dimensions in the center of the drawing area
borderW = self.x_mrg * 2
borderH = self.y_mrg + self.y_end + self.title_offset
@@ -486,7 +522,8 @@ class CalDraw:
self.restW = ((self.sizew - borderW)%7 ) - 1
self.weekHdrCellH = int(self.cellH * self.cal_week_scale) # week title adjustment
# week title adjustment
self.weekHdrCellH = int(self.cellH * self.cal_week_scale)
# recalculate the cell height exkl. the week header and
# subtracting the size
self.cellH = int((self.sizeh - borderH - self.weekHdrCellH)/6)
@@ -496,6 +533,7 @@ class CalDraw:
self.calH = self.cellH * 6 + self.weekHdrCellH
def DrawSel(self, DC): # highlighted selected days
for key in self.cal_sel.keys():
sel_color = self.cal_sel[key][1]
brush = wxBrush(MakeColor(sel_color), wxSOLID)
@@ -578,10 +616,13 @@ class PrtCalDraw(CalDraw):
def SetPreview(self, preview):
self.preview = preview
class wxCalendar(wxWindow):
def __init__(self, parent, id, pos=wxDefaultPosition, size=wxDefaultSize):
wxWindow.__init__(self, parent, id, pos, size)
class wxCalendar( wxPyControl ):
def __init__(self, parent, id, pos=wxDefaultPosition, size=(400,400),
style= 0, validator=wxDefaultValidator,
name= "calendar"):
wxPyControl.__init__(self, parent, id, pos, size, style | wxWANTS_CHARS, validator, name)
self.hasFocus = False
# set the calendar control attributes
self.cal = None
@@ -604,6 +645,9 @@ class wxCalendar(wxWindow):
self.Connect(-1, -1, wxEVT_LEFT_DCLICK, self.OnLeftDEvent)
self.Connect(-1, -1, wxEVT_RIGHT_DOWN, self.OnRightEvent)
self.Connect(-1, -1, wxEVT_RIGHT_DCLICK, self.OnRightDEvent)
self.Connect(-1, -1, wxEVT_SET_FOCUS, self.OnSetFocus)
self.Connect(-1, -1, wxEVT_KILL_FOCUS, self.OnKillFocus)
self.Connect(-1, -1, wxEVT_KEY_DOWN, self.OnKeyDown)
self.sel_key = None # last used by
self.sel_lst = [] # highlighted selected days
@@ -616,6 +660,9 @@ class wxCalendar(wxWindow):
EVT_PAINT(self, self.OnPaint)
EVT_SIZE(self, self.OnSize)
def AcceptsFocus(self):
return self.IsShown() and self.IsEnabled()
def GetColor(self, name):
return MakeColor(self.colors[name])
@@ -657,6 +704,65 @@ class wxCalendar(wxWindow):
self.click = 'DRIGHT'
self.ProcessClick(event)
def OnSetFocus(self, event):
self.hasFocus = True
self.DrawFocusIndicator(True)
def OnKillFocus(self, event):
self.hasFocus = False
self.DrawFocusIndicator(False)
def OnKeyDown(self, event):
if not self.hasFocus:
event.Skip()
return
key_code = event.KeyCode()
if key_code == WXK_TAB:
forward = not event.ShiftDown()
ne = wxNavigationKeyEvent()
ne.SetDirection(forward)
ne.SetCurrentFocus(self)
ne.SetEventObject(self)
self.GetParent().GetEventHandler().ProcessEvent(ne)
event.Skip()
return
delta = None
if key_code == WXK_UP:
delta = -7
elif key_code == WXK_DOWN:
delta = 7
elif key_code == WXK_LEFT:
delta = -1
elif key_code == WXK_RIGHT:
delta = 1
elif key_code == wx.WXK_HOME:
curDate = wxDateTimeFromDMY(int(self.cal_days[self.sel_key]),self.month - 1,self.year)
newDate = wxDateTime_Now()
ts = newDate - curDate
delta = ts.GetDays()
if delta <> None:
curDate = wxDateTimeFromDMY(int(self.cal_days[self.sel_key]),self.month - 1,self.year)
timeSpan = wxTimeSpan_Days(delta)
newDate = curDate + timeSpan
if curDate.GetMonth() == newDate.GetMonth():
self.set_day = newDate.GetDay()
key = self.sel_key + delta
self.SelectDay(key)
else:
self.month = newDate.GetMonth() + 1
self.year = newDate.GetYear()
self.set_day = newDate.GetDay()
self.sel_key = None
self.DoDrawing(wxClientDC(self))
event.Skip()
def SetSize(self, set_size):
self.size = set_size
@@ -840,7 +946,36 @@ class wxCalendar(wxWindow):
DC.EndDrawing()
# draw the selection rectangle
def DrawRect(self, key, fgcolor = None, width = 0):
def DrawFocusIndicator(self, draw):
DC = wxClientDC(self)
try:
if draw == True:
self.caldraw.DrawFocusIndicator(DC)
else:
self.caldraw.DrawBorder(DC,True)
except:
pass
def DrawRect(self, key, bgcolor = 'WHITE', fgcolor= 'PINK',width = 0):
if key == None:
return
DC = wxClientDC(self)
DC.BeginDrawing()
brush = wxBrush(MakeColor(bgcolor))
DC.SetBrush(brush)
DC.SetPen(wxTRANSPARENT_PEN)
rect = self.rg[key]
DC.DrawRectangle(rect.x+1, rect.y+1, rect.width-2, rect.height-2)
self.caldraw.DrawDayText(DC,key)
DC.EndDrawing()
def DrawRectOrg(self, key, fgcolor = 'BLACK', width = 0):
if key == None:
return
@@ -867,12 +1002,24 @@ class wxCalendar(wxWindow):
day = day + self.st_pos - 1
self.SelectDay(day)
def IsDayInWeekend(self, key):
try:
t = Date(self.year, self.month, 1)
day = self.cal_days[key]
day = int(day) + t.day_of_week
if day % 7 == 6 or day % 7 == 0:
return True
except:
return False
def SelectDay(self, key):
sel_size = 1
self.DrawRect(self.sel_key, self.GetColor(COLOR_BACKGROUND), sel_size) # clear large selection
if self.hide_grid is False:
self.DrawRect(self.sel_key, self.GetColor(COLOR_GRID_LINES),sel_size )
if self.sel_key != None:
(cfont, bgcolor) = self.__GetColorsForDay(self.sel_key)
self.DrawRect(self.sel_key, bgcolor,cfont, sel_size)
self.DrawRect(key, self.GetColor(COLOR_HIGHLIGHT_BACKGROUND), sel_size)
self.sel_key = key # store last used by
@@ -884,6 +1031,21 @@ class wxCalendar(wxWindow):
self.set_x_mrg = xmarg
self.set_y_mrg = ymarg
self.set_y_end = ymarg
def __GetColorsForDay(self, key):
cfont = self.GetColor(COLOR_FONT)
bgcolor = self.GetColor(COLOR_BACKGROUND)
if self.IsDayInWeekend(key) is True and self.show_weekend is True:
cfont = self.GetColor(COLOR_WEEKEND_FONT)
bgcolor = self.GetColor(COLOR_WEEKEND_BACKGROUND)
try:
dayIdx = int(self.cal_days[key])
(cfont, bgcolor) = self.caldraw.cal_sel[dayIdx]
except:
pass
return (cfont, bgcolor)
class CalenDlg(wxDialog):
def __init__(self, parent, month=None, day = None, year=None):

View File

@@ -75,11 +75,6 @@ class ImageView(wxWindow):
dc = wxPaintDC(self)
self.DrawImage(dc)
def DrawImage(self, dc):
dc.BeginDrawing()
self.DrawImage(dc)
dc.EndDrawing()
def SetValue(self, file_nm): # display the selected file in the panel
image = ConvertBMP(file_nm)
self.image = image

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,7 @@
# are exceeded.
#
# wxMaskedNumCtrl is intended to support fixed-point numeric entry, and
# is derived from wxMaskedTextCtrl. As such, it supports a limited range
# is derived from wxBaseMaskedTextCtrl. As such, it supports a limited range
# of values to comply with a fixed-width entry mask.
"""<html><body>
<P>
@@ -74,6 +74,7 @@ Here's the API:
<B>emptyBackgroundColour</B> = "White",
<B>validBackgroundColour</B> = "White",
<B>invalidBackgroundColour</B> = "Yellow",
<B>autoSize</B> = True
)
</PRE>
<UL>
@@ -164,6 +165,15 @@ Here's the API:
<DT><B>invalidBackgroundColour</B>
<DD>Color value used for illegal values or values out-of-bounds of the
control when the bounds are set but the control is not limited.
<BR>
<DT><B>autoSize</B>
<DD>Boolean indicating whether or not the control should set its own
width based on the integer and fraction widths. True by default.
<B><I>Note:</I></B> Setting this to False will produce seemingly odd
behavior unless the control is large enough to hold the maximum
specified value given the widths and the sign positions; if not,
the control will appear to "jump around" as the contents scroll.
(ie. autoSize is highly recommended.)
</UL>
<BR>
<BR>
@@ -340,6 +350,12 @@ within the control. (The default is True.)
the field values on entry.
<BR>
<BR>
<DT><B>SetAutoSize(bool)</B>
<DD>Resets the autoSize attribute of the control.
<DT><B>GetAutoSize()</B>
<DD>Returns the current state of the autoSize attribute for the control.
<BR>
<BR>
</DL>
</body></html>
"""
@@ -351,7 +367,7 @@ MAXINT = maxint # (constants should be in upper case)
MININT = -maxint-1
from wxPython.tools.dbg import Logger
from wxPython.lib.maskededit import wxMaskedEditMixin, wxMaskedTextCtrl, Field
from wxPython.lib.maskededit import wxMaskedEditMixin, wxBaseMaskedTextCtrl, Field
import wxPython.utils
dbg = Logger()
dbg(enable=0)
@@ -381,16 +397,54 @@ class wxMaskedNumNumberUpdatedEvent(wxPyCommandEvent):
#----------------------------------------------------------------------------
class wxMaskedNumCtrlAccessorsMixin:
# Define wxMaskedNumCtrl's list of attributes having their own
# Get/Set functions, ignoring those that make no sense for
# an numeric control.
exposed_basectrl_params = (
'decimalChar',
'shiftDecimalChar',
'groupChar',
'useParensForNegatives',
'defaultValue',
'description',
class wxMaskedNumCtrl(wxMaskedTextCtrl):
'useFixedWidthFont',
'autoSize',
'signedForegroundColour',
'emptyBackgroundColour',
'validBackgroundColour',
'invalidBackgroundColour',
'emptyInvalid',
'validFunc',
'validRequired',
)
for param in exposed_basectrl_params:
propname = param[0].upper() + param[1:]
exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
if param.find('Colour') != -1:
# add non-british spellings, for backward-compatibility
propname.replace('Colour', 'Color')
exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
#----------------------------------------------------------------------------
class wxMaskedNumCtrl(wxBaseMaskedTextCtrl, wxMaskedNumCtrlAccessorsMixin):
valid_ctrl_params = {
'integerWidth': 10, # by default allow all 32-bit integers
'fractionWidth': 0, # by default, use integers
'fractionWidth': 0, # by default, use integers
'decimalChar': '.', # by default, use '.' for decimal point
'allowNegative': True, # by default, allow negative numbers
'useParensForNegatives': False, # by default, use '-' to indicate negatives
'groupDigits': True, # by default, don't insert grouping
'groupDigits': True, # by default, don't insert grouping
'groupChar': ',', # by default, use ',' for grouping
'min': None, # by default, no bounds set
'max': None,
@@ -402,7 +456,8 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
'emptyBackgroundColour': "White",
'validBackgroundColour': "White",
'invalidBackgroundColour': "Yellow",
'useFixedWidthFont': True, # by default, use a fixed-width font
'useFixedWidthFont': True, # by default, use a fixed-width font
'autoSize': True, # by default, set the width of the control based on the mask
}
@@ -475,6 +530,12 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
del init_args['integerWidth']
del init_args['fractionWidth']
self._autoSize = init_args['autoSize']
if self._autoSize:
formatcodes = 'FR<'
else:
formatcodes = 'R<'
mask = intmask+fracmask
@@ -484,11 +545,11 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
self._typedSign = False
# Construct the base control:
wxMaskedTextCtrl.__init__(
wxBaseMaskedTextCtrl.__init__(
self, parent, id, '',
pos, size, style, validator, name,
mask = mask,
formatcodes = 'FR<',
formatcodes = formatcodes,
fields = fields,
validFunc=self.IsInBounds,
setupEventHandling = False)
@@ -525,7 +586,8 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
if( (kwargs.has_key('integerWidth') and kwargs['integerWidth'] != self._integerWidth)
or (kwargs.has_key('fractionWidth') and kwargs['fractionWidth'] != self._fractionWidth)
or (kwargs.has_key('groupDigits') and kwargs['groupDigits'] != self._groupDigits) ):
or (kwargs.has_key('groupDigits') and kwargs['groupDigits'] != self._groupDigits)
or (kwargs.has_key('autoSize') and kwargs['autoSize'] != self._autoSize) ):
fields = {}
@@ -601,7 +663,7 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
dbg('kwargs:', kwargs)
# reprocess existing format codes to ensure proper resulting format:
formatcodes = self.GetFormatcodes()
formatcodes = self.GetCtrlParameter('formatcodes')
if kwargs.has_key('allowNegative'):
if kwargs['allowNegative'] and '-' not in formatcodes:
formatcodes += '-'
@@ -628,6 +690,16 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
formatcodes = formatcodes.replace('S','')
maskededit_kwargs['formatcodes'] = formatcodes
if kwargs.has_key('autoSize'):
self._autoSize = kwargs['autoSize']
if kwargs['autoSize'] and 'F' not in formatcodes:
formatcodes += 'F'
maskededit_kwargs['formatcodes'] = formatcodes
elif not kwargs['autoSize'] and 'F' in formatcodes:
formatcodes = formatcodes.replace('F', '')
maskededit_kwargs['formatcodes'] = formatcodes
if 'r' in formatcodes and self._fractionWidth:
# top-level mask should only be right insert if no fractional
# part will be shown; ie. if reconfiguring control, remove
@@ -635,6 +707,7 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
formatcodes = formatcodes.replace('r', '')
maskededit_kwargs['formatcodes'] = formatcodes
if kwargs.has_key('limited'):
if kwargs['limited'] and not self._limited:
maskededit_kwargs['validRequired'] = True
@@ -720,7 +793,7 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
dbg('abs(value):', value)
self._isNeg = False
elif not self._allowNone and wxMaskedTextCtrl.GetValue(self) == '':
elif not self._allowNone and wxBaseMaskedTextCtrl.GetValue(self) == '':
if self._min > 0:
value = self._min
else:
@@ -762,7 +835,7 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
else:
fracstart, fracend = self._fields[1]._extent
if candidate is None:
value = self._toGUI(wxMaskedTextCtrl.GetValue(self))
value = self._toGUI(wxBaseMaskedTextCtrl.GetValue(self))
else:
value = self._toGUI(candidate)
fracstring = value[fracstart:fracend].strip()
@@ -811,8 +884,8 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
if numvalue == "":
if self._allowNone:
dbg('calling base wxMaskedTextCtrl._SetValue(self, "%s")' % value)
wxMaskedTextCtrl._SetValue(self, value)
dbg('calling base wxBaseMaskedTextCtrl._SetValue(self, "%s")' % value)
wxBaseMaskedTextCtrl._SetValue(self, value)
self.Refresh()
return
elif self._min > 0 and self.IsLimited():
@@ -912,7 +985,7 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
# reasonable instead:
dbg('setting replacement value:', replacement)
self._SetValue(self._toGUI(replacement))
sel_start = wxMaskedTextCtrl.GetValue(self).find(str(abs(replacement))) # find where it put the 1, so we can select it
sel_start = wxBaseMaskedTextCtrl.GetValue(self).find(str(abs(replacement))) # find where it put the 1, so we can select it
sel_to = sel_start + len(str(abs(replacement)))
dbg('queuing selection of (%d, %d)' %(sel_start, sel_to))
wxCallAfter(self.SetInsertionPoint, sel_start)
@@ -938,8 +1011,8 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
sel_start, sel_to = self._GetSelection() # record current insertion point
dbg('calling base wxMaskedTextCtrl._SetValue(self, "%s")' % adjvalue)
wxMaskedTextCtrl._SetValue(self, adjvalue)
dbg('calling base wxBaseMaskedTextCtrl._SetValue(self, "%s")' % adjvalue)
wxBaseMaskedTextCtrl._SetValue(self, adjvalue)
# After all actions so far scheduled, check that resulting cursor
# position is appropriate, and move if not:
wxCallAfter(self._CheckInsertionPoint)
@@ -972,7 +1045,7 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
# delete next digit to appropriate side:
if self._groupDigits:
key = event.GetKeyCode()
value = wxMaskedTextCtrl.GetValue(self)
value = wxBaseMaskedTextCtrl.GetValue(self)
sel_start, sel_to = self._GetSelection()
if key == WXK_BACK:
@@ -998,7 +1071,7 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
self.SetInsertionPoint(sel_start)
self.SetSelection(sel_start, sel_to+1)
wxMaskedTextCtrl._OnErase(self, event)
wxBaseMaskedTextCtrl._OnErase(self, event)
dbg(indent=0)
@@ -1012,7 +1085,7 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
before passing the events on.
"""
dbg('wxMaskedNumCtrl::OnTextChange', indent=1)
if not wxMaskedTextCtrl._OnTextChange(self, event):
if not wxBaseMaskedTextCtrl._OnTextChange(self, event):
dbg(indent=0)
return
@@ -1033,7 +1106,7 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
def _GetValue(self):
"""
Override of wxMaskedTextCtrl to allow amixin to get the raw text value of the
Override of wxBaseMaskedTextCtrl to allow mixin to get the raw text value of the
control with this function.
"""
return wxTextCtrl.GetValue(self)
@@ -1043,7 +1116,7 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
"""
Returns the current numeric value of the control.
"""
return self._fromGUI( wxMaskedTextCtrl.GetValue(self) )
return self._fromGUI( wxBaseMaskedTextCtrl.GetValue(self) )
def SetValue(self, value):
"""
@@ -1054,16 +1127,16 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
A ValueError exception will be raised if an invalid value
is specified.
"""
wxMaskedTextCtrl.SetValue( self, self._toGUI(value) )
wxBaseMaskedTextCtrl.SetValue( self, self._toGUI(value) )
def SetIntegerWidth(self, value):
self.SetCtrlParameters(integerWidth=value)
self.SetParameters(integerWidth=value)
def GetIntegerWidth(self):
return self._integerWidth
def SetFractionWidth(self, value):
self.SetCtrlParameters(fractionWidth=value)
self.SetParameters(fractionWidth=value)
def GetFractionWidth(self):
return self._fractionWidth
@@ -1208,7 +1281,7 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
except ValueError, e:
dbg('error getting NumValue(self._toGUI(value)):', e, indent=0)
return False
if value == '':
if value.strip() == '':
value = None
elif self._fractionWidth:
value = float(value)
@@ -1281,6 +1354,12 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
def GetSelectOnEntry(self):
return self._selectOnEntry
def SetAutoSize(self, value):
self.SetParameters(autoSize=value)
def GetAutoSize(self):
return self._autoSize
# (Other parameter accessors are inherited from base class)
@@ -1298,6 +1377,14 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
elif type(value) in (types.StringType, types.UnicodeType):
value = self._GetNumValue(value)
dbg('cleansed num value: "%s"' % value)
if value == "":
if self.IsNoneAllowed():
dbg(indent=0)
return self._template
else:
dbg('exception raised:', e, indent=0)
raise ValueError ('wxMaskedNumCtrl requires numeric value, passed %s'% repr(value) )
# else...
try:
if self._fractionWidth or value.find('.') != -1:
value = float(value)
@@ -1367,7 +1454,7 @@ class wxMaskedNumCtrl(wxMaskedTextCtrl):
# So, to ensure consistency and to prevent spurious ValueErrors,
# we make the following test, and react accordingly:
#
if value == '':
if value.strip() == '':
if not self.IsNoneAllowed():
dbg('empty value; not allowed,returning 0', indent = 0)
if self._fractionWidth:
@@ -1503,3 +1590,12 @@ i=0
## =============================##
## 1. Add support for printf-style format specification.
## 2. Add option for repositioning on 'illegal' insertion point.
##
## Version 1.1
## 1. Fixed .SetIntegerWidth() and .SetFractionWidth() functions.
## 2. Added autoSize parameter, to allow manual sizing of the control.
## 3. Changed inheritance to use wxBaseMaskedTextCtrl, to remove exposure of
## nonsensical parameter methods from the control, so it will work
## properly with Boa.
## 4. Fixed allowNone bug found by user sameerc1@grandecom.net

View File

@@ -53,7 +53,9 @@ Here's the API for wxTimeCtrl:
<B>style</B> = wxTE_PROCESS_TAB,
<B>validator</B> = wxDefaultValidator,
name = "time",
<B>format</B> = 'HHMMSS',
<B>fmt24hr</B> = False,
<B>displaySeconds</B> = True,
<B>spinButton</B> = None,
<B>min</B> = None,
<B>max</B> = None,
@@ -77,10 +79,21 @@ Here's the API for wxTimeCtrl:
of its validation for entry control is handled internally. However, a validator
can be supplied to provide data transfer capability to the control.
<BR>
<DT><B>format</B>
<DD>This parameter can be used instead of the fmt24hr and displaySeconds
parameters, respectively; it provides a shorthand way to specify the time
format you want. Accepted values are 'HHMMSS', 'HHMM', '24HHMMSS', and
'24HHMM'. If the format is specified, the other two arguments will be ignored.
<DT><B>fmt24hr</B>
<DD>If True, control will display time in 24 hour time format; if False, it will
use 12 hour AM/PM format. SetValue() will adjust values accordingly for the
control, based on the format specified.
control, based on the format specified. (This value is ignored if the <i>format</i>
parameter is specified.)
<BR>
<DT><B>displaySeconds</B>
<DD>If True, control will include a seconds field; if False, it will
just show hours and minutes. (This value is ignored if the <i>format</i>
parameter is specified.)
<BR>
<DT><B>spinButton</B>
<DD>If specified, this button's events will be bound to the behavior of the
@@ -242,7 +255,7 @@ value to fall within the current bounds.
import string, copy
from wxPython.wx import *
from wxPython.tools.dbg import Logger
from wxPython.lib.maskededit import wxMaskedTextCtrl, Field
from wxPython.lib.maskededit import wxBaseMaskedTextCtrl, Field
import wxPython.utils
dbg = Logger()
dbg(enable=0)
@@ -267,11 +280,41 @@ class TimeUpdatedEvent(wxPyCommandEvent):
"""Retrieve the value of the time control at the time this event was generated"""
return self.value
class wxTimeCtrlAccessorsMixin:
# Define wxMaskedNumCtrl's list of attributes having their own
# Get/Set functions, ignoring those that make no sense for
# an numeric control.
exposed_basectrl_params = (
'defaultValue',
'description',
class wxTimeCtrl(wxMaskedTextCtrl):
'useFixedWidthFont',
'emptyBackgroundColour',
'validBackgroundColour',
'invalidBackgroundColour',
'validFunc',
'validRequired',
)
for param in exposed_basectrl_params:
propname = param[0].upper() + param[1:]
exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
if param.find('Colour') != -1:
# add non-british spellings, for backward-compatibility
propname.replace('Colour', 'Color')
exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
class wxTimeCtrl(wxBaseMaskedTextCtrl):
valid_ctrl_params = {
'display_seconds' : True, # by default, shows seconds
'format' : 'HHMMSS', # default format code
'displaySeconds' : True, # by default, shows seconds
'min': None, # by default, no bounds set
'max': None,
'limited': False, # by default, no limiting even if bounds set
@@ -303,60 +346,39 @@ class wxTimeCtrl(wxMaskedTextCtrl):
limited = self.__limited
self.__posCurrent = 0
# handle deprecated keword argument name:
if kwargs.has_key('display_seconds'):
kwargs['displaySeconds'] = kwargs['display_seconds']
del kwargs['display_seconds']
if not kwargs.has_key('displaySeconds'):
kwargs['displaySeconds'] = True
# (handle positional args (from original release) differently from rest of kwargs:)
self.__fmt24hr = fmt24hr
# (handle positional arg (from original release) differently from rest of kwargs:)
self.__fmt24hr = False
if not kwargs.has_key('format'):
if fmt24hr:
if kwargs.has_key('displaySeconds') and kwargs['displaySeconds']:
kwargs['format'] = '24HHMMSS'
del kwargs['displaySeconds']
else:
kwargs['format'] = '24HHMM'
else:
if kwargs.has_key('displaySeconds') and kwargs['displaySeconds']:
kwargs['format'] = 'HHMMSS'
del kwargs['displaySeconds']
else:
kwargs['format'] = 'HHMM'
maskededit_kwargs = {}
if not kwargs.has_key('useFixedWidthFont'):
# allow control over font selection:
kwargs['useFixedWidthFont'] = self.__useFixedWidthFont
# assign keyword args as appropriate:
for key, param_value in kwargs.items():
if key not in wxTimeCtrl.valid_ctrl_params.keys():
raise AttributeError('invalid keyword argument "%s"' % key)
maskededit_kwargs = self.SetParameters(**kwargs)
if key == "display_seconds":
self.__display_seconds = param_value
elif key == "min": min = param_value
elif key == "max": max = param_value
elif key == "limited": limited = param_value
elif key == "useFixedWidthFont":
maskededit_kwargs[key] = param_value
elif key == "oob_color":
maskededit_kwargs['invalidBackgroundColor'] = param_value
if self.__fmt24hr:
if self.__display_seconds: maskededit_kwargs['autoformat'] = 'MILTIMEHHMMSS'
else: maskededit_kwargs['autoformat'] = 'MILTIMEHHMM'
# Set hour field to zero-pad, right-insert, require explicit field change,
# select entire field on entry, and require a resultant valid entry
# to allow character entry:
hourfield = Field(formatcodes='0r<SV', validRegex='0\d|1\d|2[0123]', validRequired=True)
else:
if self.__display_seconds: maskededit_kwargs['autoformat'] = 'TIMEHHMMSS'
else: maskededit_kwargs['autoformat'] = 'TIMEHHMM'
# Set hour field to allow spaces (at start), right-insert,
# require explicit field change, select entire field on entry,
# and require a resultant valid entry to allow character entry:
hourfield = Field(formatcodes='_0<rSV', validRegex='0[1-9]| [1-9]|1[012]', validRequired=True)
ampmfield = Field(formatcodes='S', emptyInvalid = True, validRequired = True)
# Field 1 is always a zero-padded right-insert minute field,
# similarly configured as above:
minutefield = Field(formatcodes='0r<SV', validRegex='[0-5]\d', validRequired=True)
fields = [ hourfield, minutefield ]
if self.__display_seconds:
fields.append(copy.copy(minutefield)) # second field has same constraints as field 1
if not self.__fmt24hr:
fields.append(ampmfield)
# set fields argument:
maskededit_kwargs['fields'] = fields
# allow for explicit size specification:
if size != wxDefaultSize:
# override (and remove) "autofit" autoformat code in standard time formats:
maskededit_kwargs['formatcodes'] = 'T!'
# This allows range validation if set
maskededit_kwargs['validFunc'] = self.IsInBounds
@@ -365,16 +387,9 @@ class wxTimeCtrl(wxMaskedTextCtrl):
# dynamically without affecting individual field constraint validation
maskededit_kwargs['retainFieldValidation'] = True
# allow control over font selection:
maskededit_kwargs['useFixedWidthFont'] = self.__useFixedWidthFont
# allow for explicit size specification:
if size != wxDefaultSize:
# override (and remove) "autofit" autoformat code in standard time formats:
maskededit_kwargs['formatcodes'] = 'T!'
# Now we can initialize the base control:
wxMaskedTextCtrl.__init__(
wxBaseMaskedTextCtrl.__init__(
self, parent, id=id,
pos=pos, size=size,
style = style,
@@ -411,7 +426,7 @@ class wxTimeCtrl(wxMaskedTextCtrl):
EVT_LEFT_DCLICK(self, self._OnDoubleClick ) ## select field under cursor on dclick
EVT_KEY_DOWN( self, self._OnKeyDown ) ## capture control events not normally seen, eg ctrl-tab.
EVT_CHAR( self, self.__OnChar ) ## remove "shift" attribute from colon key event,
## then call wxMaskedTextCtrl._OnChar with
## then call wxBaseMaskedTextCtrl._OnChar with
## the possibly modified event.
EVT_TEXT( self, self.GetId(), self.__OnTextChange ) ## color control appropriately and EVT_TIMEUPDATE events
@@ -428,6 +443,111 @@ class wxTimeCtrl(wxMaskedTextCtrl):
self.BindSpinButton(spinButton) # bind spin button up/down events to this control
def SetParameters(self, **kwargs):
dbg('wxTimeCtrl::SetParameters(%s)' % repr(kwargs), indent=1)
maskededit_kwargs = {}
reset_format = False
if kwargs.has_key('display_seconds'):
kwargs['displaySeconds'] = kwargs['display_seconds']
del kwargs['display_seconds']
if kwargs.has_key('format') and kwargs.has_key('displaySeconds'):
del kwargs['displaySeconds'] # always apply format if specified
# assign keyword args as appropriate:
for key, param_value in kwargs.items():
if key not in wxTimeCtrl.valid_ctrl_params.keys():
raise AttributeError('invalid keyword argument "%s"' % key)
if key == 'format':
# handle both local or generic 'maskededit' autoformat codes:
if param_value == 'HHMMSS' or param_value == 'TIMEHHMMSS':
self.__displaySeconds = True
self.__fmt24hr = False
elif param_value == 'HHMM' or param_value == 'TIMEHHMM':
self.__displaySeconds = False
self.__fmt24hr = False
elif param_value == '24HHMMSS' or param_value == '24HRTIMEHHMMSS':
self.__displaySeconds = True
self.__fmt24hr = True
elif param_value == '24HHMM' or param_value == '24HRTIMEHHMM':
self.__displaySeconds = False
self.__fmt24hr = True
else:
raise AttributeError('"%s" is not a valid format' % param_value)
reset_format = True
elif key in ("displaySeconds", "display_seconds") and not kwargs.has_key('format'):
self.__displaySeconds = param_value
reset_format = True
elif key == "min": min = param_value
elif key == "max": max = param_value
elif key == "limited": limited = param_value
elif key == "useFixedWidthFont":
maskededit_kwargs[key] = param_value
elif key == "oob_color":
maskededit_kwargs['invalidBackgroundColor'] = param_value
if reset_format:
if self.__fmt24hr:
if self.__displaySeconds: maskededit_kwargs['autoformat'] = '24HRTIMEHHMMSS'
else: maskededit_kwargs['autoformat'] = '24HRTIMEHHMM'
# Set hour field to zero-pad, right-insert, require explicit field change,
# select entire field on entry, and require a resultant valid entry
# to allow character entry:
hourfield = Field(formatcodes='0r<SV', validRegex='0\d|1\d|2[0123]', validRequired=True)
else:
if self.__displaySeconds: maskededit_kwargs['autoformat'] = 'TIMEHHMMSS'
else: maskededit_kwargs['autoformat'] = 'TIMEHHMM'
# Set hour field to allow spaces (at start), right-insert,
# require explicit field change, select entire field on entry,
# and require a resultant valid entry to allow character entry:
hourfield = Field(formatcodes='_0<rSV', validRegex='0[1-9]| [1-9]|1[012]', validRequired=True)
ampmfield = Field(formatcodes='S', emptyInvalid = True, validRequired = True)
# Field 1 is always a zero-padded right-insert minute field,
# similarly configured as above:
minutefield = Field(formatcodes='0r<SV', validRegex='[0-5]\d', validRequired=True)
fields = [ hourfield, minutefield ]
if self.__displaySeconds:
fields.append(copy.copy(minutefield)) # second field has same constraints as field 1
if not self.__fmt24hr:
fields.append(ampmfield)
# set fields argument:
maskededit_kwargs['fields'] = fields
# This allows range validation if set
maskededit_kwargs['validFunc'] = self.IsInBounds
# This allows range limits to affect insertion into control or not
# dynamically without affecting individual field constraint validation
maskededit_kwargs['retainFieldValidation'] = True
if hasattr(self, 'controlInitialized') and self.controlInitialized:
self.SetCtrlParameters(**maskededit_kwargs) # set appropriate parameters
# Validate initial value and set if appropriate
try:
self.SetBounds(min, max)
self.SetLimited(limited)
self.SetValue(value)
except:
self.SetValue('12:00:00 AM')
dbg(indent=0)
return {} # no arguments to return
else:
dbg(indent=0)
return maskededit_kwargs
def BindSpinButton(self, sb):
"""
@@ -482,7 +602,7 @@ class wxTimeCtrl(wxMaskedTextCtrl):
elif as_mxDateTimeDelta:
value = DateTime.DateTimeDelta(0, value.GetHour(), value.GetMinute(), value.GetSecond())
else:
value = wxMaskedTextCtrl.GetValue(self)
value = wxBaseMaskedTextCtrl.GetValue(self)
return value
@@ -874,6 +994,16 @@ class wxTimeCtrl(wxMaskedTextCtrl):
except ValueError:
return False
def SetFormat(self, format):
self.SetParameters(format=format)
def GetFormat(self):
if self.__displaySeconds:
if self.__fmt24hr: return '24HHMMSS'
else: return 'HHMMSS'
else:
if self.__fmt24hr: return '24HHMM'
else: return 'HHMM'
#-------------------------------------------------------------------------------------------------------------
# these are private functions and overrides:
@@ -891,7 +1021,7 @@ class wxTimeCtrl(wxMaskedTextCtrl):
## event iff the value has actually changed. The masked edit
## OnTextChange routine does this, and returns True on a valid event,
## False otherwise.
if not wxMaskedTextCtrl._OnTextChange(self, event):
if not wxBaseMaskedTextCtrl._OnTextChange(self, event):
return
dbg('firing TimeUpdatedEvent...')
@@ -908,7 +1038,7 @@ class wxTimeCtrl(wxMaskedTextCtrl):
point is lost when the focus shifts to the spin button.
"""
dbg('wxTimeCtrl::SetInsertionPoint', pos, indent=1)
wxMaskedTextCtrl.SetInsertionPoint(self, pos) # (causes EVT_TEXT event to fire)
wxBaseMaskedTextCtrl.SetInsertionPoint(self, pos) # (causes EVT_TEXT event to fire)
self.__posCurrent = self.GetInsertionPoint()
dbg(indent=0)
@@ -927,7 +1057,7 @@ class wxTimeCtrl(wxMaskedTextCtrl):
sel_to = cell_end
self.__bSelection = sel_start != sel_to
wxMaskedTextCtrl.SetSelection(self, sel_start, sel_to)
wxBaseMaskedTextCtrl.SetSelection(self, sel_start, sel_to)
dbg(indent=0)
@@ -984,7 +1114,7 @@ class wxTimeCtrl(wxMaskedTextCtrl):
if keycode == ord(':'):
dbg('colon seen! removing shift attribute')
event.m_shiftDown = False
wxMaskedTextCtrl._OnChar(self, event ) ## handle each keypress
wxBaseMaskedTextCtrl._OnChar(self, event ) ## handle each keypress
dbg(indent=0)
@@ -1070,10 +1200,10 @@ class wxTimeCtrl(wxMaskedTextCtrl):
converts it to a string appropriate for the format of the control.
"""
if self.__fmt24hr:
if self.__display_seconds: strval = wxdt.Format('%H:%M:%S')
if self.__displaySeconds: strval = wxdt.Format('%H:%M:%S')
else: strval = wxdt.Format('%H:%M')
else:
if self.__display_seconds: strval = wxdt.Format('%I:%M:%S %p')
if self.__displaySeconds: strval = wxdt.Format('%I:%M:%S %p')
else: strval = wxdt.Format('%I:%M %p')
return strval
@@ -1164,3 +1294,11 @@ if __name__ == '__main__':
app.MainLoop()
except:
traceback.print_exc()
i=0
## Version 1.2
## 1. Changed parameter name display_seconds to displaySeconds, to follow
## other masked edit conventions.
## 2. Added format parameter, to remove need to use both fmt24hr and displaySeconds.
## 3. Changed inheritance to use wxBaseMaskedTextCtrl, to remove exposure of
## nonsensical parameter methods from the control, so it will work
## properly with Boa.

View File

@@ -61,6 +61,10 @@ def getAttributeNames(object, includeMagic=1, includeSingle=1,
for item in attributes:
dict[item] = None
attributes = dict.keys()
# new-style swig wrappings can result in non-string attributes
# e.g. ITK http://www.itk.org/
attributes = [attribute for attribute in attributes \
if type(attribute) == str]
attributes.sort(lambda x, y: cmp(x.upper(), y.upper()))
if not includeSingle:
attributes = filter(lambda item: item[0]!='_' \