Added validators, which show red/yellow when validation generates a warning or error.

Added 'better' popup for tooltip help.
This commit is contained in:
daid 2012-02-24 17:07:03 +01:00
parent 86c8bc2288
commit 2c7adfe8ec
3 changed files with 108 additions and 19 deletions

View File

@ -19,6 +19,9 @@ def defaultSetting(setting):
def storedSetting(name):
return lambda setting: getSetting(name, setting.value)
def storedPercentSetting(name):
return lambda setting: float(getSetting(name, setting.value)) / 100
def getSkeinPyPyProfileInformation():
return {
'carve': {
@ -79,7 +82,7 @@ def getSkeinPyPyProfileInformation():
'Grid_Rectangular': defaultSetting,
'Line': defaultSetting,
'Infill_Perimeter_Overlap_ratio': defaultSetting,
'Infill_Solidity_ratio': defaultSetting,
'Infill_Solidity_ratio': storedPercentSetting('fill_density'),
'Infill_Width': defaultSetting,
'Solid_Surface_Thickness_layers': defaultSetting,
'Start_From_Choice': defaultSetting,
@ -157,7 +160,7 @@ def getSkeinPyPyProfileInformation():
'Gap_Width_mm': storedSetting("skirt_gap"),
'Layers_To_index': "1",
},'chamber': {
'Activate_Chamber': defaultSetting,
'Activate_Chamber': "False",
'Bed_Temperature_Celcius': defaultSetting,
'Bed_Temperature_Begin_Change_Height_mm': defaultSetting,
'Bed_Temperature_End_Change_Height_mm': defaultSetting,
@ -165,7 +168,7 @@ def getSkeinPyPyProfileInformation():
'Chamber_Temperature_Celcius': defaultSetting,
'Holding_Force_bar': defaultSetting,
},'tower': {
'Activate_Tower': defaultSetting,
'Activate_Tower': "False",
'Extruder_Possible_Collision_Cone_Angle_degrees': defaultSetting,
'Maximum_Tower_Height_layers': defaultSetting,
'Tower_Start_Layer_integer': defaultSetting,
@ -321,24 +324,24 @@ def loadGlobalProfile(filename):
def saveGlobalProfile(filename):
globalProfileParser.write(open(filename, 'w'))
def getSetting(name, default = ""):
def getSetting(name, default = "", section = 'profile'):
#Check if we have a configuration file loaded, else load the default.
if not globals().has_key('globalProfileParser'):
loadGlobalProfile(getDefaultProfilePath())
if not globalProfileParser.has_option("profile", name):
if not globalProfileParser.has_section("profile"):
globalProfileParser.add_section("profile")
globalProfileParser.set("profile", name, str(default))
if not globalProfileParser.has_option(section, name):
if not globalProfileParser.has_section(section):
globalProfileParser.add_section(section)
globalProfileParser.set(section, name, str(default))
return default
return globalProfileParser.get("profile", name)
return globalProfileParser.get(section, name)
def putSetting(name, value):
def putSetting(name, value, section = 'profile'):
#Check if we have a configuration file loaded, else load the default.
if not globals().has_key('globalProfileParser'):
loadGlobalProfile(getDefaultProfilePath())
if not globalProfileParser.has_section("profile"):
globalProfileParser.add_section("profile")
globalProfileParser.set("profile", name, str(value))
if not globalProfileParser.has_section(section):
globalProfileParser.add_section(section)
globalProfileParser.set(section, name, str(value))
def getDefaultProfilePath():
return os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../current_profile.ini"))

View File

@ -10,6 +10,7 @@ from skeinforge_application.skeinforge_utilities import skeinforge_profile
from newui import preview3d
from newui import sliceProgessPanel
from newui import alterationPanel
from newui import validators
def main():
app = wx.App(False)
@ -41,6 +42,7 @@ class mainWindow(wx.Frame):
self.filename = None
self.progressPanelList = []
self.controlList = []
self.validators = []
nb = wx.Notebook(self)
@ -58,13 +60,19 @@ class mainWindow(wx.Frame):
sizer.Add(rightConfigPanel)
self.AddTitle(leftConfigPanel, "Accuracy")
self.AddSetting(leftConfigPanel, "Layer height (mm)", 'layer_height', 'Layer height in millimeters.\n0.2 is a good value for quick prints.\n0.1 gives high quality prints.')
c = self.AddSetting(leftConfigPanel, "Layer height (mm)", 'layer_height', '0.2', 'Layer height in millimeters.\n0.2 is a good value for quick prints.\n0.1 gives high quality prints.')
validators.validFloat(c, 0.0)
c = self.AddSetting(leftConfigPanel, "Wall thickness (mm)", 'wall_thickness', '0.8', 'Thickness of the walls.\nThis is used in combination with the nozzle size to define the number\nof perimeter lines and the thickness of those perimeter lines.')
validators.validFloat(c, 0.0)
self.AddTitle(leftConfigPanel, "Fill")
#self.AddSetting(leftConfigPanel, "Solid layers", self.plugins['fill'].preferencesDict['Solid_Surface_Thickness_layers'])
#self.AddSetting(leftConfigPanel, "Fill Density", self.plugins['fill'].preferencesDict['Infill_Solidity_ratio'])
c = self.AddSetting(leftConfigPanel, "Fill Density (%)", 'fill_density', '20')
validators.validFloat(c, 0.0, 100.0)
self.AddTitle(leftConfigPanel, "Skirt")
self.AddSetting(leftConfigPanel, "Line count", 'skirt_line_count')
self.AddSetting(leftConfigPanel, "Start distance (mm)", 'skirt_gap')
c = self.AddSetting(leftConfigPanel, "Line count", 'skirt_line_count', '1')
validators.validInt(c, 0, 10)
c = self.AddSetting(leftConfigPanel, "Start distance (mm)", 'skirt_gap', '6.0')
validators.validFloat(c, 0.0)
self.AddTitle(leftConfigPanel, "Cool")
#self.AddSetting(configPanel, "Cool type", self.plugins['cool'].preferencesDict['Cool_Type'])
#self.AddSetting(leftConfigPanel, "Minimal layer time", self.plugins['cool'].preferencesDict['Minimum_Layer_Time_seconds'])
@ -126,6 +134,14 @@ class mainWindow(wx.Frame):
self.sizer = sizer
#Create the popup window
self.popup = wx.PopupWindow(self, wx.BORDER_SIMPLE)
self.popup.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOBK))
self.popup.text = wx.StaticText(self.popup, -1, '');
self.popup.sizer = wx.BoxSizer()
self.popup.sizer.Add(self.popup.text, flag=wx.EXPAND)
self.popup.SetSizer(self.popup.sizer)
self.Fit()
self.Centre()
self.Show(True)
@ -139,19 +155,46 @@ class mainWindow(wx.Frame):
sizer.Add(wx.StaticLine(panel), (sizer.GetRows()+1,sizer.GetCols()), (1,3), flag=wx.EXPAND)
sizer.SetRows(sizer.GetRows() + 2)
def AddSetting(self, panel, name, settingName, help = 'Help: TODO'):
def AddSetting(self, panel, name, settingName, default = '', help = 'Help: TODO'):
"Add a setting to the configuration panel"
sizer = panel.GetSizer()
sizer.Add(wx.StaticText(panel, -1, name), (sizer.GetRows(),sizer.GetCols()), flag=wx.ALIGN_CENTER_VERTICAL)
ctrl = wx.TextCtrl(panel, -1, settings.getSetting(settingName))
ctrl = wx.TextCtrl(panel, -1, settings.getSetting(settingName, default))
ctrl.settingName = settingName
ctrl.main = self
self.Bind(wx.EVT_TEXT, self.OnSettingTextChange, ctrl)
self.controlList.append(ctrl)
sizer.Add(ctrl, (sizer.GetRows(),sizer.GetCols()+1), flag=wx.ALIGN_BOTTOM|wx.EXPAND)
helpButton = wx.Button(panel, -1, "?", style=wx.BU_EXACTFIT)
sizer.Add(helpButton, (sizer.GetRows(),sizer.GetCols()+2))
helpButton.SetToolTip(wx.ToolTip(help))
sizer.SetRows(sizer.GetRows()+1)
ctrl.Bind(wx.EVT_ENTER_WINDOW, lambda e: self.OnPopupDisplay(ctrl, help))
ctrl.Bind(wx.EVT_LEAVE_WINDOW, self.OnPopupHide)
return ctrl
def OnPopupDisplay(self, e, helpText):
x, y = e.ClientToScreenXY(0, 0)
sx, sy = e.GetSizeTuple()
self.popup.text.SetLabel(helpText)
self.popup.SetPosition((x, y+sy))
self.popup.Fit()
self.popup.Show(True)
def OnPopupHide(self, e):
self.popup.Show(False)
def OnSettingTextChange(self, e):
for validator in self.validators:
res, err = validator.validate()
if res == validators.ERROR:
validator.ctrl.SetBackgroundColour('Red')
elif res == validators.WARNING:
validator.ctrl.SetBackgroundColour('Yellow')
else:
validator.ctrl.SetBackgroundColour(wx.NullColor)
def OnLoadProfile(self, e):
dlg=wx.FileDialog(self, "Select profile file to load", self.lastPath, style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)

