1 from __future__ import absolute_import
2 from __future__ import division
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):
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.sizer = wx.BoxSizer()
24 self.popup.sizer.Add(self.popup.text, flag=wx.EXPAND|wx.ALL, border=1)
25 self.popup.SetSizer(self.popup.sizer)
27 def CreateConfigTab(self, nb, name):
28 leftConfigPanel, rightConfigPanel, configPanel = self.CreateConfigPanel(nb)
29 nb.AddPage(configPanel, name)
30 return leftConfigPanel, rightConfigPanel
32 def CreateConfigPanel(self, parent):
33 configPanel = wx.Panel(parent);
34 leftConfigPanel = wx.Panel(configPanel)
35 rightConfigPanel = wx.Panel(configPanel)
37 sizer = wx.GridBagSizer(2, 2)
38 leftConfigPanel.SetSizer(sizer)
39 sizer = wx.GridBagSizer(2, 2)
40 rightConfigPanel.SetSizer(sizer)
42 sizer = wx.BoxSizer(wx.HORIZONTAL)
43 configPanel.SetSizer(sizer)
44 sizer.Add(leftConfigPanel, border=35, flag=wx.RIGHT)
45 sizer.Add(rightConfigPanel)
46 leftConfigPanel.main = self
47 rightConfigPanel.main = self
48 return leftConfigPanel, rightConfigPanel, configPanel
50 def CreateDynamicConfigTab(self, nb, name):
51 configPanel = wx.lib.scrolledpanel.ScrolledPanel(nb)
52 #configPanel = wx.Panel(nb);
53 leftConfigPanel = wx.Panel(configPanel)
54 rightConfigPanel = wx.Panel(configPanel)
56 sizer = wx.GridBagSizer(2, 2)
57 leftConfigPanel.SetSizer(sizer)
58 sizer.AddGrowableCol(1)
60 sizer = wx.GridBagSizer(2, 2)
61 rightConfigPanel.SetSizer(sizer)
62 sizer.AddGrowableCol(1)
64 sizer = wx.BoxSizer(wx.HORIZONTAL)
65 sizer.Add(leftConfigPanel, proportion=1, border=35, flag=wx.EXPAND)
66 sizer.Add(rightConfigPanel, proportion=1, flag=wx.EXPAND)
67 configPanel.SetSizer(sizer)
69 configPanel.SetAutoLayout(1)
70 configPanel.SetupScrolling(scroll_x=False, scroll_y=True)
72 leftConfigPanel.main = self
73 rightConfigPanel.main = self
75 configPanel.leftPanel = leftConfigPanel
76 configPanel.rightPanel = rightConfigPanel
78 nb.AddPage(configPanel, name)
80 return leftConfigPanel, rightConfigPanel, configPanel
82 def OnPopupDisplay(self, setting):
83 self.popup.setting = setting
84 self.UpdatePopup(setting)
87 def OnPopupHide(self, e):
88 self.popup.Show(False)
90 def UpdatePopup(self, setting):
91 if self.popup.setting == setting:
92 if setting.validationMsg != '':
93 self.popup.text.SetLabel(setting.validationMsg + '\n\n' + setting.helpText)
95 self.popup.text.SetLabel(setting.helpText)
96 self.popup.text.Wrap(350)
98 x, y = setting.ctrl.ClientToScreenXY(0, 0)
99 sx, sy = setting.ctrl.GetSizeTuple()
100 #if platform.system() == "Windows":
101 # for some reason, under windows, the popup is relative to the main window... in some cases. (Wierd ass bug)
102 # wx, wy = self.ClientToScreenXY(0, 0)
105 self.popup.SetPosition((x, y+sy))
107 def updateProfileToControls(self):
108 "Update the configuration wx controls to show the new configuration settings"
109 for setting in self.settingControlList:
110 if setting.type == 'profile':
111 setting.SetValue(profile.getProfileSetting(setting.configName))
113 setting.SetValue(profile.getPreference(setting.configName))
116 def getLabelColumnWidth(self, panel):
118 for child in panel.GetChildren():
119 if isinstance(child, wx.lib.stattext.GenStaticText):
120 maxWidth = max(maxWidth, child.GetSize()[0])
123 def setLabelColumnWidth(self, panel, width):
124 for child in panel.GetChildren():
125 if isinstance(child, wx.lib.stattext.GenStaticText):
126 size = child.GetSize()
128 child.SetBestSize(size)
131 def __init__(self, panel, name):
132 "Add a title row to the configuration panel"
133 sizer = panel.GetSizer()
135 self.title = wx.StaticText(panel, -1, name)
136 self.title.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
137 sizer.Add(self.title, (x,0), (1,3), flag=wx.EXPAND|wx.TOP|wx.LEFT, border=10)
138 sizer.Add(wx.StaticLine(panel), (x+1,0), (1,3), flag=wx.EXPAND|wx.LEFT,border=10)
142 def __init__(self, panel, label, configName, defaultValue = '', helpText = 'Help: TODO', type = 'profile'):
143 "Add a setting to the configuration panel"
144 sizer = panel.GetSizer()
150 self.validationMsg = ''
151 self.helpText = helpText
152 self.configName = configName
156 self.label = wx.lib.stattext.GenStaticText(panel, -1, label)
157 self.label.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
158 self.label.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
160 getSettingFunc = profile.getPreference
161 if self.type == 'profile':
162 getSettingFunc = profile.getProfileSetting
163 if isinstance(defaultValue, types.StringTypes):
164 self.ctrl = wx.TextCtrl(panel, -1, getSettingFunc(configName))
165 self.ctrl.Bind(wx.EVT_TEXT, self.OnSettingChange)
167 elif isinstance(defaultValue, types.FloatType):
169 while 1 / pow(10, digits) > defaultValue:
171 self.ctrl = floatspin.FloatSpin(panel, -1, value=float(getSettingFunc(configName)), increment=defaultValue, digits=digits, min_val=0.0)
172 self.ctrl.Bind(floatspin.EVT_FLOATSPIN, self.OnSettingChange)
174 elif isinstance(defaultValue, types.BooleanType):
175 self.ctrl = wx.CheckBox(panel, -1, style=wx.ALIGN_RIGHT)
176 self.SetValue(getSettingFunc(configName))
177 self.ctrl.Bind(wx.EVT_CHECKBOX, self.OnSettingChange)
178 elif isinstance(defaultValue, wx.Colour):
179 self.ctrl = wx.ColourPickerCtrl(panel, -1)
180 self.SetValue(getSettingFunc(configName))
181 self.ctrl.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnSettingChange)
183 self.ctrl = wx.ComboBox(panel, -1, getSettingFunc(configName), choices=defaultValue, style=wx.CB_DROPDOWN|wx.CB_READONLY)
184 self.ctrl.Bind(wx.EVT_COMBOBOX, self.OnSettingChange)
185 self.ctrl.Bind(wx.EVT_LEFT_DOWN, self.OnMouseExit)
188 # Set the minimum size of control to something other than the humungous default
189 minSize = self.ctrl.GetMinSize()
191 ##if platform.system() == "Darwin":
192 ## # Under MacOS, it appears that the minSize is used for the actual size, so give the field a bit more room...
196 ##self.ctrl.SetMinSize(minSize)
198 sizer.Add(self.label, (x,y), flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT,border=10)
199 sizer.Add(self.ctrl, (x,y+1), flag=wx.ALIGN_BOTTOM|flag)
202 self.ctrl.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
203 self.ctrl.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
204 if isinstance(self.ctrl, floatspin.FloatSpin):
205 self.ctrl.GetTextCtrl().Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
206 self.ctrl.GetTextCtrl().Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
207 self.defaultBGColour = self.ctrl.GetTextCtrl().GetBackgroundColour()
209 self.defaultBGColour = self.ctrl.GetBackgroundColour()
211 panel.main.settingControlList.append(self)
213 def OnMouseEnter(self, e):
214 self.panel.main.OnPopupDisplay(self)
216 def OnMouseExit(self, e):
217 self.panel.main.OnPopupHide(self)
220 def OnSettingChange(self, e):
221 if self.type == 'profile':
222 profile.putProfileSetting(self.configName, self.GetValue())
224 profile.putPreference(self.configName, self.GetValue())
225 result = validators.SUCCESS
227 for validator in self.validators:
228 res, err = validator.validate()
229 if res == validators.ERROR:
231 elif res == validators.WARNING and result != validators.ERROR:
233 if res != validators.SUCCESS:
236 if isinstance(ctrl, floatspin.FloatSpin):
237 ctrl = ctrl.GetTextCtrl()
238 if result == validators.ERROR:
239 ctrl.SetBackgroundColour('Red')
240 elif result == validators.WARNING:
241 ctrl.SetBackgroundColour('Yellow')
243 ctrl.SetBackgroundColour(self.defaultBGColour)
246 self.validationMsg = '\n'.join(msgs)
247 self.panel.main.UpdatePopup(self)
250 if isinstance(self.ctrl, wx.ColourPickerCtrl):
251 return str(self.ctrl.GetColour().GetAsString(wx.C2S_HTML_SYNTAX))
253 return str(self.ctrl.GetValue())
255 def SetValue(self, value):
256 if isinstance(self.ctrl, wx.CheckBox):
257 self.ctrl.SetValue(str(value) == "True")
258 elif isinstance(self.ctrl, wx.ColourPickerCtrl):
259 self.ctrl.SetColour(value)
260 elif isinstance(self.ctrl, floatspin.FloatSpin):
262 self.ctrl.SetValue(float(value))
266 self.ctrl.SetValue(value)
268 #Settings notify works as a validator, but instead of validating anything, it calls another function, which can use the value.
269 # A bit hacky, bit it works.
270 class settingNotify():
271 def __init__(self, setting, func):
272 self.setting = setting
273 self.setting.validators.append(self)
278 return validators.SUCCESS, ''