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