]>
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