1 from __future__ import absolute_import
4 import wx, wx.lib.stattext, types
6 from Cura.util import validators
7 from Cura.util import profile
9 class configPanelBase(wx.Panel):
10 "A base class for configuration dialogs. Handles creation of settings, and popups"
11 def __init__(self, parent):
12 super(configPanelBase, self).__init__(parent)
14 self.settingControlList = []
16 #Create the popup window
17 self.popup = wx.PopupWindow(self, flags=wx.BORDER_SIMPLE)
18 self.popup.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOBK))
19 self.popup.setting = None
20 self.popup.text = wx.StaticText(self.popup, -1, '');
21 self.popup.sizer = wx.BoxSizer()
22 self.popup.sizer.Add(self.popup.text, flag=wx.EXPAND|wx.ALL, border=1)
23 self.popup.SetSizer(self.popup.sizer)
25 def CreateConfigTab(self, nb, name):
26 leftConfigPanel, rightConfigPanel, configPanel = self.CreateConfigPanel(nb)
27 nb.AddPage(configPanel, name)
28 return leftConfigPanel, rightConfigPanel
30 def CreateConfigPanel(self, parent):
31 configPanel = wx.Panel(parent);
32 leftConfigPanel = wx.Panel(configPanel)
33 rightConfigPanel = wx.Panel(configPanel)
35 sizer = wx.GridBagSizer(2, 2)
36 leftConfigPanel.SetSizer(sizer)
37 sizer = wx.GridBagSizer(2, 2)
38 rightConfigPanel.SetSizer(sizer)
40 sizer = wx.BoxSizer(wx.HORIZONTAL)
41 configPanel.SetSizer(sizer)
42 sizer.Add(leftConfigPanel, border=35, flag=wx.RIGHT)
43 sizer.Add(rightConfigPanel)
44 leftConfigPanel.main = self
45 rightConfigPanel.main = self
46 return leftConfigPanel, rightConfigPanel, configPanel
48 def CreateDynamicConfigTab(self, nb, name):
49 configPanel = wx.lib.scrolledpanel.ScrolledPanel(nb)
50 #configPanel = wx.Panel(nb);
51 leftConfigPanel = wx.Panel(configPanel)
52 rightConfigPanel = wx.Panel(configPanel)
54 sizer = wx.GridBagSizer(2, 2)
55 leftConfigPanel.SetSizer(sizer)
56 sizer.AddGrowableCol(1)
58 sizer = wx.GridBagSizer(2, 2)
59 rightConfigPanel.SetSizer(sizer)
60 sizer.AddGrowableCol(1)
62 sizer = wx.BoxSizer(wx.HORIZONTAL)
63 sizer.Add(leftConfigPanel, proportion=1, border=35, flag=wx.EXPAND)
64 sizer.Add(rightConfigPanel, proportion=1, flag=wx.EXPAND)
65 configPanel.SetSizer(sizer)
67 configPanel.SetAutoLayout(1)
68 configPanel.SetupScrolling(scroll_x=False, scroll_y=True)
70 leftConfigPanel.main = self
71 rightConfigPanel.main = self
73 configPanel.leftPanel = leftConfigPanel
74 configPanel.rightPanel = rightConfigPanel
76 nb.AddPage(configPanel, name)
78 return leftConfigPanel, rightConfigPanel, configPanel
80 def OnPopupDisplay(self, setting):
81 self.popup.setting = setting
82 self.UpdatePopup(setting)
85 def OnPopupHide(self, e):
86 self.popup.Show(False)
88 def UpdatePopup(self, setting):
89 if self.popup.setting == setting:
90 if setting.validationMsg != '':
91 self.popup.text.SetLabel(setting.validationMsg + '\n\n' + setting.helpText)
93 self.popup.text.SetLabel(setting.helpText)
94 self.popup.text.Wrap(350)
96 x, y = setting.ctrl.ClientToScreenXY(0, 0)
97 sx, sy = setting.ctrl.GetSizeTuple()
98 #if platform.system() == "Windows":
99 # for some reason, under windows, the popup is relative to the main window... in some cases. (Wierd ass bug)
100 # wx, wy = self.ClientToScreenXY(0, 0)
103 self.popup.SetPosition((x, y+sy))
105 def updateProfileToControls(self):
106 "Update the configuration wx controls to show the new configuration settings"
107 for setting in self.settingControlList:
108 if setting.type == 'profile':
109 setting.SetValue(profile.getProfileSetting(setting.configName))
111 setting.SetValue(profile.getPreference(setting.configName))
114 def getLabelColumnWidth(self, panel):
116 for child in panel.GetChildren():
117 if isinstance(child, wx.lib.stattext.GenStaticText):
118 maxWidth = max(maxWidth, child.GetSize()[0])
121 def setLabelColumnWidth(self, panel, width):
122 for child in panel.GetChildren():
123 if isinstance(child, wx.lib.stattext.GenStaticText):
124 size = child.GetSize()
126 child.SetBestSize(size)
129 def __init__(self, panel, name):
130 "Add a title row to the configuration panel"
131 sizer = panel.GetSizer()
133 self.title = wx.StaticText(panel, -1, name)
134 self.title.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
135 sizer.Add(self.title, (x,0), (1,3), flag=wx.EXPAND|wx.TOP|wx.LEFT, border=10)
136 sizer.Add(wx.StaticLine(panel), (x+1,0), (1,3), flag=wx.EXPAND|wx.LEFT,border=10)
140 def __init__(self, panel, label, configName, defaultValue = '', helpText = 'Help: TODO', type = 'profile'):
141 "Add a setting to the configuration panel"
142 sizer = panel.GetSizer()
148 self.validationMsg = ''
149 self.helpText = helpText
150 self.configName = configName
154 self.label = wx.lib.stattext.GenStaticText(panel, -1, label)
155 self.label.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
156 self.label.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
158 getSettingFunc = profile.getPreference
159 if self.type == 'profile':
160 getSettingFunc = profile.getProfileSetting
161 if isinstance(defaultValue, types.StringTypes):
162 self.ctrl = wx.TextCtrl(panel, -1, getSettingFunc(configName))
163 self.ctrl.Bind(wx.EVT_TEXT, self.OnSettingChange)
165 elif isinstance(defaultValue, types.BooleanType):
166 self.ctrl = wx.CheckBox(panel, -1, style=wx.ALIGN_RIGHT)
167 self.SetValue(getSettingFunc(configName))
168 self.ctrl.Bind(wx.EVT_CHECKBOX, self.OnSettingChange)
169 elif isinstance(defaultValue, wx.Colour):
170 self.ctrl = wx.ColourPickerCtrl(panel, -1)
171 self.SetValue(getSettingFunc(configName))
172 self.ctrl.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnSettingChange)
174 self.ctrl = wx.ComboBox(panel, -1, getSettingFunc(configName), choices=defaultValue, style=wx.CB_DROPDOWN|wx.CB_READONLY)
175 self.ctrl.Bind(wx.EVT_COMBOBOX, self.OnSettingChange)
176 self.ctrl.Bind(wx.EVT_LEFT_DOWN, self.OnMouseExit)
179 # Set the minimum size of control to something other than the humungous default
180 minSize = self.ctrl.GetMinSize()
182 if platform.system() == "Darwin":
183 # Under MacOS, it appears that the minSize is used for the actual size...
187 self.ctrl.SetMinSize(minSize)
189 sizer.Add(self.label, (x,y), flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT,border=10)
190 sizer.Add(self.ctrl, (x,y+1), flag=wx.ALIGN_BOTTOM|flag)
193 self.ctrl.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
194 self.ctrl.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
196 self.defaultBGColour = self.ctrl.GetBackgroundColour()
198 panel.main.settingControlList.append(self)
200 def OnMouseEnter(self, e):
201 self.panel.main.OnPopupDisplay(self)
203 def OnMouseExit(self, e):
204 self.panel.main.OnPopupHide(self)
207 def OnSettingChange(self, e):
208 if self.type == 'profile':
209 profile.putProfileSetting(self.configName, self.GetValue())
211 profile.putPreference(self.configName, self.GetValue())
212 result = validators.SUCCESS
214 for validator in self.validators:
215 res, err = validator.validate()
216 if res == validators.ERROR:
218 elif res == validators.WARNING and result != validators.ERROR:
220 if res != validators.SUCCESS:
222 if result == validators.ERROR:
223 self.ctrl.SetBackgroundColour('Red')
224 elif result == validators.WARNING:
225 self.ctrl.SetBackgroundColour('Yellow')
227 self.ctrl.SetBackgroundColour(self.defaultBGColour)
230 self.validationMsg = '\n'.join(msgs)
231 self.panel.main.UpdatePopup(self)
234 if isinstance(self.ctrl, wx.ColourPickerCtrl):
235 return str(self.ctrl.GetColour().GetAsString(wx.C2S_HTML_SYNTAX))
237 return str(self.ctrl.GetValue())
239 def SetValue(self, value):
240 if isinstance(self.ctrl, wx.CheckBox):
241 self.ctrl.SetValue(str(value) == "True")
242 elif isinstance(self.ctrl, wx.ColourPickerCtrl):
243 self.ctrl.SetColour(value)
245 self.ctrl.SetValue(value)
247 #Settings notify works as a validator, but instead of validating anything, it calls another function, which can use the value.
248 # A bit hacky, bit it works.
249 class settingNotify():
250 def __init__(self, setting, func):
251 self.setting = setting
252 self.setting.validators.append(self)
257 return validators.SUCCESS, ''