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