- Added '*' mask char that means "all ansii chars" (ords 32-255)
    - Added proper unicode support to masked controls and wx.tools.dbg
    - Fixed two reported missing import bugs introduced by package
      creation
    - Converted masked package doc strings to reST format for better
      epydoc support
    - lots of doc string improvements and function hiding to better
      reflect package's public contents.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@29787 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
	
		
			
				
	
	
		
			221 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			221 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #----------------------------------------------------------------------------
 | |
| # Name:         masked.ipaddrctrl.py
 | |
| # Authors:      Will Sadkin
 | |
| # Email:        wsadkin@nameconnector.com
 | |
| # Created:      02/11/2003
 | |
| # Copyright:    (c) 2003 by Will Sadkin, 2003
 | |
| # RCS-ID:       $Id$
 | |
| # License:      wxWidgets license
 | |
| #----------------------------------------------------------------------------
 | |
| # NOTE:
 | |
| #   Masked.IpAddrCtrl is a minor modification to masked.TextCtrl, that is
 | |
| #   specifically tailored for entering IP addresses.  It allows for
 | |
| #   right-insert fields and provides an accessor to obtain the entered
 | |
| #   address with extra whitespace removed.
 | |
| #
 | |
| #----------------------------------------------------------------------------
 | |
| """
 | |
| Provides a smart text input control that understands the structure and
 | |
| limits of IP Addresses, and allows automatic field navigation as the
 | |
| user hits '.' when typing.
 | |
| """
 | |
| 
 | |
| import  wx, types, string
 | |
| from wx.lib.masked import BaseMaskedTextCtrl
 | |
| 
 | |
| # jmg 12/9/03 - when we cut ties with Py 2.2 and earlier, this would
 | |
| # be a good place to implement the 2.3 logger class
 | |
| from wx.tools.dbg import Logger
 | |
| ##dbg = Logger()
 | |
| ##dbg(enable=0)
 | |
| 
 | |
| class IpAddrCtrlAccessorsMixin:
 | |
|     """
 | |
|     Defines IpAddrCtrl's list of attributes having their own
 | |
|     Get/Set functions, exposing only those that make sense for
 | |
|     an IP address control.
 | |
|     """
 | |
| 
 | |
|     exposed_basectrl_params = (
 | |
|         'fields',
 | |
|         'retainFieldValidation',
 | |
|         'formatcodes',
 | |
|         'fillChar',
 | |
|         'defaultValue',
 | |
|         'description',
 | |
| 
 | |
|         'useFixedWidthFont',
 | |
|         '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 IpAddrCtrl( BaseMaskedTextCtrl, IpAddrCtrlAccessorsMixin ):
 | |
|     """
 | |
|     This class is a particular type of MaskedTextCtrl that accepts
 | |
|     and understands the semantics of IP addresses, reformats input
 | |
|     as you move from field to field, and accepts '.' as a navigation
 | |
|     character, so that typing an IP address can be done naturally.
 | |
|     """
 | |
| 
 | |
| 
 | |
| 
 | |
|     def __init__( self, parent, id=-1, value = '',
 | |
|                   pos = wx.DefaultPosition,
 | |
|                   size = wx.DefaultSize,
 | |
|                   style = wx.TE_PROCESS_TAB,
 | |
|                   validator = wx.DefaultValidator,
 | |
|                   name = 'IpAddrCtrl',
 | |
|                   setupEventHandling = True,        ## setup event handling by default
 | |
|                   **kwargs):
 | |
| 
 | |
|         if not kwargs.has_key('mask'):
 | |
|            kwargs['mask'] = mask = "###.###.###.###"
 | |
|         if not kwargs.has_key('formatcodes'):
 | |
|             kwargs['formatcodes'] = 'F_Sr<>'
 | |
|         if not kwargs.has_key('validRegex'):
 | |
|             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}"
 | |
| 
 | |
| 
 | |
|         BaseMaskedTextCtrl.__init__(
 | |
|                 self, parent, id=id, value = value,
 | |
|                 pos=pos, size=size,
 | |
|                 style = style,
 | |
|                 validator = validator,
 | |
|                 name = name,
 | |
|                 setupEventHandling = setupEventHandling,
 | |
|                 **kwargs)
 | |
| 
 | |
| 
 | |
|         # set up individual field parameters as well:
 | |
|         field_params = {}
 | |
|         field_params['validRegex'] = "(   |  \d| \d |\d  | \d\d|\d\d |\d \d|(1\d\d|2[0-4]\d|25[0-5]))"
 | |
| 
 | |
|         # require "valid" string; this prevents entry of any value > 255, but allows
 | |
|         # intermediate constructions; overall control validation requires well-formatted value.
 | |
|         field_params['formatcodes'] = 'V'
 | |
| 
 | |
