1 from __future__ import division
2 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
4 import wx, wx.lib.stattext, types
5 from wx.lib.agw import floatspin
7 from Cura.util import validators
8 from Cura.util import profile
9 from Cura.gui import configWizard
11 class configPanelBase(wx.Panel):
12 "A base class for configuration dialogs. Handles creation of settings, and popups"
13 def __init__(self, parent, changeCallback = None):
14 super(configPanelBase, self).__init__(parent)
16 self.settingControlList = []
18 self._callback = changeCallback
20 def CreateConfigTab(self, nb, name):
21 leftConfigPanel, rightConfigPanel, configPanel = self.CreateConfigPanel(nb)
22 nb.AddPage(configPanel, name)
23 return leftConfigPanel, rightConfigPanel
25 def CreateConfigPanel(self, parent):
26 configPanel = wx.Panel(parent)
27 leftConfigPanel = wx.Panel(configPanel)
28 rightConfigPanel = wx.Panel(configPanel)
30 sizer = wx.GridBagSizer(2, 2)
31 leftConfigPanel.SetSizer(sizer)
32 sizer = wx.GridBagSizer(2, 2)
33 rightConfigPanel.SetSizer(sizer)
35 sizer = wx.BoxSizer(wx.HORIZONTAL)
36 configPanel.SetSizer(sizer)
37 sizer.Add(leftConfigPanel, border=35, flag=wx.RIGHT)
38 sizer.Add(rightConfigPanel)
39 leftConfigPanel.main = self
40 rightConfigPanel.main = self
41 return leftConfigPanel, rightConfigPanel, configPanel
43 def CreateDynamicConfigTab(self, nb, name):
44 configPanel = wx.lib.scrolledpanel.ScrolledPanel(nb)
45 #configPanel = wx.Panel(nb);
46 leftConfigPanel = wx.Panel(configPanel)
47 rightConfigPanel = wx.Panel(configPanel)
49 sizer = wx.GridBagSizer(2, 2)
50 leftConfigPanel.SetSizer(sizer)
51 #sizer.AddGrowableCol(1)
53 sizer = wx.GridBagSizer(2, 2)
54 rightConfigPanel.SetSizer(sizer)
55 #sizer.AddGrowableCol(1)
57 sizer = wx.BoxSizer(wx.HORIZONTAL)
58 sizer.Add(leftConfigPanel, proportion=1, border=35, flag=wx.EXPAND)
59 sizer.Add(rightConfigPanel, proportion=1, flag=wx.EXPAND)
60 configPanel.SetSizer(sizer)
62 configPanel.SetAutoLayout(1)
63 configPanel.SetupScrolling(scroll_x=False, scroll_y=True)
65 leftConfigPanel.main = self
66 rightConfigPanel.main = self
68 configPanel.leftPanel = leftConfigPanel
69 configPanel.rightPanel = rightConfigPanel
71 nb.AddPage(configPanel, name)
73 return leftConfigPanel, rightConfigPanel, configPanel
75 def updateProfileToControls(self):
76 "Update the configuration wx controls to show the new configuration settings"
77 for setting in self.settingControlList:
78 setting.SetValue(setting.setting.getValue())
82 for setting in self.settingControlList:
84 if self._callback is not None:
87 def getLabelColumnWidth(self, panel):
89 for child in panel.GetChildren():
90 if isinstance(child, wx.lib.stattext.GenStaticText):
91 maxWidth = max(maxWidth, child.GetSize()[0])
94 def setLabelColumnWidth(self, panel, width):
95 for child in panel.GetChildren():
96 if isinstance(child, wx.lib.stattext.GenStaticText):
97 size = child.GetSize()
99 child.SetBestSize(size)
101 class TitleRow(object):
102 def __init__(self, panel, name):
103 "Add a title row to the configuration panel"
104 sizer = panel.GetSizer()
106 self.title = wx.StaticText(panel, -1, name.replace('&', '&&'))
107 self.title.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
108 sizer.Add(self.title, (x,0), (1,3), flag=wx.EXPAND|wx.TOP|wx.LEFT, border=10)
109 sizer.Add(wx.StaticLine(panel), (x+1,0), (1,4), flag=wx.EXPAND|wx.LEFT,border=10)
112 class SettingRow(object):
113 def __init__(self, panel, configName, valueOverride = None, index = None):
114 "Add a setting to the configuration panel"
115 sizer = panel.GetSizer()
119 has_expert_settings = False
121 self.setting = profile.settingsDictionary[configName]
122 self.settingIndex = index
123 self.validationMsg = ''
126 self.label = wx.lib.stattext.GenStaticText(panel, -1, self.setting.getLabel())
127 self.label.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
129 #if self.setting.getType() is types.FloatType and False:
131 # while 1 / pow(10, digits) > defaultValue:
133 # self.ctrl = floatspin.FloatSpin(panel, -1, value=float(getSettingFunc(configName)), increment=defaultValue, digits=digits, min_val=0.0)
134 # self.ctrl.Bind(floatspin.EVT_FLOATSPIN, self.OnSettingChange)
136 if self.setting.getType() is types.BooleanType:
137 self.ctrl = wx.CheckBox(panel, -1, style=wx.ALIGN_RIGHT)
138 self.SetValue(self.setting.getValue(self.settingIndex))
139 self.ctrl.Bind(wx.EVT_CHECKBOX, self.OnSettingChange)
140 elif valueOverride is not None and valueOverride is wx.Colour:
141 self.ctrl = wx.ColourPickerCtrl(panel, -1)
142 self.SetValue(self.setting.getValue(self.settingIndex))
143 self.ctrl.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnSettingChange)
144 elif type(self.setting.getType()) is list or valueOverride is not None:
145 value = self.setting.getValue(self.settingIndex)
146 choices = self.setting.getType()
147 if valueOverride is not None:
148 choices = valueOverride
150 self._englishChoices = choices[:]
151 if value not in choices and len(choices) > 0:
153 for n in xrange(0, len(choices)):
154 choices[n] = _(choices[n])
156 self.ctrl = wx.ComboBox(panel, -1, value, choices=choices, style=wx.CB_DROPDOWN|wx.CB_READONLY)
157 self.ctrl.Bind(wx.EVT_COMBOBOX, self.OnSettingChange)
158 self.ctrl.Bind(wx.EVT_LEFT_DOWN, self.OnMouseExit)
161 self.ctrl = wx.TextCtrl(panel, -1, self.setting.getValue(self.settingIndex))
162 self.ctrl.Bind(wx.EVT_TEXT, self.OnSettingChange)
165 self.ctrl.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
166 sizer.Add(self.label, (x,y), flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT,border=10)
167 sizer.Add(self.ctrl, (x,y+1), flag=wx.ALIGN_CENTER_VERTICAL|flag)
168 if self.setting.getExpertSubCategory() is not None:
169 self._expert_button = wx.Button(panel, -1, '...', style=wx.BU_EXACTFIT)
170 self._expert_button.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize() * 0.8, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_NORMAL))
171 self._expert_button.Bind(wx.EVT_BUTTON, self.OnExpertOpen)
172 sizer.Add(self._expert_button, (x,y+2), flag=wx.ALIGN_CENTER_VERTICAL)
175 self.ctrl.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
176 if isinstance(self.ctrl, floatspin.FloatSpin):
177 self.ctrl.GetTextCtrl().Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
178 self.defaultBGColour = self.ctrl.GetTextCtrl().GetBackgroundColour()
180 self.defaultBGColour = self.ctrl.GetBackgroundColour()
182 panel.main.settingControlList.append(self)
184 def OnMouseEnter(self, e):
185 self.label.SetToolTipString(self.setting.getTooltip())
186 self.ctrl.SetToolTipString(self.setting.getTooltip())
188 def OnMouseExit(self, e):
189 self.label.SetToolTipString('')
190 self.ctrl.SetToolTipString('')
193 def OnSettingChange(self, e):
194 self.setting.setValue(self.GetValue(), self.settingIndex)
195 self.panel.main._validate()
197 def OnExpertOpen(self, e):
198 from Cura.gui import expertConfig
200 expert_sub_category = self.setting.getExpertSubCategory()
201 if type(expert_sub_category) is list:
202 expert_sub_category = expert_sub_category[self.ctrl.GetSelection()]
203 ecw = expertConfig.expertConfigWindow(self.panel.main._callback, expert_sub_category)
208 if type(self.setting.getExpertSubCategory()) is list:
209 self._expert_button.Enable(self.setting.getExpertSubCategory()[self.ctrl.GetSelection()] is not None)
210 result, msg = self.setting.validate()
213 if isinstance(ctrl, floatspin.FloatSpin):
214 ctrl = ctrl.GetTextCtrl()
215 if result == validators.ERROR:
216 ctrl.SetBackgroundColour('Red')
217 elif result == validators.WARNING:
218 ctrl.SetBackgroundColour('Yellow')
220 ctrl.SetBackgroundColour(self.defaultBGColour)
223 self.validationMsg = msg
226 if isinstance(self.ctrl, wx.ColourPickerCtrl):
227 return str(self.ctrl.GetColour().GetAsString(wx.C2S_HTML_SYNTAX))
228 elif isinstance(self.ctrl, wx.ComboBox):
229 value = unicode(self.ctrl.GetValue())
230 for ret in self._englishChoices:
235 return str(self.ctrl.GetValue())
237 def SetValue(self, value):
238 if isinstance(self.ctrl, wx.CheckBox):
239 self.ctrl.SetValue(str(value) == "True")
240 elif isinstance(self.ctrl, wx.ColourPickerCtrl):
241 self.ctrl.SetColour(value)
242 elif isinstance(self.ctrl, floatspin.FloatSpin):
244 self.ctrl.SetValue(float(value))
247 elif isinstance(self.ctrl, wx.ComboBox):
248 self.ctrl.SetValue(_(value))
250 self.ctrl.SetValue(value)
252 class ToolheadRow(object):
253 def __init__(self, panel, configName, index = None):
254 sizer = panel.GetSizer()
259 self.setting = profile.settingsDictionary[configName]
260 self.settingIndex = index
261 self.validationMsg = ''
263 # We need a subpanel here because SettingRow always takes 2 grid spaces
264 # and we shouldn't take more than that.
265 self.subpanel = wx.Panel(self.panel)
266 subsizer = wx.BoxSizer(wx.HORIZONTAL)
267 self.subpanel.SetSizer(subsizer)
269 self.label = wx.lib.stattext.GenStaticText(panel, -1, self.setting.getLabel())
270 self.label.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
272 self.ctrl = wx.TextCtrl(self.subpanel, -1, self.setting.getValue(self.settingIndex))
273 self.ctrl.Enable(False)
275 self.button = wx.Button(self.subpanel, -1, _("Change Toolhead"))
278 self.ctrl.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
279 subsizer.Add(self.ctrl, 1, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
280 subsizer.Add(self.button, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT,border=2)
282 sizer.Add(self.label, (x,y), flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT,border=10)
283 sizer.Add(self.subpanel, (x,y+1), flag=wx.ALIGN_CENTER_VERTICAL|flag)
286 panel.main.settingControlList.append(self)
288 def OnMouseEnter(self, e):
289 self.label.SetToolTipString(self.setting.getTooltip())
290 self.ctrl.SetToolTipString(self.setting.getTooltip())
293 def OnMouseExit(self, e):
294 self.label.SetToolTipString('')
295 self.ctrl.SetToolTipString('')
299 return str(self.ctrl.GetValue())
301 def SetValue(self, value):
302 self.ctrl.SetValue(value)
308 class PopUp(wx.Frame):
309 def __init__(self, parent, id, text):
310 wx.Frame.__init__(self, parent, id, 'Frame title', size=(400,300))
311 panely = wx.Panel(self)
312 wx.StaticText(panely, -1, text, (10,10))