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