View File

@ -0,0 +1,43 @@
from __future__ import absolute_import
import __init__
SUCCESS = 0
WARNING = 1
ERROR = 2
class validFloat():
def __init__(self, ctrl, minValue = None, maxValue = None):
self.ctrl = ctrl
self.ctrl.main.validators.append(self)
self.minValue = minValue
self.maxValue = maxValue
def validate(self):
try:
f = float(self.ctrl.GetValue())
if self.minValue != None and f < self.minValue:
return ERROR, 'Should not be below ' + str(self.minValue)
if self.maxValue != None and f > self.maxValue:
return ERROR, 'Should not be above ' + str(self.maxValue)
return SUCCESS, ''
except ValueError:
return ERROR, 'Not a valid number'
class validInt():
def __init__(self, ctrl, minValue = None, maxValue = None):
self.ctrl = ctrl
self.ctrl.main.validators.append(self)
self.minValue = minValue
self.maxValue = maxValue
def validate(self):
try:
f = int(self.ctrl.GetValue())
if self.minValue != None and f < self.minValue:
return ERROR, 'Should not be below ' + str(self.minValue)
if self.maxValue != None and f > self.maxValue:
return ERROR, 'Should not be above ' + str(self.maxValue)
return SUCCESS, ''
except ValueError:
return ERROR, 'Not a valid number'