Source code for domdf_wxpython_tools.validators

#!/usr/bin/env python
#
#  validators.py
"""
Various validator classes
"""
#
#  Copyright (c) 2019-2020 Dominic Davis-Foster <dominic@davis-foster.co.uk>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#
#  Based on the wxPython Demo.
#  Licenced under the wxWindows Library Licence, Version 3.1
#
#  CharValidator based on
#  http://wxpython-users.1045709.n5.nabble.com/best-way-to-restrict-input-to-integers-td2370605.html
#

# stdlib
import string

# 3rd party
import wx  # type: ignore

__all__ = ["ValidatorBase", "CharValidator", "FloatValidator"]


[docs]class ValidatorBase(wx.Validator): """ Base class for Validators. """
[docs] def Clone(self): """ Clones the :class:`wx.Validator`. """ return self.__class__()
[docs] def TransferToWindow(self) -> bool: """ Transfer data from validator to window. The default implementation returns :py:obj:`False`, indicating that an error occurred. We simply return :py:obj:`True`, as we don't do any data transfer. """ return True # Prevent wxDialog from complaining.
[docs] def TransferFromWindow(self) -> bool: """ Transfer data from window to validator. The default implementation returns :py:obj:`False`, indicating that an error occurred. We simply return :py:obj:`True`, as we don't do any data transfer. """ return True # Prevent wxDialog from complaining.
[docs] def set_warning(self) -> bool: """ Set the control's background colour to pink. """ self.GetWindow().SetBackgroundColour("pink") self.GetWindow().SetFocus() self.GetWindow().Refresh() return False
[docs] def reset_ctrl(self) -> bool: """ Resets the control's background colour. """ self.GetWindow().SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)) self.GetWindow().Refresh() return True
[docs]class CharValidator(ValidatorBase): """ A Validator that only allows the type of characters selected to be entered. The possible flags are: * int-only - only the numbers ``0123456789`` can be entered. * float-only - only numbers and decimal points can be entered. """ def __init__(self, flag): wx.Validator.__init__(self) self.flag = flag self.Bind(wx.EVT_CHAR, self.OnChar) # Special allowed keys, including del, Ctrl+C, Ctrl+X and Ctrl+V self.special_keys = { wx.WXK_BACK, wx.WXK_TAB, wx.WXK_RETURN, wx.WXK_SHIFT, wx.WXK_CONTROL, wx.WXK_ALT, wx.WXK_CONTROL_C, wx.WXK_CONTROL_V, wx.WXK_CONTROL_X, wx.WXK_DELETE, }
[docs] def Clone(self): """ Clones the :class:`~.CharValidator`. """ return self.__class__(self.flag)
[docs] def Validate(self, win) -> bool: """ Validate the control. :param win: """ return True
[docs] def OnChar(self, event) -> None: """ Event handler for text being entered in the control. :param event: The wxPython event. """ keycode = int(event.GetKeyCode()) if keycode < 256: key = chr(keycode) if keycode in self.special_keys: event.Skip() if self.flag == "int-only": if key not in "0123456789": return elif self.flag == "float-only": if key == '.' and '.' in event.GetEventObject().GetValue(): return if key not in "0123456789.": return elif self.flag == "no-alpha" and key in string.ascii_letters: return elif self.flag == "no-digit" and key in string.digits: return event.Skip()
[docs]class FloatValidator(CharValidator): """ A Validator that only allows numbers and decimal points to be entered. If a decimal point has already been entered, a second one cannot be entered. The argument `flag` is used to limit the number of decimal places that can be entered. """
[docs] def OnChar(self, event) -> None: """ Event handler for text being entered in the control. :param event: The wxPython event. """ keycode = int(event.GetKeyCode()) if keycode < 256: key = chr(keycode) if keycode in self.special_keys: event.Skip() current_value = event.GetEventObject().GetValue() if key not in "0123456789.": return if '.' in current_value: if key == '.': if '.' not in event.GetEventObject().GetStringSelection(): return # Current decimal places current_dp = len(current_value.split('.')[1]) if current_dp == self.flag: # Already at maximum decimal places return event.Skip()