]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/masked/ipaddrctrl.py
1 #----------------------------------------------------------------------------
2 # Name: masked.ipaddrctrl.py
4 # Email: wsadkin@nameconnector.com
6 # Copyright: (c) 2003 by Will Sadkin, 2003
8 # License: wxWidgets license
9 #----------------------------------------------------------------------------
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.
16 #----------------------------------------------------------------------------
18 Provides a smart text input control that understands the structure and
19 limits of IP Addresses, and allows automatic field navigation as the
20 user hits '.' when typing.
23 import wx
, types
, string
24 from wx
.lib
.masked
import BaseMaskedTextCtrl
26 # jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would
27 # be a good place to implement the 2.3 logger class
28 from wx
.tools
.dbg
import Logger
32 class IpAddrCtrlAccessorsMixin
:
34 Defines IpAddrCtrl's list of attributes having their own
35 Get/Set functions, exposing only those that make sense for
36 an IP address control.
39 exposed_basectrl_params
= (
41 'retainFieldValidation',
48 'signedForegroundColour',
49 'emptyBackgroundColour',
50 'validBackgroundColour',
51 'invalidBackgroundColour',
58 for param
in exposed_basectrl_params
:
59 propname
= param
[0].upper() + param
[1:]
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))
63 if param.find('Colour
') != -1:
64 # add non-british spellings, for backward-compatibility
65 propname.replace('Colour
', 'Color
')
67 exec('def Set
%s(self
, value
): self
.SetCtrlParameters(%s=value
)' % (propname, param))
68 exec('def Get
%s(self
): return self
.GetCtrlParameter("%s")''' % (propname, param))
71 class IpAddrCtrl( BaseMaskedTextCtrl, IpAddrCtrlAccessorsMixin ):
73 This class is a particular type of MaskedTextCtrl that accepts
74 and understands the semantics of IP addresses, reformats input
75 as you move from field to field, and accepts '.' as a navigation
76 character, so that typing an IP address can be done naturally.
81 def __init__( self, parent, id=-1, value = '',
82 pos = wx.DefaultPosition,
83 size = wx.DefaultSize,
84 style = wx.TE_PROCESS_TAB,
85 validator = wx.DefaultValidator,
87 setupEventHandling = True, ## setup event handling by default
90 if not kwargs.has_key('mask'):
91 kwargs['mask'] = mask = "###.###.###.###"
92 if not kwargs.has_key('formatcodes'):
93 kwargs['formatcodes'] = 'F_Sr<>'
94 if not kwargs.has_key('validRegex'):
95 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}"
98 BaseMaskedTextCtrl.__init__(
99 self, parent, id=id, value = value,
102 validator = validator,
104 setupEventHandling = setupEventHandling,
108 # set up individual field parameters as well:
110 field_params['validRegex'] = "( | \d| \d |\d | \d\d|\d\d |\d \d|(1\d\d|2[0-4]\d|25[0-5]))"
112 # require "valid" string; this prevents entry of any value > 255, but allows
113 # intermediate constructions; overall control validation requires well-formatted value.
114 field_params['formatcodes'] = 'V'
117 for i in self._field_indices:
118 self.SetFieldParameters(i, **field_params)
120 # This makes '.' act like tab:
121 self._AddNavKey('.', handler=self.OnDot)
122 self._AddNavKey('>', handler=self.OnDot) # for "shift-."
125 def OnDot(self, event):
127 Defines what action to take when the '.' character is typed in the
128 control. By default, the current field is right-justified, and the
129 cursor is placed in the next field.
131 ## dbg('IpAddrCtrl::OnDot', indent=1)
132 pos = self._adjustPos(self._GetInsertionPoint(), event.GetKeyCode())
133 oldvalue = self.GetValue()
134 edit_start, edit_end, slice = self._FindFieldExtent(pos, getslice=True)
135 if not event.ShiftDown():
136 if pos > edit_start and pos < edit_end:
137 # clip data in field to the right of pos, if adjusting fields
138 # when not at delimeter; (assumption == they hit '.')
139 newvalue = oldvalue[:pos] + ' ' * (edit_end - pos) + oldvalue[edit_end:]
140 self._SetValue(newvalue)
141 self._SetInsertionPoint(pos)
143 return self._OnChangeField(event)
147 def GetAddress(self):
149 Returns the control value, with any spaces removed.
151 value = BaseMaskedTextCtrl.GetValue(self)
152 return value.replace(' ','') # remove spaces from the value
155 def _OnCtrl_S(self, event):
156 ## dbg("IpAddrCtrl::_OnCtrl_S")
158 print "value:", self.GetAddress()
161 def SetValue(self, value):
163 Takes a string value, validates it for a valid IP address,
164 splits it into an array of 4 fields, justifies it
165 appropriately, and inserts it into the control.
166 Invalid values will raise a ValueError exception.
168 ## dbg('IpAddrCtrl::SetValue(%s)' % str(value), indent=1)
169 if type(value) not in (types.StringType, types.UnicodeType):
171 raise ValueError('%s must be a string', str(value))
173 bValid = True # assume True
174 parts = value.split('.')
181 if not 0 <= len(part) <= 3:
184 elif part.strip(): # non-empty part
186 j = string.atoi(part)
187 if not 0 <= j <= 255:
196 # allow empty sections for SetValue (will result in "invalid" value,
197 # but this may be useful for initializing the control:
198 parts[i] = ' ' # convert empty field to 3-char length
202 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))
204 ## dbg('parts:', parts)
205 value = string.join(parts, '.')
206 BaseMaskedTextCtrl.SetValue(self, value)
211 ## ====================
213 ## 1. Fixed bugs involving missing imports now that these classes are in
215 ## 2. Added doc strings for ePyDoc.
216 ## 3. Renamed helper functions, vars etc. not intended to be visible in public
217 ## interface to code.
220 ## Made ipaddrctrls allow right-insert in subfields, now that insert/cut/paste works better