chiark / gitweb /
Fix for problems with new layout
[cura.git] / Cura / gui / configBase.py
1 from __future__ import absolute_import
2
3 import wx, wx.lib.stattext, types
4
5 from Cura.util import validators
6 from Cura.util import profile
7
8 class configPanelBase(wx.Panel):
9         "A base class for configuration dialogs. Handles creation of settings, and popups"
10         def __init__(self, parent):
11                 super(configPanelBase, self).__init__(parent)
12                 
13                 self.settingControlList = []
14                 
15                 #Create the popup window
16                 self.popup = wx.PopupWindow(self, flags=wx.BORDER_SIMPLE)
17                 self.popup.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_INFOBK))
18                 self.popup.setting = None
19                 self.popup.text = wx.StaticText(self.popup, -1, '');
20                 self.popup.sizer = wx.BoxSizer()
21                 self.popup.sizer.Add(self.popup.text, flag=wx.EXPAND|wx.ALL, border=1)
22                 self.popup.SetSizer(self.popup.sizer)
23         
24         def CreateConfigTab(self, nb, name):
25                 leftConfigPanel, rightConfigPanel, configPanel = self.CreateConfigPanel(nb)
26                 nb.AddPage(configPanel, name)
27                 return leftConfigPanel, rightConfigPanel
28         
29         def CreateConfigPanel(self, parent):
30                 configPanel = wx.Panel(parent);
31                 leftConfigPanel = wx.Panel(configPanel)
32                 rightConfigPanel = wx.Panel(configPanel)
33                 sizer = wx.GridBagSizer(2, 2)
34                 leftConfigPanel.SetSizer(sizer)
35                 sizer = wx.GridBagSizer(2, 2)
36                 rightConfigPanel.SetSizer(sizer)
37                 sizer = wx.BoxSizer(wx.HORIZONTAL)
38                 configPanel.SetSizer(sizer)
39                 sizer.Add(leftConfigPanel, border=35, flag=wx.RIGHT)
40                 sizer.Add(rightConfigPanel)
41                 leftConfigPanel.main = self
42                 rightConfigPanel.main = self
43                 return leftConfigPanel, rightConfigPanel, configPanel
44
45         def CreateSimpleConfigTab(self, nb, name):
46                 leftConfigPanel, configPanel = self.CreateSimpleConfigPanel(nb)
47                 nb.AddPage(configPanel, name)
48                 return leftConfigPanel
49         
50         def CreateSimpleConfigPanel(self, parent):
51                 configPanel = wx.lib.scrolledpanel.ScrolledPanel(parent)
52                 leftConfigPanel = wx.Panel(configPanel)
53                 
54                 sizer = wx.GridBagSizer(2, 2)
55                 leftConfigPanel.SetSizer(sizer)
56                 sizer.AddGrowableCol(1)
57
58                 sizer = wx.BoxSizer(wx.HORIZONTAL)
59                 configPanel.SetSizer(sizer)
60                 sizer.Add(leftConfigPanel, 1, wx.EXPAND)
61
62                 configPanel.SetAutoLayout(1)
63                 configPanel.SetupScrolling()
64
65                 leftConfigPanel.main = self
66                 return leftConfigPanel, configPanel
67
68         def OnPopupDisplay(self, setting):
69                 self.popup.setting = setting
70                 self.UpdatePopup(setting)
71                 self.popup.Show(True)
72                 
73         def OnPopupHide(self, e):
74                 self.popup.Show(False)
75         
76         def UpdatePopup(self, setting):
77                 if self.popup.setting == setting:
78                         if setting.validationMsg != '':
79                                 self.popup.text.SetLabel(setting.validationMsg + '\n\n' + setting.helpText)
80                         else:
81                                 self.popup.text.SetLabel(setting.helpText)
82                         self.popup.text.Wrap(350)
83                         self.popup.Fit()
84                         x, y = setting.ctrl.ClientToScreenXY(0, 0)
85                         sx, sy = setting.ctrl.GetSizeTuple()
86                         #if platform.system() == "Windows":
87                         #       for some reason, under windows, the popup is relative to the main window... in some cases. (Wierd ass bug)
88                         #       wx, wy = self.ClientToScreenXY(0, 0)
89                         #       x -= wx
90                         #       y -= wy
91                         self.popup.SetPosition((x, y+sy))
92         
93         def updateProfileToControls(self):
94                 "Update the configuration wx controls to show the new configuration settings"
95                 for setting in self.settingControlList:
96                         if setting.type == 'profile':
97                                 setting.SetValue(profile.getProfileSetting(setting.configName))
98                         else:
99                                 setting.SetValue(profile.getPreference(setting.configName))
100                 self.Update()
101
102 class TitleRow():
103         def __init__(self, panel, name):
104                 "Add a title row to the configuration panel"
105                 sizer = panel.GetSizer()
106                 x = sizer.GetRows()
107                 self.title = wx.StaticText(panel, -1, name)
108                 self.title.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
109                 sizer.Add(self.title, (x,0), (1,3), flag=wx.EXPAND|wx.TOP|wx.LEFT, border=10)
110                 sizer.Add(wx.StaticLine(panel), (x+1,0), (1,3), flag=wx.EXPAND|wx.LEFT,border=10)
111                 sizer.SetRows(x + 2)
112
113 class SettingRow():
114         def __init__(self, panel, label, configName, defaultValue = '', helpText = 'Help: TODO', type = 'profile'):
115                 "Add a setting to the configuration panel"
116                 sizer = panel.GetSizer()
117                 x = sizer.GetRows()
118                 y = 0
119                 flag = 0
120                 
121                 self.validators = []
122                 self.validationMsg = ''
123                 self.helpText = helpText
124                 self.configName = configName
125                 self.panel = panel
126                 self.type = type
127
128                 self.label = wx.lib.stattext.GenStaticText(panel, -1, label)
129                 self.label.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
130                 self.label.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
131
132                 getSettingFunc = profile.getPreference
133                 if self.type == 'profile':
134                         getSettingFunc = profile.getProfileSetting
135                 if isinstance(defaultValue, types.StringTypes):
136                         self.ctrl = wx.TextCtrl(panel, -1, getSettingFunc(configName))
137                         self.ctrl.Bind(wx.EVT_TEXT, self.OnSettingChange)
138                         flag = wx.EXPAND
139                 elif isinstance(defaultValue, types.BooleanType):
140                         self.ctrl = wx.CheckBox(panel, -1, style=wx.ALIGN_RIGHT)
141                         self.SetValue(getSettingFunc(configName))
142                         self.ctrl.Bind(wx.EVT_CHECKBOX, self.OnSettingChange)
143                 elif isinstance(defaultValue, wx.Colour):
144                         self.ctrl = wx.ColourPickerCtrl(panel, -1)
145                         self.SetValue(getSettingFunc(configName))
146                         self.ctrl.Bind(wx.EVT_COLOURPICKER_CHANGED, self.OnSettingChange)
147                 else:
148                         self.ctrl = wx.ComboBox(panel, -1, getSettingFunc(configName), choices=defaultValue, style=wx.CB_DROPDOWN|wx.CB_READONLY)
149                         self.ctrl.Bind(wx.EVT_COMBOBOX, self.OnSettingChange)
150                         self.ctrl.Bind(wx.EVT_LEFT_DOWN, self.OnMouseExit)
151                         flag = wx.EXPAND
152
153                 sizer.Add(self.label, (x,y), flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT,border=10)
154                 sizer.Add(self.ctrl, (x,y+1), flag=wx.ALIGN_BOTTOM|flag)
155                 sizer.SetRows(x+1)
156
157                 self.ctrl.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter)
158                 self.ctrl.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseExit)
159                 
160                 self.defaultBGColour = self.ctrl.GetBackgroundColour()
161                 
162                 panel.main.settingControlList.append(self)
163
164         def OnMouseEnter(self, e):
165                 self.panel.main.OnPopupDisplay(self)
166
167         def OnMouseExit(self, e):
168                 self.panel.main.OnPopupHide(self)
169                 e.Skip()
170
171         def OnSettingChange(self, e):
172                 if self.type == 'profile':
173                         profile.putProfileSetting(self.configName, self.GetValue())
174                 else:
175                         profile.putPreference(self.configName, self.GetValue())
176                 result = validators.SUCCESS
177                 msgs = []
178                 for validator in self.validators:
179                         res, err = validator.validate()
180                         if res == validators.ERROR:
181                                 result = res
182                         elif res == validators.WARNING and result != validators.ERROR:
183                                 result = res
184                         if res != validators.SUCCESS:
185                                 msgs.append(err)
186                 if result == validators.ERROR:
187                         self.ctrl.SetBackgroundColour('Red')
188                 elif result == validators.WARNING:
189                         self.ctrl.SetBackgroundColour('Yellow')
190                 else:
191                         self.ctrl.SetBackgroundColour(self.defaultBGColour)
192                 self.ctrl.Refresh()
193
194                 self.validationMsg = '\n'.join(msgs)
195                 self.panel.main.UpdatePopup(self)
196
197         def GetValue(self):
198                 if isinstance(self.ctrl, wx.ColourPickerCtrl):
199                         return str(self.ctrl.GetColour().GetAsString(wx.C2S_HTML_SYNTAX))
200                 else:
201                         return str(self.ctrl.GetValue())
202
203         def SetValue(self, value):
204                 if isinstance(self.ctrl, wx.CheckBox):
205                         self.ctrl.SetValue(str(value) == "True")
206                 elif isinstance(self.ctrl, wx.ColourPickerCtrl):
207                         self.ctrl.SetColour(value)
208                 else:
209                         self.ctrl.SetValue(value)
210
211 #Settings notify works as a validator, but instead of validating anything, it calls another function, which can use the value.
212 # A bit hacky, bit it works.
213 class settingNotify():
214         def __init__(self, setting, func):
215                 self.setting = setting
216                 self.setting.validators.append(self)
217                 self.func = func
218         
219         def validate(self):
220                 self.func()
221                 return validators.SUCCESS, ''
222