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"
5 import wx, wx.lib.stattext, types
6 from wx.lib.agw import floatspin
8 from Cura.util import validators
9 from Cura.util import profile
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 #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)
28 self._callback = changeCallback
30 def CreateConfigTab(self, nb, name):
31 leftConfigPanel, rightConfigPanel, configPanel = self.CreateConfigPanel(nb)
32 nb.AddPage(configPanel, name)
33 return leftConfigPanel, rightConfigPanel
35 def CreateConfigPanel(self, parent):
36 configPanel = wx.Panel(parent);
37 leftConfigPanel = wx.Panel(configPanel)
38 rightConfigPanel = wx.Panel(configPanel)
40 sizer = wx.GridBagSizer(2, 2)
41 leftConfigPanel.SetSizer(sizer)
42 sizer = wx.GridBagSizer(2, 2)
43 rightConfigPanel.SetSizer(sizer)
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
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)
59 sizer = wx.GridBagSizer(2, 2)
60 leftConfigPanel.SetSizer(sizer)
61 #sizer.AddGrowableCol(1)
63 sizer = wx.GridBagSizer(2, 2)
64 rightConfigPanel.SetSizer(sizer)
65 #sizer.AddGrowableCol(1)
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)
72 configPanel.SetAutoLayout(1)
73 configPanel.SetupScrolling(scroll_x=False, scroll_y=True)
75 leftConfigPanel.main = self
76 rightConfigPanel.main = self
78 configPanel.leftPanel = leftConfigPanel
79 configPanel.rightPanel = rightConfigPanel
81 nb.AddPage(configPanel, name)
83 return leftConfigPanel, rightConfigPanel, configPanel
85 def OnPopupDisplay(self, setting):
86 self.popup.setting = setting
87 self.UpdatePopup(setting)
90 def OnPopupHide(self, e):
91 self.popup.Show(False)
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())
98 self.popup.text.SetLabel(setting.setting.getTooltip())
99 self.popup.text.Wrap(350)
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)
108 self.popup.SetPosition((x, y+sy))
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())
117 for setting in self.settingControlList:
119 if self._callback is not None:
122 def getLabelColumnWidth(self, panel):
124 for child in panel.GetChildren():
125 if isinstance(child, wx.lib.stattext.GenStaticText):
126 maxWidth = max(maxWidth, child.GetSize()[0])
129 def setLabelColumnWidth(self, panel, width):
130 for child in panel.GetChildren():
131 if isinstance(child, wx.lib.stattext.GenStaticText):
132 size = child.GetSize()
134 child.SetBestSize(size)
136 class TitleRow(object):
137 def __init__(self, panel, name):
138 "Add a title row to the configuration panel"
139 sizer = panel.GetSizer()
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)
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()
155 self.setting = profile.settingsDictionary[configName]
156 self.settingIndex = index
157 self.validationMsg = ''
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)
164 #if self.setting.getType() is types.FloatType and False:
166 # while 1 / pow(10, digits) > defaultValue:
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)
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:
187 for n in xrange(0, len(choices)):
188 choices[n] = _(choices[n])
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)
195 self.ctrl = wx.TextCtrl(panel, -1, self.setting.getValue(self.settingIndex))
196 self.ctrl.Bind(wx.EVT_TEXT, self.OnSettingChange)
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)
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()
210 self.defaultBGColour = self.ctrl.GetBackgroundColour()
212 panel.main.settingControlList.append(self)
214 def OnMouseEnter(self, e):
215 self.panel.main.OnPopupDisplay(self)
217 def OnMouseExit(self, e):
218 self.panel.main.OnPopupHide(self)
221 def OnSettingChange(self, e):
222 self.setting.setValue(self.GetValue(), self.settingIndex)
223 self.panel.main._validate()
226 result, msg = self.setting.validate()
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')
236 ctrl.SetBackgroundColour(self.defaultBGColour)
239 self.validationMsg = msg
240 self.panel.main.UpdatePopup(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:
252 return str(self.ctrl.GetValue())
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):
261 self.ctrl.SetValue(float(value))
264 elif isinstance(self.ctrl, wx.ComboBox):
265 self.ctrl.SetValue(_(value))
267 self.ctrl.SetValue(value)