]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/lib/masked/ipaddrctrl.py
Added new MaskedEditControl code from Will Sadkin. The modules are
[wxWidgets.git] / wxPython / wx / lib / masked / ipaddrctrl.py
CommitLineData
c878ceea
RD
1#----------------------------------------------------------------------------
2# Name: masked.ipaddrctrl.py
3# Authors: Will Sadkin
4# Email: wsadkin@nameconnector.com
5# Created: 02/11/2003
6# Copyright: (c) 2003 by Will Sadkin, 2003
7# RCS-ID: $Id$
8# License: wxWidgets license
9#----------------------------------------------------------------------------
10# NOTE:
11# Masked.IpAddrCtrl is a minor modification to masked.TextCtrl, that is
12# specifically tailored for entering IP addresses. It allows for
13# right-insert fields and provides an accessor to obtain the entered
14# address with extra whitespace removed.
15#
16#----------------------------------------------------------------------------
17
18import wx
19from wx.lib.masked import BaseMaskedTextCtrl
20
21# jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would
22# be a good place to implement the 2.3 logger class
23from wx.tools.dbg import Logger
24dbg = Logger()
25##dbg(enable=0)
26
27class IpAddrCtrlAccessorsMixin:
28 # Define IpAddrCtrl's list of attributes having their own
29 # Get/Set functions, exposing only those that make sense for
30 # an IP address control.
31
32 exposed_basectrl_params = (
33 'fields',
34 'retainFieldValidation',
35 'formatcodes',
36 'fillChar',
37 'defaultValue',
38 'description',
39
40 'useFixedWidthFont',
41 'signedForegroundColour',
42 'emptyBackgroundColour',
43 'validBackgroundColour',
44 'invalidBackgroundColour',
45
46 'emptyInvalid',
47 'validFunc',
48 'validRequired',
49 )
50
51 for param in exposed_basectrl_params:
52 propname = param[0].upper() + param[1:]
53 exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
54 exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
55
56 if param.find('Colour') != -1:
57 # add non-british spellings, for backward-compatibility
58 propname.replace('Colour', 'Color')
59
60 exec('def Set%s(self, value): self.SetCtrlParameters(%s=value)' % (propname, param))
61 exec('def Get%s(self): return self.GetCtrlParameter("%s")''' % (propname, param))
62
63
64class IpAddrCtrl( BaseMaskedTextCtrl, IpAddrCtrlAccessorsMixin ):
65 """
66 This class is a particular type of MaskedTextCtrl that accepts
67 and understands the semantics of IP addresses, reformats input
68 as you move from field to field, and accepts '.' as a navigation
69 character, so that typing an IP address can be done naturally.
70 """
71
72
73
74 def __init__( self, parent, id=-1, value = '',
75 pos = wx.DefaultPosition,
76 size = wx.DefaultSize,
77 style = wx.TE_PROCESS_TAB,
78 validator = wx.DefaultValidator,
79 name = 'IpAddrCtrl',
80 setupEventHandling = True, ## setup event handling by default
81 **kwargs):
82
83 if not kwargs.has_key('mask'):
84 kwargs['mask'] = mask = "###.###.###.###"
85 if not kwargs.has_key('formatcodes'):
86 kwargs['formatcodes'] = 'F_Sr<'
87 if not kwargs.has_key('validRegex'):
88 kwargs['validRegex'] = "( \d| \d\d|(1\d\d|2[0-4]\d|25[0-5]))(\.( \d| \d\d|(1\d\d|2[0-4]\d|25[0-5]))){3}"
89
90
91 BaseMaskedTextCtrl.__init__(
92 self, parent, id=id, value = value,
93 pos=pos, size=size,
94 style = style,
95 validator = validator,
96 name = name,
97 setupEventHandling = setupEventHandling,
98 **kwargs)
99
100
101 # set up individual field parameters as well:
102 field_params = {}
103 field_params['validRegex'] = "( | \d| \d |\d | \d\d|\d\d |\d \d|(1\d\d|2[0-4]\d|25[0-5]))"
104
105 # require "valid" string; this prevents entry of any value > 255, but allows
106 # intermediate constructions; overall control validation requires well-formatted value.
107 field_params['formatcodes'] = 'V'
108
109 if field_params:
110 for i in self._field_indices:
111 self.SetFieldParameters(i, **field_params)
112
113 # This makes '.' act like tab:
114 self._AddNavKey('.', handler=self.OnDot)
115 self._AddNavKey('>', handler=self.OnDot) # for "shift-."
116
117
118 def OnDot(self, event):
119## dbg('IpAddrCtrl::OnDot', indent=1)
120 pos = self._adjustPos(self._GetInsertionPoint(), event.GetKeyCode())
121 oldvalue = self.GetValue()
122 edit_start, edit_end, slice = self._FindFieldExtent(pos, getslice=True)
123 if not event.ShiftDown():
124 if pos > edit_start and pos < edit_end:
125 # clip data in field to the right of pos, if adjusting fields
126 # when not at delimeter; (assumption == they hit '.')
127 newvalue = oldvalue[:pos] + ' ' * (edit_end - pos) + oldvalue[edit_end:]
128 self._SetValue(newvalue)
129 self._SetInsertionPoint(pos)
130## dbg(indent=0)
131 return self._OnChangeField(event)
132
133
134
135 def GetAddress(self):
136 value = BaseMaskedTextCtrl.GetValue(self)
137 return value.replace(' ','') # remove spaces from the value
138
139
140 def _OnCtrl_S(self, event):
141## dbg("IpAddrCtrl::_OnCtrl_S")
142 if self._demo:
143 print "value:", self.GetAddress()
144 return False
145
146 def SetValue(self, value):
147## dbg('IpAddrCtrl::SetValue(%s)' % str(value), indent=1)
148 if type(value) not in (types.StringType, types.UnicodeType):
149## dbg(indent=0)
150 raise ValueError('%s must be a string', str(value))
151
152 bValid = True # assume True
153 parts = value.split('.')
154 if len(parts) != 4:
155 bValid = False
156 else:
157 for i in range(4):
158 part = parts[i]
159 if not 0 <= len(part) <= 3:
160 bValid = False
161 break
162 elif part.strip(): # non-empty part
163 try:
164 j = string.atoi(part)
165 if not 0 <= j <= 255:
166 bValid = False
167 break
168 else:
169 parts[i] = '%3d' % j
170 except:
171 bValid = False
172 break
173 else:
174 # allow empty sections for SetValue (will result in "invalid" value,
175 # but this may be useful for initializing the control:
176 parts[i] = ' ' # convert empty field to 3-char length
177
178 if not bValid:
179## dbg(indent=0)
180 raise ValueError('value (%s) must be a string of form n.n.n.n where n is empty or in range 0-255' % str(value))
181 else:
182## dbg('parts:', parts)
183 value = string.join(parts, '.')
184 BaseMaskedTextCtrl.SetValue(self, value)
185## dbg(indent=0)
186
187