1 from __future__ import absolute_import
2 from __future__ import division
5 import wx, wx.lib.stattext, types
7 from Cura.util import validators
8 from Cura.util import profile
10 class configPanelBase(wx.Panel):
11 "A base class for configuration dialogs. Handles creation of settings, and popups"
12 def __init__(self, parent):
13 super(configPanelBase, self).__init__(parent)
15 self.settingControlList = []
17 #Create the popup window
18 self.popup = wx.PopupWindow(self, flags=wx.BORDER_SIMPLE)
19 self.popup.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOBK))
20 self.popup.setting = None
21 self.popup.text = wx.StaticText(self.popup, -1, '');
22 self.popup.sizer = wx.BoxSizer()
23 self.popup.sizer.Add(self.popup.text, flag=wx.EXPAND|wx.ALL, border=1)
24 self.popup.SetSizer(self.popup.sizer)
26 def CreateConfigTab(self, nb, name):
27 leftConfigPanel, rightConfigPanel, configPanel = self.CreateConfigPanel(nb)
28 nb.AddPage(configPanel, name)
29 return leftConfigPanel, rightConfigPanel
31 def CreateConfigPanel(self, parent):
32 configPanel = wx.Panel(parent);
33 leftConfigPanel = wx.Panel(configPanel)
34 rightConfigPanel = wx.Panel(configPanel)
36 sizer = wx.GridBagSizer(2, 2)
37 leftConfigPanel.SetSizer(sizer)
38 sizer = wx.GridBagSizer(2, 2)
39 rightConfigPanel.SetSizer(sizer)
41 sizer = wx.BoxSizer(wx.HORIZONTAL)
42 configPanel.SetSizer(sizer)
43 sizer.Add(leftConfigPanel, border=35, flag=wx.RIGHT)
44 sizer.Add(rightConfigPanel)
45 leftConfigPanel.main = self
46 rightConfigPanel.main = self
47 return leftConfigPanel, rightConfigPanel, configPanel
49 def CreateDynamicConfigTab(self, nb, name):
50 configPanel = wx.lib.scrolledpanel.ScrolledPanel(nb)
51 #configPanel = wx.Panel(nb);
52 leftConfigPanel = wx.Panel(configPanel)
53 rightConfigPanel = wx.Panel(configPanel)
55 sizer = wx.GridBagSizer(2, 2)
56 leftConfigPanel.SetSizer(sizer)
57 sizer.AddGrowableCol(1)
59 sizer = wx.GridBagSizer(2, 2)
60 rightConfigPanel.SetSizer(sizer)
61 sizer.AddGrowableCol(1)
63 sizer = wx.BoxSizer(wx.HORIZONTAL)
64 sizer.Add(leftConfigPanel, proportion=1, border=35, flag=wx.EXPAND)
65 sizer.Add(rightConfigPanel, proportion=1, flag=wx.EXPAND)
66 configPanel.SetSizer(sizer)
68 configPanel.SetAutoLayout(1)
69 configPanel.SetupScrolling(scroll_x=False, scroll_y=True)
71 leftConfigPanel.main = self
72 rightConfigPanel.main = self
74 configPanel.leftPanel = leftConfigPanel
75 configPanel.rightPanel = rightConfigPanel
77 nb.AddPage(configPanel, name)
79 return leftConfigPanel, rightConfigPanel, configPanel
81 def OnPopupDisplay(self, setting):
82 self.popup.setting = setting
83 self.UpdatePopup(setting)
86 def OnPopupHide(self, e):
87 self.popup.Show(False)
89 def UpdatePopup(self, setting):
90 if self.popup.setting == setting:
91 if setting.validationMsg != '':
92 self.popup.text.SetLabel(setting.validationMsg + '\n\n' + setting.helpText)
94 self.popup.text.SetLabel(setting.helpText)
95 self.popup.text.Wrap(350)
97 x, y = setting.ctrl.ClientToScreenXY(0, 0)
98 sx, sy = setting.ctrl.GetSizeTuple()
99 #if platform.system() == "Windows":
100 # for some reason, under windows, the popup is relative to the main window... in some cases. (Wierd ass bug)
101 # wx, wy = self.ClientToScreenXY(0, 0)
104 self.popup.SetPosition((x, y+sy))
106 def updateProfileToControls(self):
107 "Update the configuration wx controls to show the new configuration settings"
108 for setting in self.settingControlList:
109 if setting.type == 'profile':
110 setting.SetValue(profile.getProfileSetting(setting.configName))
112 setting.SetValue(profile.getPreference(setting.configName))
115 def getLabelColumnWidth(self, panel):
117 for child in panel.GetChildren():
118 if isinstance(child, wx.lib.stattext.GenStaticText):
119 maxWidth = max(maxWidth, child.GetSize()[0])
122 def setLabelColumnWidth(self, panel, width):
123 for child in panel.GetChildren():
124 if isinstance(child, wx.lib.stattext.GenStaticText):
125 size = child.GetSize()
127 child.SetBestSize(size)
130 def __init__(self, panel, name):
131 "Add a title row to the configuration panel"
132 sizer = panel.GetSizer()
134 self.title = wx.StaticText(panel, -1, name)
135 self.title.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
136 sizer.Add(self.title, (x,0), (1,3), flag=wx.EXPAND|wx.TOP|wx.LEFT, border=10)
137 sizer.Add(wx.StaticLine(panel), (x+1,0), (1,3), flag=wx.EXPAND|wx.LEFT,border=10)
141 def __init__(self, panel, label, configName, defaultValue = '', helpText = 'Help: TODO', type = 'profile'):
142 "Add a setting to the configuration panel"
143 sizer = panel.GetSizer()
149 self.validationMsg = ''
150 self.helpText = helpText
151 self.configName = configName
155 self.label = wx.lib.stattext.GenStaticText(panel, -1, label)
156 self.label.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
157 self.label.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
159 getSettingFunc = profile.getPreference
160 if self.type == 'profile':
161 getSettingFunc = profile.getProfileSetting
162 if isinstance(defaultValue, types.StringTypes):
163 self.ctrl = wx.TextCtrl(panel, -1, getSettingFunc(configName))
164 self.ctrl.Bind(wx.EVT_TEXT, self.OnSettingChange)
166 elif isinstance(defaultValue, types.BooleanType):
167 self.ctrl = wx.CheckBox(panel, -1, style=wx.ALIGN_RIGHT)
168 self.SetValue(getSettingFunc(configName))
169 self.ctrl.Bind(wx.EVT_CHECKBOX, self.OnSettingChange)
170 elif isinstance(defaultValue, wx.Colour):
171 self.ctrl = wx.ColourPickerCtrl(panel, -1)
172 self.SetValue(getSettingFunc(configName))
173 self.ctrl.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnSettingChange)
175 self.ctrl = wx.ComboBox(panel, -1, getSettingFunc(configName), choices=defaultValue, style=wx.CB_DROPDOWN|wx.CB_READONLY)
176 self.ctrl.Bind(wx.EVT_COMBOBOX, self.OnSettingChange)
177 self.ctrl.Bind(wx.EVT_LEFT_DOWN, self.OnMouseExit)
180 # Set the minimum size of control to something other than the humungous default
181 minSize = self.ctrl.GetMinSize()
183 ##if platform.system() == "Darwin":
184 ## # Under MacOS, it appears that the minSize is used for the actual size, so give the field a bit more room...
188 ##self.ctrl.SetMinSize(minSize)
190 sizer.Add(self.label, (x,y), flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT,border=10)
191 sizer.Add(self.ctrl, (x,y+1), flag=wx.ALIGN_BOTTOM|flag)
194 self.ctrl.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
195 self.ctrl.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
197 self.defaultBGColour = self.ctrl.GetBackgroundColour()
199 panel.main.settingControlList.append(self)
201 def OnMouseEnter(self, e):
202 self.panel.main.OnPopupDisplay(self)
204 def OnMouseExit(self, e):
205 self.panel.main.OnPopupHide(self)
208 def OnSettingChange(self, e):
209 if self.type == 'profile':
210 profile.putProfileSetting(self.configName, self.GetValue())
212 profile.putPreference(self.configName, self.GetValue())
213 result = validators.SUCCESS
215 for validator in self.validators:
216 res, err = validator.validate()
217 if res == validators.ERROR:
219 elif res == validators.WARNING and result != validators.ERROR:
221 if res != validators.SUCCESS:
223 if result == validators.ERROR:
224 self.ctrl.SetBackgroundColour('Red')
225 elif result == validators.WARNING:
226 self.ctrl.SetBackgroundColour('Yellow')
228 self.ctrl.SetBackgroundColour(self.defaultBGColour)
231 self.validationMsg = '\n'.join(msgs)
232 self.panel.main.UpdatePopup(self)
235 if isinstance(self.ctrl, wx.ColourPickerCtrl):
236 return str(self.ctrl.GetColour().GetAsString(wx.C2S_HTML_SYNTAX))
238 return str(self.ctrl.GetValue())
240 def SetValue(self, value):
241 if isinstance(self.ctrl, wx.CheckBox):
242 self.ctrl.SetValue(str(value) == "True")
243 elif isinstance(self.ctrl, wx.ColourPickerCtrl):
244 self.ctrl.SetColour(value)
246 self.ctrl.SetValue(value)
248 #Settings notify works as a validator, but instead of validating anything, it calls another function, which can use the value.
249 # A bit hacky, bit it works.
250 class settingNotify():
251 def __init__(self, setting, func):
252 self.setting = setting
253 self.setting.validators.append(self)
258 return validators.SUCCESS, ''