chiark / gitweb /
Update on the dual-head offset calibration.
[cura.git] / Cura / gui / mainWindow.py
1 from __future__ import absolute_import
2
3 import wx
4 import os
5 import webbrowser
6
7 from Cura.gui import configBase
8 from Cura.gui import expertConfig
9 from Cura.gui import alterationPanel
10 from Cura.gui import pluginPanel
11 from Cura.gui import preferencesDialog
12 from Cura.gui import configWizard
13 from Cura.gui import firmwareInstall
14 from Cura.gui import simpleMode
15 from Cura.gui import sceneView
16 #from Cura.gui.tools import batchRun
17 from Cura.gui.util import dropTarget
18 from Cura.gui.tools import minecraftImport
19 from Cura.gui.tools import superformula
20 from Cura.util import profile
21 from Cura.util import version
22 from Cura.util import meshLoader
23
24 class mainWindow(wx.Frame):
25         def __init__(self):
26                 super(mainWindow, self).__init__(None, title='Cura Steam Engine BETA - ' + version.getVersion())
27
28                 self.extruderCount = int(profile.getPreference('extruder_amount'))
29
30                 wx.EVT_CLOSE(self, self.OnClose)
31
32                 self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.loadSupportedExtensions()))
33
34                 self.normalModeOnlyItems = []
35
36                 mruFile = os.path.join(profile.getBasePath(), 'mru_filelist.ini')
37                 self.config = wx.FileConfig(appName="Cura", 
38                                                 localFilename=mruFile,
39                                                 style=wx.CONFIG_USE_LOCAL_FILE)
40                                                 
41                 self.ID_MRU_MODEL1, self.ID_MRU_MODEL2, self.ID_MRU_MODEL3, self.ID_MRU_MODEL4, self.ID_MRU_MODEL5, self.ID_MRU_MODEL6, self.ID_MRU_MODEL7, self.ID_MRU_MODEL8, self.ID_MRU_MODEL9, self.ID_MRU_MODEL10 = [wx.NewId() for line in xrange(10)]
42                 self.modelFileHistory = wx.FileHistory(10, self.ID_MRU_MODEL1)
43                 self.config.SetPath("/ModelMRU")
44                 self.modelFileHistory.Load(self.config)
45
46                 self.ID_MRU_PROFILE1, self.ID_MRU_PROFILE2, self.ID_MRU_PROFILE3, self.ID_MRU_PROFILE4, self.ID_MRU_PROFILE5, self.ID_MRU_PROFILE6, self.ID_MRU_PROFILE7, self.ID_MRU_PROFILE8, self.ID_MRU_PROFILE9, self.ID_MRU_PROFILE10 = [wx.NewId() for line in xrange(10)]
47                 self.profileFileHistory = wx.FileHistory(10, self.ID_MRU_PROFILE1)
48                 self.config.SetPath("/ProfileMRU")
49                 self.profileFileHistory.Load(self.config)
50
51                 self.menubar = wx.MenuBar()
52                 self.fileMenu = wx.Menu()
53                 i = self.fileMenu.Append(-1, 'Load model file...\tCTRL+L')
54                 self.Bind(wx.EVT_MENU, lambda e: self.scene.showLoadModel(), i)
55                 i = self.fileMenu.Append(-1, 'Save model...\tCTRL+S')
56                 self.Bind(wx.EVT_MENU, lambda e: self.scene.showSaveModel(), i)
57
58                 self.fileMenu.AppendSeparator()
59                 i = self.fileMenu.Append(-1, 'Print...\tCTRL+P')
60                 self.Bind(wx.EVT_MENU, lambda e: self.scene.showPrintWindow(), i)
61                 i = self.fileMenu.Append(-1, 'Save GCode...')
62                 self.Bind(wx.EVT_MENU, lambda e: self.scene.showSaveGCode(), i)
63
64                 self.fileMenu.AppendSeparator()
65                 i = self.fileMenu.Append(-1, 'Open Profile...')
66                 self.normalModeOnlyItems.append(i)
67                 self.Bind(wx.EVT_MENU, self.OnLoadProfile, i)
68                 i = self.fileMenu.Append(-1, 'Save Profile...')
69                 self.normalModeOnlyItems.append(i)
70                 self.Bind(wx.EVT_MENU, self.OnSaveProfile, i)
71                 i = self.fileMenu.Append(-1, 'Load Profile from GCode...')
72                 self.normalModeOnlyItems.append(i)
73                 self.Bind(wx.EVT_MENU, self.OnLoadProfileFromGcode, i)
74                 self.fileMenu.AppendSeparator()
75                 i = self.fileMenu.Append(-1, 'Reset Profile to default')
76                 self.normalModeOnlyItems.append(i)
77                 self.Bind(wx.EVT_MENU, self.OnResetProfile, i)
78
79                 self.fileMenu.AppendSeparator()
80                 i = self.fileMenu.Append(-1, 'Preferences...\tCTRL+,')
81                 self.Bind(wx.EVT_MENU, self.OnPreferences, i)
82                 self.fileMenu.AppendSeparator()
83
84                 # Model MRU list
85                 modelHistoryMenu = wx.Menu()
86                 self.fileMenu.AppendMenu(wx.NewId(), "&Recent Model Files", modelHistoryMenu)
87                 self.modelFileHistory.UseMenu(modelHistoryMenu)
88                 self.modelFileHistory.AddFilesToMenu()
89                 self.Bind(wx.EVT_MENU_RANGE, self.OnModelMRU, id=self.ID_MRU_MODEL1, id2=self.ID_MRU_MODEL10)
90
91                 # Profle MRU list
92                 profileHistoryMenu = wx.Menu()
93                 self.fileMenu.AppendMenu(wx.NewId(), "&Recent Profile Files", profileHistoryMenu)
94                 self.profileFileHistory.UseMenu(profileHistoryMenu)
95                 self.profileFileHistory.AddFilesToMenu()
96                 self.Bind(wx.EVT_MENU_RANGE, self.OnProfileMRU, id=self.ID_MRU_PROFILE1, id2=self.ID_MRU_PROFILE10)
97                 
98                 self.fileMenu.AppendSeparator()
99                 i = self.fileMenu.Append(wx.ID_EXIT, 'Quit')
100                 self.Bind(wx.EVT_MENU, self.OnQuit, i)
101                 self.menubar.Append(self.fileMenu, '&File')
102
103                 toolsMenu = wx.Menu()
104                 i = toolsMenu.Append(-1, 'Switch to quickprint...')
105                 self.switchToQuickprintMenuItem = i
106                 self.Bind(wx.EVT_MENU, self.OnSimpleSwitch, i)
107                 i = toolsMenu.Append(-1, 'Switch to full settings...')
108                 self.switchToNormalMenuItem = i
109                 self.Bind(wx.EVT_MENU, self.OnNormalSwitch, i)
110                 toolsMenu.AppendSeparator()
111                 #i = toolsMenu.Append(-1, 'Batch run...')
112                 #self.Bind(wx.EVT_MENU, self.OnBatchRun, i)
113                 #self.normalModeOnlyItems.append(i)
114                 if minecraftImport.hasMinecraft():
115                         i = toolsMenu.Append(-1, 'Minecraft import...')
116                         self.Bind(wx.EVT_MENU, self.OnMinecraftImport, i)
117                 i = toolsMenu.Append(-1, 'Super-shaper...')
118                 self.Bind(wx.EVT_MENU, self.OnSuperformula, i)
119                 self.menubar.Append(toolsMenu, 'Tools')
120
121                 expertMenu = wx.Menu()
122                 i = expertMenu.Append(-1, 'Open expert settings...')
123                 self.normalModeOnlyItems.append(i)
124                 self.Bind(wx.EVT_MENU, self.OnExpertOpen, i)
125                 expertMenu.AppendSeparator()
126                 if firmwareInstall.getDefaultFirmware() is not None:
127                         i = expertMenu.Append(-1, 'Install default Marlin firmware')
128                         self.Bind(wx.EVT_MENU, self.OnDefaultMarlinFirmware, i)
129                 i = expertMenu.Append(-1, 'Install custom firmware')
130                 self.Bind(wx.EVT_MENU, self.OnCustomFirmware, i)
131                 expertMenu.AppendSeparator()
132                 i = expertMenu.Append(-1, 'Run first run wizard...')
133                 self.Bind(wx.EVT_MENU, self.OnFirstRunWizard, i)
134                 i = expertMenu.Append(-1, 'Run bed leveling wizard...')
135                 self.Bind(wx.EVT_MENU, self.OnBedLevelWizard, i)
136                 if self.extruderCount > 1:
137                         i = expertMenu.Append(-1, 'Run head offset wizard...')
138                         self.Bind(wx.EVT_MENU, self.OnHeadOffsetWizard, i)
139                 self.menubar.Append(expertMenu, 'Expert')
140
141                 helpMenu = wx.Menu()
142                 i = helpMenu.Append(-1, 'Online documentation...')
143                 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('http://daid.github.com/Cura'), i)
144                 i = helpMenu.Append(-1, 'Report a problem...')
145                 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i)
146                 i = helpMenu.Append(-1, 'Check for update...')
147                 self.Bind(wx.EVT_MENU, self.OnCheckForUpdate, i)
148                 self.menubar.Append(helpMenu, 'Help')
149                 self.SetMenuBar(self.menubar)
150
151                 self.splitter = wx.SplitterWindow(self, style = wx.SP_3D | wx.SP_LIVE_UPDATE)
152                 self.leftPane = wx.Panel(self.splitter, style=wx.BORDER_NONE)
153                 self.rightPane = wx.Panel(self.splitter, style=wx.BORDER_NONE)
154                 self.splitter.Bind(wx.EVT_SPLITTER_DCLICK, lambda evt: evt.Veto())
155
156                 ##Gui components##
157                 self.simpleSettingsPanel = simpleMode.simpleModePanel(self.leftPane, lambda : self.scene.sceneUpdated())
158                 self.normalSettingsPanel = normalSettingsPanel(self.leftPane, lambda : self.scene.sceneUpdated())
159
160                 self.leftSizer = wx.BoxSizer(wx.VERTICAL)
161                 self.leftSizer.Add(self.simpleSettingsPanel)
162                 self.leftSizer.Add(self.normalSettingsPanel, 1, wx.EXPAND)
163                 self.leftPane.SetSizer(self.leftSizer)
164                 
165                 #Preview window
166                 self.scene = sceneView.SceneView(self.rightPane)
167
168                 #Main sizer, to position the preview window, buttons and tab control
169                 sizer = wx.BoxSizer()
170                 self.rightPane.SetSizer(sizer)
171                 sizer.Add(self.scene, 1, flag=wx.EXPAND)
172
173                 # Main window sizer
174                 sizer = wx.BoxSizer(wx.VERTICAL)
175                 self.SetSizer(sizer)
176                 sizer.Add(self.splitter, 1, wx.EXPAND)
177                 sizer.Layout()
178                 self.sizer = sizer
179
180                 self.updateProfileToControls()
181
182                 self.SetBackgroundColour(self.normalSettingsPanel.GetBackgroundColour())
183
184                 self.simpleSettingsPanel.Show(False)
185                 self.normalSettingsPanel.Show(False)
186
187                 # Set default window size & position
188                 self.SetSize((wx.Display().GetClientArea().GetWidth()/2,wx.Display().GetClientArea().GetHeight()/2))
189                 self.Centre()
190
191                 # Restore the window position, size & state from the preferences file
192                 try:
193                         if profile.getPreference('window_maximized') == 'True':
194                                 self.Maximize(True)
195                         else:
196                                 posx = int(profile.getPreference('window_pos_x'))
197                                 posy = int(profile.getPreference('window_pos_y'))
198                                 width = int(profile.getPreference('window_width'))
199                                 height = int(profile.getPreference('window_height'))
200                                 if posx > 0 or posy > 0:
201                                         self.SetPosition((posx,posy))
202                                 if width > 0 and height > 0:
203                                         self.SetSize((width,height))
204                                 
205                         self.normalSashPos = int(profile.getPreference('window_normal_sash'))
206                 except:
207                         self.normalSashPos = 0
208                         self.Maximize(True)
209                 if self.normalSashPos < self.normalSettingsPanel.printPanel.GetBestSize()[0] + 5:
210                         self.normalSashPos = self.normalSettingsPanel.printPanel.GetBestSize()[0] + 5
211
212                 self.splitter.SplitVertically(self.leftPane, self.rightPane, self.normalSashPos)
213
214                 if wx.Display.GetFromPoint(self.GetPosition()) < 0:
215                         self.Centre()
216                 if wx.Display.GetFromPoint((self.GetPositionTuple()[0] + self.GetSizeTuple()[1], self.GetPositionTuple()[1] + self.GetSizeTuple()[1])) < 0:
217                         self.Centre()
218                 if wx.Display.GetFromPoint(self.GetPosition()) < 0:
219                         self.SetSize((800,600))
220                         self.Centre()
221
222                 self.updateSliceMode()
223
224         def updateSliceMode(self):
225                 isSimple = profile.getPreference('startMode') == 'Simple'
226
227                 self.normalSettingsPanel.Show(not isSimple)
228                 self.simpleSettingsPanel.Show(isSimple)
229                 self.leftPane.Layout()
230
231                 for i in self.normalModeOnlyItems:
232                         i.Enable(not isSimple)
233                 self.switchToQuickprintMenuItem.Enable(not isSimple)
234                 self.switchToNormalMenuItem.Enable(isSimple)
235
236                 # Set splitter sash position & size
237                 if isSimple:
238                         # Save normal mode sash
239                         self.normalSashPos = self.splitter.GetSashPosition()
240                         
241                         # Change location of sash to width of quick mode pane 
242                         (width, height) = self.simpleSettingsPanel.GetSizer().GetSize() 
243                         self.splitter.SetSashPosition(width, True)
244                         
245                         # Disable sash
246                         self.splitter.SetSashSize(0)
247                 else:
248                         self.splitter.SetSashPosition(self.normalSashPos, True)
249                         # Enabled sash
250                         self.splitter.SetSashSize(4)
251                 self.scene.updateProfileToControls()
252                                                                 
253         def OnPreferences(self, e):
254                 prefDialog = preferencesDialog.preferencesDialog(self)
255                 prefDialog.Centre()
256                 prefDialog.Show()
257
258         def OnDropFiles(self, files):
259                 profile.setPluginConfig([])
260                 self.updateProfileToControls()
261                 self.scene.loadScene(files)
262
263         def OnModelMRU(self, e):
264                 fileNum = e.GetId() - self.ID_MRU_MODEL1
265                 path = self.modelFileHistory.GetHistoryFile(fileNum)
266                 # Update Model MRU
267                 self.modelFileHistory.AddFileToHistory(path)  # move up the list
268                 self.config.SetPath("/ModelMRU")
269                 self.modelFileHistory.Save(self.config)
270                 self.config.Flush()
271                 # Load Model
272                 filelist = [ path ]
273                 self.scene.loadScene(filelist)
274
275         def addToModelMRU(self, file):
276                 self.modelFileHistory.AddFileToHistory(file)
277                 self.config.SetPath("/ModelMRU")
278                 self.modelFileHistory.Save(self.config)
279                 self.config.Flush()
280         
281         def OnProfileMRU(self, e):
282                 fileNum = e.GetId() - self.ID_MRU_PROFILE1
283                 path = self.profileFileHistory.GetHistoryFile(fileNum)
284                 # Update Profile MRU
285                 self.profileFileHistory.AddFileToHistory(path)  # move up the list
286                 self.config.SetPath("/ProfileMRU")
287                 self.profileFileHistory.Save(self.config)
288                 self.config.Flush()
289                 # Load Profile  
290                 profile.loadProfile(path)
291                 self.updateProfileToControls()
292
293         def addToProfileMRU(self, file):
294                 self.profileFileHistory.AddFileToHistory(file)
295                 self.config.SetPath("/ProfileMRU")
296                 self.profileFileHistory.Save(self.config)
297                 self.config.Flush()                     
298
299         def updateProfileToControls(self):
300                 self.scene.updateProfileToControls()
301                 self.normalSettingsPanel.updateProfileToControls()
302                 self.simpleSettingsPanel.updateProfileToControls()
303
304         def OnLoadProfile(self, e):
305                 dlg=wx.FileDialog(self, "Select profile file to load", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
306                 dlg.SetWildcard("ini files (*.ini)|*.ini")
307                 if dlg.ShowModal() == wx.ID_OK:
308                         profileFile = dlg.GetPath()
309                         profile.loadProfile(profileFile)
310                         self.updateProfileToControls()
311
312                         # Update the Profile MRU
313                         self.addToProfileMRU(profileFile)
314                 dlg.Destroy()
315
316         def OnLoadProfileFromGcode(self, e):
317                 dlg=wx.FileDialog(self, "Select gcode file to load profile from", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
318                 dlg.SetWildcard("gcode files (*.gcode)|*.gcode;*.g")
319                 if dlg.ShowModal() == wx.ID_OK:
320                         gcodeFile = dlg.GetPath()
321                         f = open(gcodeFile, 'r')
322                         hasProfile = False
323                         for line in f:
324                                 if line.startswith(';CURA_PROFILE_STRING:'):
325                                         profile.loadProfileFromString(line[line.find(':')+1:].strip())
326                                         hasProfile = True
327                         if hasProfile:
328                                 self.updateProfileToControls()
329                         else:
330                                 wx.MessageBox('No profile found in GCode file.\nThis feature only works with GCode files made by Cura 12.07 or newer.', 'Profile load error', wx.OK | wx.ICON_INFORMATION)
331                 dlg.Destroy()
332
333         def OnSaveProfile(self, e):
334                 dlg=wx.FileDialog(self, "Select profile file to save", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE)
335                 dlg.SetWildcard("ini files (*.ini)|*.ini")
336                 if dlg.ShowModal() == wx.ID_OK:
337                         profileFile = dlg.GetPath()
338                         profile.saveProfile(profileFile)
339                 dlg.Destroy()
340
341         def OnResetProfile(self, e):
342                 dlg = wx.MessageDialog(self, 'This will reset all profile settings to defaults.\nUnless you have saved your current profile, all settings will be lost!\nDo you really want to reset?', 'Profile reset', wx.YES_NO | wx.ICON_QUESTION)
343                 result = dlg.ShowModal() == wx.ID_YES
344                 dlg.Destroy()
345                 if result:
346                         profile.resetProfile()
347                         self.updateProfileToControls()
348
349         def OnBatchRun(self, e):
350                 br = batchRun.batchRunWindow(self)
351                 br.Centre()
352                 br.Show(True)
353
354         def OnSimpleSwitch(self, e):
355                 profile.putPreference('startMode', 'Simple')
356                 self.updateSliceMode()
357
358         def OnNormalSwitch(self, e):
359                 profile.putPreference('startMode', 'Normal')
360                 self.updateSliceMode()
361
362         def OnDefaultMarlinFirmware(self, e):
363                 firmwareInstall.InstallFirmware()
364
365         def OnCustomFirmware(self, e):
366                 if profile.getPreference('machine_type') == 'ultimaker':
367                         wx.MessageBox('Warning: Installing a custom firmware does not guarantee that you machine will function correctly, and could damage your machine.', 'Firmware update', wx.OK | wx.ICON_EXCLAMATION)
368                 dlg=wx.FileDialog(self, "Open firmware to upload", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
369                 dlg.SetWildcard("HEX file (*.hex)|*.hex;*.HEX")
370                 if dlg.ShowModal() == wx.ID_OK:
371                         filename = dlg.GetPath()
372                         if not(os.path.exists(filename)):
373                                 return
374                         #For some reason my Ubuntu 10.10 crashes here.
375                         firmwareInstall.InstallFirmware(filename)
376
377         def OnFirstRunWizard(self, e):
378                 configWizard.configWizard()
379                 self.updateProfileToControls()
380
381         def OnBedLevelWizard(self, e):
382                 configWizard.bedLevelWizard()
383
384         def OnHeadOffsetWizard(self, e):
385                 configWizard.headOffsetWizard()
386
387         def OnExpertOpen(self, e):
388                 ecw = expertConfig.expertConfigWindow()
389                 ecw.Centre()
390                 ecw.ShowModal()
391                 self.scene.sceneUpdated()
392
393         def OnMinecraftImport(self, e):
394                 mi = minecraftImport.minecraftImportWindow(self)
395                 mi.Centre()
396                 mi.Show(True)
397
398         def OnSuperformula(self, e):
399                 sf = superformula.superformulaWindow(self)
400                 sf.Centre()
401                 sf.Show(True)
402
403         def OnCheckForUpdate(self, e):
404                 newVersion = version.checkForNewerVersion()
405                 if newVersion is not None:
406                         if wx.MessageBox('A new version of Cura is available, would you like to download?', 'New version available', wx.YES_NO | wx.ICON_INFORMATION) == wx.YES:
407                                 webbrowser.open(newVersion)
408                 else:
409                         wx.MessageBox('You are running the latest version of Cura!', 'Awesome!', wx.ICON_INFORMATION)
410
411         def OnClose(self, e):
412                 profile.saveProfile(profile.getDefaultProfilePath())
413
414                 # Save the window position, size & state from the preferences file
415                 profile.putPreference('window_maximized', self.IsMaximized())
416                 if not self.IsMaximized() and not self.IsIconized():
417                         (posx, posy) = self.GetPosition()
418                         profile.putPreference('window_pos_x', posx)
419                         profile.putPreference('window_pos_y', posy)
420                         (width, height) = self.GetSize()
421                         profile.putPreference('window_width', width)
422                         profile.putPreference('window_height', height)                  
423                         
424                         # Save normal sash position.  If in normal mode (!simple mode), get last position of sash before saving it...
425                         isSimple = profile.getPreference('startMode') == 'Simple'
426                         if not isSimple:
427                                 self.normalSashPos = self.splitter.GetSashPosition()
428                         profile.putPreference('window_normal_sash', self.normalSashPos)
429
430                 #HACK: Set the paint function of the glCanvas to nothing so it won't keep refreshing. Which keeps wxWidgets from quiting.
431                 print "Closing down"
432                 self.scene.OnPaint = lambda e : e
433                 self.scene._slicer.cleanup()
434                 self.Destroy()
435
436         def OnQuit(self, e):
437                 self.Close()
438
439 class normalSettingsPanel(configBase.configPanelBase):
440         "Main user interface window"
441         def __init__(self, parent, callback = None):
442                 super(normalSettingsPanel, self).__init__(parent, callback)
443
444                 #Main tabs
445                 self.nb = wx.Notebook(self)
446                 self.SetSizer(wx.BoxSizer(wx.HORIZONTAL))
447                 self.GetSizer().Add(self.nb, 1, wx.EXPAND)
448
449                 (left, right, self.printPanel) = self.CreateDynamicConfigTab(self.nb, 'Basic')
450                 self._addSettingsToPanels('basic', left, right)
451                 self.SizeLabelWidths(left, right)
452                 
453                 (left, right, self.advancedPanel) = self.CreateDynamicConfigTab(self.nb, 'Advanced')
454                 self._addSettingsToPanels('advanced', left, right)
455                 self.SizeLabelWidths(left, right)
456
457                 #Plugin page
458                 self.pluginPanel = pluginPanel.pluginPanel(self.nb, callback)
459                 if len(self.pluginPanel.pluginList) > 0:
460                         self.nb.AddPage(self.pluginPanel, "Plugins")
461                 else:
462                         self.pluginPanel.Show(False)
463
464                 #Alteration page
465                 self.alterationPanel = alterationPanel.alterationPanel(self.nb, callback)
466                 self.nb.AddPage(self.alterationPanel, "Start/End-GCode")
467
468                 self.Bind(wx.EVT_SIZE, self.OnSize)
469
470                 self.nb.SetSize(self.GetSize())
471                 self.UpdateSize(self.printPanel)
472                 self.UpdateSize(self.advancedPanel)
473
474         def _addSettingsToPanels(self, category, left, right):
475                 count = len(profile.getSubCategoriesFor(category)) + len(profile.getSettingsForCategory(category))
476
477                 p = left
478                 n = 0
479                 for title in profile.getSubCategoriesFor(category):
480                         n += 1 + len(profile.getSettingsForCategory(category, title))
481                         if n > count / 2:
482                                 p = right
483                         configBase.TitleRow(p, title)
484                         for s in profile.getSettingsForCategory(category, title):
485                                 if s.checkConditions():
486                                         configBase.SettingRow(p, s.getName())
487
488         def SizeLabelWidths(self, left, right):
489                 leftWidth = self.getLabelColumnWidth(left)
490                 rightWidth = self.getLabelColumnWidth(right)
491                 maxWidth = max(leftWidth, rightWidth)
492                 self.setLabelColumnWidth(left, maxWidth)
493                 self.setLabelColumnWidth(right, maxWidth)
494
495         def OnSize(self, e):
496                 # Make the size of the Notebook control the same size as this control
497                 self.nb.SetSize(self.GetSize())
498                 
499                 # Propegate the OnSize() event (just in case)
500                 e.Skip()
501                 
502                 # Perform out resize magic
503                 self.UpdateSize(self.printPanel)
504                 self.UpdateSize(self.advancedPanel)
505         
506         def UpdateSize(self, configPanel):
507                 sizer = configPanel.GetSizer()
508                 
509                 # Pseudocde
510                 # if horizontal:
511                 #     if width(col1) < best_width(col1) || width(col2) < best_width(col2):
512                 #         switch to vertical
513                 # else:
514                 #     if width(col1) > (best_width(col1) + best_width(col1)):
515                 #         switch to horizontal
516                 #
517                                 
518                 col1 = configPanel.leftPanel
519                 colSize1 = col1.GetSize()
520                 colBestSize1 = col1.GetBestSize()
521                 col2 = configPanel.rightPanel
522                 colSize2 = col2.GetSize()
523                 colBestSize2 = col2.GetBestSize()
524
525                 orientation = sizer.GetOrientation()
526                 
527                 if orientation == wx.HORIZONTAL:
528                         if (colSize1[0] <= colBestSize1[0]) or (colSize2[0] <= colBestSize2[0]):
529                                 configPanel.Freeze()
530                                 sizer = wx.BoxSizer(wx.VERTICAL)
531                                 sizer.Add(configPanel.leftPanel, flag=wx.EXPAND)
532                                 sizer.Add(configPanel.rightPanel, flag=wx.EXPAND)
533                                 configPanel.SetSizer(sizer)
534                                 #sizer.Layout()
535                                 configPanel.Layout()
536                                 self.Layout()
537                                 configPanel.Thaw()
538                 else:
539                         if max(colSize1[0], colSize2[0]) > (colBestSize1[0] + colBestSize2[0]):
540                                 configPanel.Freeze()
541                                 sizer = wx.BoxSizer(wx.HORIZONTAL)
542                                 sizer.Add(configPanel.leftPanel, proportion=1, border=35, flag=wx.EXPAND)
543                                 sizer.Add(configPanel.rightPanel, proportion=1, flag=wx.EXPAND)
544                                 configPanel.SetSizer(sizer)
545                                 #sizer.Layout()
546                                 configPanel.Layout()
547                                 self.Layout()
548                                 configPanel.Thaw()
549
550         def updateProfileToControls(self):
551                 super(normalSettingsPanel, self).updateProfileToControls()
552                 self.alterationPanel.updateProfileToControls()
553                 self.pluginPanel.updateProfileToControls()