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