|         if field_params:
 | |
|             for i in self._field_indices:
 | |
|                 self.SetFieldParameters(i, **field_params)
 | |
| 
 | |
|         # This makes '.' act like tab:
 | |
|         self._AddNavKey('.', handler=self.OnDot)
 | |
|         self._AddNavKey('>', handler=self.OnDot)    # for "shift-."
 | |
| 
 | |
| 
 | |
|     def OnDot(self, event):
 | |
|         """
 | |
|         Defines what action to take when the '.' character is typed in the
 | |
|         control.  By default, the current field is right-justified, and the
 | |
|         cursor is placed in the next field.
 | |
|         """
 | |
| ##        dbg('IpAddrCtrl::OnDot', indent=1)
 | |
|         pos = self._adjustPos(self._GetInsertionPoint(), event.GetKeyCode())
 | |
|         oldvalue = self.GetValue()
 | |
|         edit_start, edit_end, slice = self._FindFieldExtent(pos, getslice=True)
 | |
|         if not event.ShiftDown():
 | |
|             if pos > edit_start and pos < edit_end:
 | |
|                 # clip data in field to the right of pos, if adjusting fields
 | |
|                 # when not at delimeter; (assumption == they hit '.')
 | |
|                 newvalue = oldvalue[:pos] + ' ' * (edit_end - pos) + oldvalue[edit_end:]
 | |
|                 self._SetValue(newvalue)
 | |
|                 self._SetInsertionPoint(pos)
 | |
| ##        dbg(indent=0)
 | |
|         return self._OnChangeField(event)
 | |
| 
 | |
| 
 | |
| 
 | |
|     def GetAddress(self):
 | |
|         """
 | |
|         Returns the control value, with any spaces removed.
 | |
|         """
 | |
|         value = BaseMaskedTextCtrl.GetValue(self)
 | |
|         return value.replace(' ','')    # remove spaces from the value
 | |
| 
 | |
| 
 | |
|     def _OnCtrl_S(self, event):
 | |
| ##        dbg("IpAddrCtrl::_OnCtrl_S")
 | |
|         if self._demo:
 | |
|             print "value:", self.GetAddress()
 | |
|         return False
 | |
| 
 | |
|     def SetValue(self, value):
 | |
|         """
 | |
|         Takes a string value, validates it for a valid IP address,
 | |
|         splits it into an array of 4 fields, justifies it
 | |
|         appropriately, and inserts it into the control.
 | |
|         Invalid values will raise a ValueError exception.
 | |
|         """
 | |
| ##        dbg('IpAddrCtrl::SetValue(%s)' % str(value), indent=1)
 | |
|         if type(value) not in (types.StringType, types.UnicodeType):
 | |
| ##            dbg(indent=0)
 | |
|             raise ValueError('%s must be a string', str(value))
 | |
| 
 | |
|         bValid = True   # assume True
 | |
|         parts = value.split('.')
 | |
| 
 | |
|         if len(parts) != 4:
 | |
|             bValid = False
 | |
|         else:
 | |
|             for i in range(4):
 | |
|                 part = parts[i]
 | |
|                 if not 0 <= len(part) <= 3:
 | |
|                     bValid = False
 | |
|                     break
 | |
|                 elif part.strip():  # non-empty part
 | |
|                     try:
 | |
|                         j = string.atoi(part)
 | |
|                         if not 0 <= j <= 255:
 | |
|                             bValid = False
 | |
|                             break
 | |
|                         else:
 | |
|                             parts[i] = '%3d' % j
 | |
|                     except:
 | |
|                         bValid = False
 | |
|                         break
 | |
|                 else:
 | |
|                     # allow empty sections for SetValue (will result in "invalid" value,
 | |
|                     # but this may be useful for initializing the control:
 | |
|                     parts[i] = '   '    # convert empty field to 3-char length
 | |
| 
 | |
|         if not bValid:
 | |
| ##            dbg(indent=0)
 | |
|             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))
 | |
|         else:
 | |
| ##            dbg('parts:', parts)
 | |
|             value = string.join(parts, '.')
 | |
|             BaseMaskedTextCtrl.SetValue(self, value)
 | |
| ##        dbg(indent=0)
 | |
| 
 | |
| __i=0
 | |
| ## CHANGELOG:
 | |
| ## ====================
 | |
| ##  Version 1.2
 | |
| ##  1. Fixed bugs involving missing imports now that these classes are in
 | |
| ##     their own module.
 | |
| ##  2. Added doc strings for ePyDoc.
 | |
| ##  3. Renamed helper functions, vars etc. not intended to be visible in public
 | |
| ##     interface to code.
 | |
| ##
 | |
| ## Version 1.1
 | |
| ##  Made ipaddrctrls allow right-insert in subfields, now that insert/cut/paste works better
 |