chiark / gitweb /
Added validators, which show red/yellow when validation generates a warning or error.
authordaid <daid303@gmail.com>
Fri, 24 Feb 2012 16:07:03 +0000 (17:07 +0100)
committerdaid <daid303@gmail.com>
Fri, 24 Feb 2012 16:07:03 +0000 (17:07 +0100)
Added 'better' popup for tooltip help.

SkeinPyPy_NewUI/fabmetheus_utilities/settings.py
SkeinPyPy_NewUI/newui/mainWindow.py
SkeinPyPy_NewUI/newui/validators.py [new file with mode: 0644]

index 9817c1152fb5598ff5348a0171c4d012b718fc0a..43c5c931e815b0e402c9bc3cb3d726ccc48afcae 100644 (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"))
index f629b8812dbf46444812bcd5ac05434fe582c060..542b7ab3659dae7a138eb6815649369187b4ba1d 100644 (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)
diff --git a/SkeinPyPy_NewUI/newui/validators.py b/SkeinPyPy_NewUI/newui/validators.py
new file mode 100644 (file)
index 0000000..b8b013e
--- /dev/null
@@ -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'
+