Rework target profile editor input boxes for better editing experience
This commit is contained in:
133
gui/utils/inputs.py
Normal file
133
gui/utils/inputs.py
Normal file
@@ -0,0 +1,133 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
|
||||
import re
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
import wx
|
||||
|
||||
|
||||
def valToStr(val):
|
||||
if val is None:
|
||||
return ''
|
||||
if int(val) == val:
|
||||
val = int(val)
|
||||
return str(val)
|
||||
|
||||
|
||||
def strToFloat(val):
|
||||
try:
|
||||
return float(val)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
||||
class InputValidator(metaclass=ABCMeta):
|
||||
|
||||
def validate(self, value):
|
||||
return self._validateWithReason(value)[0]
|
||||
|
||||
def getReason(self, value):
|
||||
return self._validateWithReason(value)[1]
|
||||
|
||||
@abstractmethod
|
||||
def _validateWithReason(self, value):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class FloatBox(wx.TextCtrl):
|
||||
|
||||
def __init__(self, parent, value, id=wx.ID_ANY, style=0, validator=None, **kwargs):
|
||||
super().__init__(parent=parent, id=id, style=style, **kwargs)
|
||||
self.Bind(wx.EVT_TEXT, self.OnText)
|
||||
self._storedValue = ''
|
||||
self._validator = validator
|
||||
self.ChangeValue(valToStr(value))
|
||||
|
||||
def ChangeValue(self, value):
|
||||
self._storedValue = value
|
||||
super().ChangeValue(value)
|
||||
self.updateColor()
|
||||
|
||||
def ChangeValueFloat(self, value):
|
||||
self.ChangeValue(valToStr(value))
|
||||
|
||||
def updateColor(self):
|
||||
if self.isValid():
|
||||
self.SetForegroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT))
|
||||
else:
|
||||
self.SetForegroundColour(wx.RED)
|
||||
|
||||
def isValid(self):
|
||||
if self._validator is None:
|
||||
return True
|
||||
return self._validator.validate(self.GetValue())
|
||||
|
||||
def getInvalidationReason(self):
|
||||
if self._validator is None:
|
||||
return None
|
||||
return self._validator.getReason(self.GetValue())
|
||||
|
||||
def OnText(self, event):
|
||||
currentValue = self.GetValue()
|
||||
if currentValue == self._storedValue:
|
||||
event.Skip()
|
||||
return
|
||||
if currentValue == '' or re.match('^\d*\.?\d*$', currentValue):
|
||||
self._storedValue = currentValue
|
||||
self.updateColor()
|
||||
event.Skip()
|
||||
else:
|
||||
self.ChangeValue(self._storedValue)
|
||||
|
||||
def GetValueFloat(self):
|
||||
return strToFloat(self.GetValue())
|
||||
|
||||
|
||||
class FloatRangeBox(wx.TextCtrl):
|
||||
|
||||
def __init__(self, parent, value, id=wx.ID_ANY, style=0, **kwargs):
|
||||
super().__init__(parent=parent, id=id, style=style, **kwargs)
|
||||
self.Bind(wx.EVT_TEXT, self.OnText)
|
||||
self._storedValue = ''
|
||||
self.ChangeValue('{}-{}'.format(valToStr(min(value)), valToStr(max(value))))
|
||||
|
||||
def ChangeValue(self, value):
|
||||
self._storedValue = value
|
||||
super().ChangeValue(value)
|
||||
|
||||
def OnText(self, event):
|
||||
currentValue = self.GetValue()
|
||||
if currentValue == self._storedValue:
|
||||
event.Skip()
|
||||
return
|
||||
if currentValue == '' or re.match('^\d*\.?\d*-?\d*\.?\d*$', currentValue):
|
||||
self._storedValue = currentValue
|
||||
event.Skip()
|
||||
else:
|
||||
self.ChangeValue(self._storedValue)
|
||||
|
||||
def GetValueRange(self):
|
||||
parts = self.GetValue().split('-')
|
||||
if len(parts) == 1:
|
||||
val = strToFloat(parts[0])
|
||||
return (val, val)
|
||||
else:
|
||||
return (strToFloat(parts[0]), strToFloat(parts[1]))
|
||||
Reference in New Issue
Block a user