chiark / gitweb /
Tell user to connect and power on 3D printer before attempting to flash firmware
[cura.git] / Cura / gui / configBase.py
1 from __future__ import division
2 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
3
4 import wx, wx.lib.stattext, types
5 from wx.lib.agw import floatspin
6
7 from Cura.util import validators
8 from Cura.util import profile
9 from Cura.gui import configWizard
10
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)
15                 
16                 self.settingControlList = []
17
18                 self._callback = changeCallback
19         
20         def CreateConfigTab(self, nb, name):
21                 leftConfigPanel, rightConfigPanel, configPanel = self.CreateConfigPanel(nb)
22                 nb.AddPage(configPanel, name)
23                 return leftConfigPanel, rightConfigPanel
24         
25         def CreateConfigPanel(self, parent):
26                 configPanel = wx.Panel(parent)
27                 leftConfigPanel = wx.Panel(configPanel)
28                 rightConfigPanel = wx.Panel(configPanel)
29
30                 sizer = wx.GridBagSizer(2, 2)
31                 leftConfigPanel.SetSizer(sizer)
32                 sizer = wx.GridBagSizer(2, 2)
33                 rightConfigPanel.SetSizer(sizer)
34
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
42
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)
48
49                 sizer = wx.GridBagSizer(2, 2)
50                 leftConfigPanel.SetSizer(sizer)
51                 #sizer.AddGrowableCol(1)
52
53                 sizer = wx.GridBagSizer(2, 2)
54                 rightConfigPanel.SetSizer(sizer)
55                 #sizer.AddGrowableCol(1)
56
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)
61
62                 configPanel.SetAutoLayout(1)
63                 configPanel.SetupScrolling(scroll_x=False, scroll_y=True)
64
65                 leftConfigPanel.main = self
66                 rightConfigPanel.main = self
67
68                 configPanel.leftPanel = leftConfigPanel
69                 configPanel.rightPanel = rightConfigPanel
70
71                 nb.AddPage(configPanel, name)
72
73                 return leftConfigPanel, rightConfigPanel, configPanel
74     
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())
79                 self.Update()
80
81         def _validate(self):
82                 for setting in self.settingControlList:
83                         setting._validate()
84                 if self._callback is not None:
85                         self._callback()
86
87         def getLabelColumnWidth(self, panel):
88                 maxWidth = 0
89                 for child in panel.GetChildren():
90                         if isinstance(child, wx.lib.stattext.GenStaticText):
91                                 maxWidth = max(maxWidth, child.GetSize()[0])
92                 return maxWidth
93         
94         def setLabelColumnWidth(self, panel, width):
95                 for child in panel.GetChildren():
96                         if isinstance(child, wx.lib.stattext.GenStaticText):
97                                 size = child.GetSize()
98                                 size[0] = width
99                                 child.SetBestSize(size)
100         
101 class TitleRow(object):
102         def __init__(self, panel, name):
103                 "Add a title row to the configuration panel"
104                 sizer = panel.GetSizer()
105                 x = sizer.GetRows()
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)
110                 sizer.SetRows(x + 2)
111
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()
116                 x = sizer.GetRows()
117                 y = 0
118                 flag = 0
119                 has_expert_settings = False
120
121                 self.setting = profile.settingsDictionary[configName]
122                 self.settingIndex = index
123                 self.validationMsg = ''
124                 self.panel = panel
125
126                 self.label = wx.lib.stattext.GenStaticText(panel, -1, self.setting.getLabel())
127                 self.label.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
128
129                 #if self.setting.getType() is types.FloatType and False:
130                 #       digits = 0
131                 #       while 1 / pow(10, digits) > defaultValue:
132                 #               digits += 1
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)
135                 #       flag = wx.EXPAND
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
149                         choices = choices[:]
150                         self._englishChoices = choices[:]
151                         if value not in choices and len(choices) > 0:
152                                 value = choices[0]
153                         for n in xrange(0, len(choices)):
154                                 choices[n] = _(choices[n])
155                         value = _(value)
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)
159                         flag = wx.EXPAND
160                 else:
161                         self.ctrl = wx.TextCtrl(panel, -1, self.setting.getValue(self.settingIndex))
162                         self.ctrl.Bind(wx.EVT_TEXT, self.OnSettingChange)
163                         flag = wx.EXPAND
164
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)
173                 sizer.SetRows(x+1)
174
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()
179                 else:
180                         self.defaultBGColour = self.ctrl.GetBackgroundColour()
181                 
182                 panel.main.settingControlList.append(self)
183
184         def OnMouseEnter(self, e):
185                 self.label.SetToolTipString(self.setting.getTooltip())
186                 self.ctrl.SetToolTipString(self.setting.getTooltip())
187
188         def OnMouseExit(self, e):
189                 self.label.SetToolTipString('')
190                 self.ctrl.SetToolTipString('')
191                 e.Skip()
192
193         def OnSettingChange(self, e):
194                 self.setting.setValue(self.GetValue(), self.settingIndex)
195                 self.panel.main._validate()
196
197         def OnExpertOpen(self, e):
198                 from Cura.gui import expertConfig
199
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)
204                 ecw.Centre()
205                 ecw.Show()
206
207         def _validate(self):
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()
211
212                 ctrl = self.ctrl
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')
219                 else:
220                         ctrl.SetBackgroundColour(self.defaultBGColour)
221                 ctrl.Refresh()
222
223                 self.validationMsg = msg
224
225         def GetValue(self):
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:
231                                 if _(ret) == value:
232                                         return ret
233                         return value
234                 else:
235                         return str(self.ctrl.GetValue())
236
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):
243                         try:
244                                 self.ctrl.SetValue(float(value))
245                         except ValueError:
246                                 pass
247                 elif isinstance(self.ctrl, wx.ComboBox):
248                         self.ctrl.SetValue(_(value))
249                 else:
250                         self.ctrl.SetValue(value)
251
252 class ToolHeadRow(object):
253         def __init__(self, panel, configName, index = None):
254                 sizer = panel.GetSizer()
255                 x = sizer.GetRows()
256                 y = 0
257                 flag = 0
258
259                 self.setting = profile.settingsDictionary[configName]
260                 self.settingIndex = index
261                 self.validationMsg = ''
262                 self.panel = panel
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)
268
269                 self.label = wx.lib.stattext.GenStaticText(panel, -1, self.setting.getLabel())
270                 self.label.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
271
272                 self.ctrl = wx.TextCtrl(self.subpanel, -1, self.setting.getValue(self.settingIndex))
273                 self.ctrl.SetMinSize((300, 20))
274                 self.ctrl.Enable(False)
275
276                 self.button = wx.Button(self.subpanel, -1, _("Change Tool Head"))
277
278                 flag = wx.EXPAND
279                 self.ctrl.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
280                 subsizer.Add(self.ctrl, 1, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
281                 subsizer.Add(self.button, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT,border=2)
282
283                 sizer.Add(self.label, (x,y), flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT,border=10)
284                 sizer.Add(self.subpanel, (x,y+1), flag=wx.ALIGN_CENTER_VERTICAL|flag)
285                 sizer.SetRows(x+1)
286
287                 panel.main.settingControlList.append(self)
288
289         def OnMouseEnter(self, e):
290                 self.label.SetToolTipString(self.setting.getTooltip())
291                 self.ctrl.SetToolTipString(self.setting.getTooltip())
292                 e.Skip()
293
294         def OnMouseExit(self, e):
295                 self.label.SetToolTipString('')
296                 self.ctrl.SetToolTipString('')
297                 e.Skip()
298
299         def GetValue(self):
300                 return str(self.ctrl.GetValue())
301
302         def SetValue(self, value):
303                 self.ctrl.SetValue(value)
304
305         def _validate(self):
306                 pass
307
308
309 class PopUp(wx.Frame):
310         def __init__(self, parent, id, text):
311                 wx.Frame.__init__(self, parent, id, 'Frame title', size=(400,300))
312                 panely = wx.Panel(self)         
313                 wx.StaticText(panely, -1, text, (10,10))