chiark / gitweb /
Add wipe tower size setting.
[cura.git] / Cura / gui / configBase.py
1 from __future__ import absolute_import
2 from __future__ import division
3 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
4
5 import wx, wx.lib.stattext, types
6 from wx.lib.agw import floatspin
7
8 from Cura.util import validators
9 from Cura.util import profile
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                 #Create the popup window
19                 self.popup = wx.PopupWindow(self, flags=wx.BORDER_SIMPLE)
20                 self.popup.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOBK))
21                 self.popup.setting = None
22                 self.popup.text = wx.StaticText(self.popup, -1, '')
23                 self.popup.text.SetForegroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOTEXT))
24                 self.popup.sizer = wx.BoxSizer()
25                 self.popup.sizer.Add(self.popup.text, flag=wx.EXPAND|wx.ALL, border=1)
26                 self.popup.SetSizer(self.popup.sizer)
27
28                 self._callback = changeCallback
29         
30         def CreateConfigTab(self, nb, name):
31                 leftConfigPanel, rightConfigPanel, configPanel = self.CreateConfigPanel(nb)
32                 nb.AddPage(configPanel, name)
33                 return leftConfigPanel, rightConfigPanel
34         
35         def CreateConfigPanel(self, parent):
36                 configPanel = wx.Panel(parent);
37                 leftConfigPanel = wx.Panel(configPanel)
38                 rightConfigPanel = wx.Panel(configPanel)
39
40                 sizer = wx.GridBagSizer(2, 2)
41                 leftConfigPanel.SetSizer(sizer)
42                 sizer = wx.GridBagSizer(2, 2)
43                 rightConfigPanel.SetSizer(sizer)
44
45                 sizer = wx.BoxSizer(wx.HORIZONTAL)
46                 configPanel.SetSizer(sizer)
47                 sizer.Add(leftConfigPanel, border=35, flag=wx.RIGHT)
48                 sizer.Add(rightConfigPanel)
49                 leftConfigPanel.main = self
50                 rightConfigPanel.main = self
51                 return leftConfigPanel, rightConfigPanel, configPanel
52
53         def CreateDynamicConfigTab(self, nb, name):
54                 configPanel = wx.lib.scrolledpanel.ScrolledPanel(nb)    
55                 #configPanel = wx.Panel(nb);
56                 leftConfigPanel = wx.Panel(configPanel)
57                 rightConfigPanel = wx.Panel(configPanel)
58
59                 sizer = wx.GridBagSizer(2, 2)
60                 leftConfigPanel.SetSizer(sizer)
61                 #sizer.AddGrowableCol(1)
62
63                 sizer = wx.GridBagSizer(2, 2)
64                 rightConfigPanel.SetSizer(sizer)
65                 #sizer.AddGrowableCol(1)
66
67                 sizer = wx.BoxSizer(wx.HORIZONTAL)
68                 sizer.Add(leftConfigPanel, proportion=1, border=35, flag=wx.EXPAND)
69                 sizer.Add(rightConfigPanel, proportion=1, flag=wx.EXPAND)
70                 configPanel.SetSizer(sizer)
71
72                 configPanel.SetAutoLayout(1)
73                 configPanel.SetupScrolling(scroll_x=False, scroll_y=True)
74
75                 leftConfigPanel.main = self
76                 rightConfigPanel.main = self
77
78                 configPanel.leftPanel = leftConfigPanel
79                 configPanel.rightPanel = rightConfigPanel
80
81                 nb.AddPage(configPanel, name)
82
83                 return leftConfigPanel, rightConfigPanel, configPanel
84
85         def OnPopupDisplay(self, setting):
86                 self.popup.setting = setting
87                 self.UpdatePopup(setting)
88                 self.popup.Show(True)
89                 
90         def OnPopupHide(self, e):
91                 self.popup.Show(False)
92         
93         def UpdatePopup(self, setting):
94                 if self.popup.setting == setting:
95                         if setting.validationMsg != '':
96                                 self.popup.text.SetLabel(setting.validationMsg + '\n\n' + setting.setting.getTooltip())
97                         else:
98                                 self.popup.text.SetLabel(setting.setting.getTooltip())
99                         self.popup.text.Wrap(350)
100                         self.popup.Fit()
101                         x, y = setting.ctrl.ClientToScreenXY(0, 0)
102                         sx, sy = setting.ctrl.GetSizeTuple()
103                         #if platform.system() == "Windows":
104                         #       for some reason, under windows, the popup is relative to the main window... in some cases. (Wierd ass bug)
105                         #       wx, wy = self.ClientToScreenXY(0, 0)
106                         #       x -= wx
107                         #       y -= wy
108                         self.popup.SetPosition((x, y+sy))
109         
110         def updateProfileToControls(self):
111                 "Update the configuration wx controls to show the new configuration settings"
112                 for setting in self.settingControlList:
113                         setting.SetValue(setting.setting.getValue())
114                 self.Update()
115
116         def _validate(self):
117                 for setting in self.settingControlList:
118                         setting._validate()
119                 if self._callback is not None:
120                         self._callback()
121
122         def getLabelColumnWidth(self, panel):
123                 maxWidth = 0
124                 for child in panel.GetChildren():
125                         if isinstance(child, wx.lib.stattext.GenStaticText):
126                                 maxWidth = max(maxWidth, child.GetSize()[0])
127                 return maxWidth
128         
129         def setLabelColumnWidth(self, panel, width):
130                 for child in panel.GetChildren():
131                         if isinstance(child, wx.lib.stattext.GenStaticText):
132                                 size = child.GetSize()
133                                 size[0] = width
134                                 child.SetBestSize(size)
135         
136 class TitleRow(object):
137         def __init__(self, panel, name):
138                 "Add a title row to the configuration panel"
139                 sizer = panel.GetSizer()
140                 x = sizer.GetRows()
141                 self.title = wx.StaticText(panel, -1, name.replace('&', '&&'))
142                 self.title.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
143                 sizer.Add(self.title, (x,0), (1,3), flag=wx.EXPAND|wx.TOP|wx.LEFT, border=10)
144                 sizer.Add(wx.StaticLine(panel), (x+1,0), (1,3), flag=wx.EXPAND|wx.LEFT,border=10)
145                 sizer.SetRows(x + 2)
146
147 class SettingRow(object):
148         def __init__(self, panel, configName, valueOverride = None, index = None):
149                 "Add a setting to the configuration panel"
150                 sizer = panel.GetSizer()
151                 x = sizer.GetRows()
152                 y = 0
153                 flag = 0
154
155                 self.setting = profile.settingsDictionary[configName]
156                 self.settingIndex = index
157                 self.validationMsg = ''
158                 self.panel = panel
159
160                 self.label = wx.lib.stattext.GenStaticText(panel, -1, self.setting.getLabel())
161                 self.label.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
162                 self.label.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
163
164                 #if self.setting.getType() is types.FloatType and False:
165                 #       digits = 0
166                 #       while 1 / pow(10, digits) > defaultValue:
167                 #               digits += 1
168                 #       self.ctrl = floatspin.FloatSpin(panel, -1, value=float(getSettingFunc(configName)), increment=defaultValue, digits=digits, min_val=0.0)
169                 #       self.ctrl.Bind(floatspin.EVT_FLOATSPIN, self.OnSettingChange)
170                 #       flag = wx.EXPAND
171                 if self.setting.getType() is types.BooleanType:
172                         self.ctrl = wx.CheckBox(panel, -1, style=wx.ALIGN_RIGHT)
173                         self.SetValue(self.setting.getValue(self.settingIndex))
174                         self.ctrl.Bind(wx.EVT_CHECKBOX, self.OnSettingChange)
175                 elif valueOverride is not None and valueOverride is wx.Colour:
176                         self.ctrl = wx.ColourPickerCtrl(panel, -1)
177                         self.SetValue(self.setting.getValue(self.settingIndex))
178                         self.ctrl.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnSettingChange)
179                 elif type(self.setting.getType()) is list or valueOverride is not None:
180                         value = self.setting.getValue(self.settingIndex)
181                         choices = self.setting.getType()
182                         if valueOverride is not None:
183                                 choices = valueOverride
184                         self._englishChoices = choices[:]
185                         if value not in choices and len(choices) > 0:
186                                 value = choices[0]
187                         for n in xrange(0, len(choices)):
188                                 choices[n] = _(choices[n])
189                         value = _(value)
190                         self.ctrl = wx.ComboBox(panel, -1, value, choices=choices, style=wx.CB_DROPDOWN|wx.CB_READONLY)
191                         self.ctrl.Bind(wx.EVT_COMBOBOX, self.OnSettingChange)
192                         self.ctrl.Bind(wx.EVT_LEFT_DOWN, self.OnMouseExit)
193                         flag = wx.EXPAND
194                 else:
195                         self.ctrl = wx.TextCtrl(panel, -1, self.setting.getValue(self.settingIndex))
196                         self.ctrl.Bind(wx.EVT_TEXT, self.OnSettingChange)
197                         flag = wx.EXPAND
198
199                 sizer.Add(self.label, (x,y), flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT,border=10)
200                 sizer.Add(self.ctrl, (x,y+1), flag=wx.ALIGN_BOTTOM|flag)
201                 sizer.SetRows(x+1)
202
203                 self.ctrl.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
204                 self.ctrl.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
205                 if isinstance(self.ctrl, floatspin.FloatSpin):
206                         self.ctrl.GetTextCtrl().Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
207                         self.ctrl.GetTextCtrl().Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
208                         self.defaultBGColour = self.ctrl.GetTextCtrl().GetBackgroundColour()
209                 else:
210                         self.defaultBGColour = self.ctrl.GetBackgroundColour()
211                 
212                 panel.main.settingControlList.append(self)
213
214         def OnMouseEnter(self, e):
215                 self.panel.main.OnPopupDisplay(self)
216
217         def OnMouseExit(self, e):
218                 self.panel.main.OnPopupHide(self)
219                 e.Skip()
220
221         def OnSettingChange(self, e):
222                 self.setting.setValue(self.GetValue(), self.settingIndex)
223                 self.panel.main._validate()
224
225         def _validate(self):
226                 result, msg = self.setting.validate()
227
228                 ctrl = self.ctrl
229                 if isinstance(ctrl, floatspin.FloatSpin):
230                         ctrl = ctrl.GetTextCtrl()
231                 if result == validators.ERROR:
232                         ctrl.SetBackgroundColour('Red')
233                 elif result == validators.WARNING:
234                         ctrl.SetBackgroundColour('Yellow')
235                 else:
236                         ctrl.SetBackgroundColour(self.defaultBGColour)
237                 ctrl.Refresh()
238
239                 self.validationMsg = msg
240                 self.panel.main.UpdatePopup(self)
241
242         def GetValue(self):
243                 if isinstance(self.ctrl, wx.ColourPickerCtrl):
244                         return str(self.ctrl.GetColour().GetAsString(wx.C2S_HTML_SYNTAX))
245                 elif isinstance(self.ctrl, wx.ComboBox):
246                         value = str(self.ctrl.GetValue())
247                         for ret in self._englishChoices:
248                                 if _(ret) == value:
249                                         return ret
250                         return value
251                 else:
252                         return str(self.ctrl.GetValue())
253
254         def SetValue(self, value):
255                 if isinstance(self.ctrl, wx.CheckBox):
256                         self.ctrl.SetValue(str(value) == "True")
257                 elif isinstance(self.ctrl, wx.ColourPickerCtrl):
258                         self.ctrl.SetColour(value)
259                 elif isinstance(self.ctrl, floatspin.FloatSpin):
260                         try:
261                                 self.ctrl.SetValue(float(value))
262                         except ValueError:
263                                 pass
264                 elif isinstance(self.ctrl, wx.ComboBox):
265                         self.ctrl.SetValue(_(value))
266                 else:
267                         self.ctrl.SetValue(value)