1 from __future__ import absolute_import
2 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
8 from Cura.gui import configBase
9 from Cura.gui import expertConfig
10 from Cura.gui import alterationPanel
11 from Cura.gui import pluginPanel
12 from Cura.gui import preferencesDialog
13 from Cura.gui import configWizard
14 from Cura.gui import firmwareInstall
15 from Cura.gui import simpleMode
16 from Cura.gui import sceneView
17 #from Cura.gui.tools import batchRun
18 from Cura.gui.util import dropTarget
19 from Cura.gui.tools import minecraftImport
20 from Cura.gui.tools import superformula
21 from Cura.util import profile
22 from Cura.util import version
23 from Cura.util import meshLoader
25 class mainWindow(wx.Frame):
27 super(mainWindow, self).__init__(None, title='Cura - ' + version.getVersion())
29 self.extruderCount = int(profile.getPreference('extruder_amount'))
31 wx.EVT_CLOSE(self, self.OnClose)
33 self.SetDropTarget(dropTarget.FileDropTarget(self.OnDropFiles, meshLoader.loadSupportedExtensions()))
35 self.normalModeOnlyItems = []
37 mruFile = os.path.join(profile.getBasePath(), 'mru_filelist.ini')
38 self.config = wx.FileConfig(appName="Cura",
39 localFilename=mruFile,
40 style=wx.CONFIG_USE_LOCAL_FILE)
42 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)]
43 self.modelFileHistory = wx.FileHistory(10, self.ID_MRU_MODEL1)
44 self.config.SetPath("/ModelMRU")
45 self.modelFileHistory.Load(self.config)
47 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)]
48 self.profileFileHistory = wx.FileHistory(10, self.ID_MRU_PROFILE1)
49 self.config.SetPath("/ProfileMRU")
50 self.profileFileHistory.Load(self.config)
52 self.menubar = wx.MenuBar()
53 self.fileMenu = wx.Menu()
54 i = self.fileMenu.Append(-1, 'Load model file...\tCTRL+L')
55 self.Bind(wx.EVT_MENU, lambda e: self.scene.showLoadModel(), i)
56 i = self.fileMenu.Append(-1, 'Save model...\tCTRL+S')
57 self.Bind(wx.EVT_MENU, lambda e: self.scene.showSaveModel(), i)
58 i = self.fileMenu.Append(-1, 'Clear platform')
59 self.Bind(wx.EVT_MENU, lambda e: self.scene.OnDeleteAll(e), i)
61 self.fileMenu.AppendSeparator()
62 i = self.fileMenu.Append(-1, 'Print...\tCTRL+P')
63 self.Bind(wx.EVT_MENU, lambda e: self.scene.showPrintWindow(), i)
64 i = self.fileMenu.Append(-1, 'Save GCode...')
65 self.Bind(wx.EVT_MENU, lambda e: self.scene.showSaveGCode(), i)
66 i = self.fileMenu.Append(-1, 'Show slice engine log...')
67 self.Bind(wx.EVT_MENU, lambda e: self.scene._showSliceLog(), i)
69 self.fileMenu.AppendSeparator()
70 i = self.fileMenu.Append(-1, 'Open Profile...')
71 self.normalModeOnlyItems.append(i)
72 self.Bind(wx.EVT_MENU, self.OnLoadProfile, i)
73 i = self.fileMenu.Append(-1, 'Save Profile...')
74 self.normalModeOnlyItems.append(i)
75 self.Bind(wx.EVT_MENU, self.OnSaveProfile, i)
76 i = self.fileMenu.Append(-1, 'Load Profile from GCode...')
77 self.normalModeOnlyItems.append(i)
78 self.Bind(wx.EVT_MENU, self.OnLoadProfileFromGcode, i)
79 self.fileMenu.AppendSeparator()
80 i = self.fileMenu.Append(-1, 'Reset Profile to default')
81 self.normalModeOnlyItems.append(i)
82 self.Bind(wx.EVT_MENU, self.OnResetProfile, i)
84 self.fileMenu.AppendSeparator()
85 i = self.fileMenu.Append(-1, 'Preferences...\tCTRL+,')
86 self.Bind(wx.EVT_MENU, self.OnPreferences, i)
87 self.fileMenu.AppendSeparator()
90 modelHistoryMenu = wx.Menu()
91 self.fileMenu.AppendMenu(wx.NewId(), "&Recent Model Files", modelHistoryMenu)
92 self.modelFileHistory.UseMenu(modelHistoryMenu)
93 self.modelFileHistory.AddFilesToMenu()
94 self.Bind(wx.EVT_MENU_RANGE, self.OnModelMRU, id=self.ID_MRU_MODEL1, id2=self.ID_MRU_MODEL10)
97 profileHistoryMenu = wx.Menu()
98 self.fileMenu.AppendMenu(wx.NewId(), "&Recent Profile Files", profileHistoryMenu)
99 self.profileFileHistory.UseMenu(profileHistoryMenu)
100 self.profileFileHistory.AddFilesToMenu()
101 self.Bind(wx.EVT_MENU_RANGE, self.OnProfileMRU, id=self.ID_MRU_PROFILE1, id2=self.ID_MRU_PROFILE10)
103 self.fileMenu.AppendSeparator()
104 i = self.fileMenu.Append(wx.ID_EXIT, 'Quit')
105 self.Bind(wx.EVT_MENU, self.OnQuit, i)
106 self.menubar.Append(self.fileMenu, '&File')
108 toolsMenu = wx.Menu()
109 i = toolsMenu.Append(-1, 'Switch to quickprint...')
110 self.switchToQuickprintMenuItem = i
111 self.Bind(wx.EVT_MENU, self.OnSimpleSwitch, i)
112 i = toolsMenu.Append(-1, 'Switch to full settings...')
113 self.switchToNormalMenuItem = i
114 self.Bind(wx.EVT_MENU, self.OnNormalSwitch, i)
115 toolsMenu.AppendSeparator()
116 #i = toolsMenu.Append(-1, 'Batch run...')
117 #self.Bind(wx.EVT_MENU, self.OnBatchRun, i)
118 #self.normalModeOnlyItems.append(i)
119 if minecraftImport.hasMinecraft():
120 i = toolsMenu.Append(-1, 'Minecraft import...')
121 self.Bind(wx.EVT_MENU, self.OnMinecraftImport, i)
122 i = toolsMenu.Append(-1, 'Super-shaper...')
123 self.Bind(wx.EVT_MENU, self.OnSuperformula, i)
124 self.menubar.Append(toolsMenu, 'Tools')
126 expertMenu = wx.Menu()
127 i = expertMenu.Append(-1, 'Open expert settings...')
128 self.normalModeOnlyItems.append(i)
129 self.Bind(wx.EVT_MENU, self.OnExpertOpen, i)
130 expertMenu.AppendSeparator()
131 if firmwareInstall.getDefaultFirmware() is not None:
132 i = expertMenu.Append(-1, 'Install default Marlin firmware')
133 self.Bind(wx.EVT_MENU, self.OnDefaultMarlinFirmware, i)
134 i = expertMenu.Append(-1, 'Install custom firmware')
135 self.Bind(wx.EVT_MENU, self.OnCustomFirmware, i)
136 expertMenu.AppendSeparator()
137 i = expertMenu.Append(-1, 'Run first run wizard...')
138 self.Bind(wx.EVT_MENU, self.OnFirstRunWizard, i)
139 i = expertMenu.Append(-1, 'Run bed leveling wizard...')
140 self.Bind(wx.EVT_MENU, self.OnBedLevelWizard, i)
141 if self.extruderCount > 1:
142 i = expertMenu.Append(-1, 'Run head offset wizard...')
143 self.Bind(wx.EVT_MENU, self.OnHeadOffsetWizard, i)
144 self.menubar.Append(expertMenu, 'Expert')
147 i = helpMenu.Append(-1, 'Online documentation...')
148 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('http://daid.github.com/Cura'), i)
149 i = helpMenu.Append(-1, 'Report a problem...')
150 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i)
151 i = helpMenu.Append(-1, 'Check for update...')
152 self.Bind(wx.EVT_MENU, self.OnCheckForUpdate, i)
153 i = helpMenu.Append(-1, 'About Cura...')
154 self.Bind(wx.EVT_MENU, self.OnAbout, i)
155 self.menubar.Append(helpMenu, 'Help')
156 self.SetMenuBar(self.menubar)
158 self.splitter = wx.SplitterWindow(self, style = wx.SP_3D | wx.SP_LIVE_UPDATE)
159 self.leftPane = wx.Panel(self.splitter, style=wx.BORDER_NONE)
160 self.rightPane = wx.Panel(self.splitter, style=wx.BORDER_NONE)
161 self.splitter.Bind(wx.EVT_SPLITTER_DCLICK, lambda evt: evt.Veto())
164 self.simpleSettingsPanel = simpleMode.simpleModePanel(self.leftPane, lambda : self.scene.sceneUpdated())
165 self.normalSettingsPanel = normalSettingsPanel(self.leftPane, lambda : self.scene.sceneUpdated())
167 self.leftSizer = wx.BoxSizer(wx.VERTICAL)
168 self.leftSizer.Add(self.simpleSettingsPanel)
169 self.leftSizer.Add(self.normalSettingsPanel, 1, wx.EXPAND)
170 self.leftPane.SetSizer(self.leftSizer)
173 self.scene = sceneView.SceneView(self.rightPane)
175 #Main sizer, to position the preview window, buttons and tab control
176 sizer = wx.BoxSizer()
177 self.rightPane.SetSizer(sizer)
178 sizer.Add(self.scene, 1, flag=wx.EXPAND)
181 sizer = wx.BoxSizer(wx.VERTICAL)
183 sizer.Add(self.splitter, 1, wx.EXPAND)
187 self.updateProfileToControls()
189 self.SetBackgroundColour(self.normalSettingsPanel.GetBackgroundColour())
191 self.simpleSettingsPanel.Show(False)
192 self.normalSettingsPanel.Show(False)
194 # Set default window size & position
195 self.SetSize((wx.Display().GetClientArea().GetWidth()/2,wx.Display().GetClientArea().GetHeight()/2))
198 # Restore the window position, size & state from the preferences file
200 if profile.getPreference('window_maximized') == 'True':
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))
212 self.normalSashPos = int(profile.getPreference('window_normal_sash'))
214 self.normalSashPos = 0
216 if self.normalSashPos < self.normalSettingsPanel.printPanel.GetBestSize()[0] + 5:
217 self.normalSashPos = self.normalSettingsPanel.printPanel.GetBestSize()[0] + 5
219 self.splitter.SplitVertically(self.leftPane, self.rightPane, self.normalSashPos)
221 if wx.Display.GetFromPoint(self.GetPosition()) < 0:
223 if wx.Display.GetFromPoint((self.GetPositionTuple()[0] + self.GetSizeTuple()[1], self.GetPositionTuple()[1] + self.GetSizeTuple()[1])) < 0:
225 if wx.Display.GetFromPoint(self.GetPosition()) < 0:
226 self.SetSize((800,600))
229 self.updateSliceMode()
231 def updateSliceMode(self):
232 isSimple = profile.getPreference('startMode') == 'Simple'
234 self.normalSettingsPanel.Show(not isSimple)
235 self.simpleSettingsPanel.Show(isSimple)
236 self.leftPane.Layout()
238 for i in self.normalModeOnlyItems:
239 i.Enable(not isSimple)
240 self.switchToQuickprintMenuItem.Enable(not isSimple)
241 self.switchToNormalMenuItem.Enable(isSimple)
243 # Set splitter sash position & size
245 # Save normal mode sash
246 self.normalSashPos = self.splitter.GetSashPosition()
248 # Change location of sash to width of quick mode pane
249 (width, height) = self.simpleSettingsPanel.GetSizer().GetSize()
250 self.splitter.SetSashPosition(width, True)
253 self.splitter.SetSashSize(0)
255 self.splitter.SetSashPosition(self.normalSashPos, True)
257 self.splitter.SetSashSize(4)
258 self.scene.updateProfileToControls()
260 def OnPreferences(self, e):
261 prefDialog = preferencesDialog.preferencesDialog(self)
265 def OnDropFiles(self, files):
267 profile.setPluginConfig([])
268 self.updateProfileToControls()
269 self.scene.loadScene(files)
271 def OnModelMRU(self, e):
272 fileNum = e.GetId() - self.ID_MRU_MODEL1
273 path = self.modelFileHistory.GetHistoryFile(fileNum)
275 self.modelFileHistory.AddFileToHistory(path) # move up the list
276 self.config.SetPath("/ModelMRU")
277 self.modelFileHistory.Save(self.config)
280 profile.putPreference('lastFile', path)
282 self.scene.loadScene(filelist)
284 def addToModelMRU(self, file):
285 self.modelFileHistory.AddFileToHistory(file)
286 self.config.SetPath("/ModelMRU")
287 self.modelFileHistory.Save(self.config)
290 def OnProfileMRU(self, e):
291 fileNum = e.GetId() - self.ID_MRU_PROFILE1
292 path = self.profileFileHistory.GetHistoryFile(fileNum)
294 self.profileFileHistory.AddFileToHistory(path) # move up the list
295 self.config.SetPath("/ProfileMRU")
296 self.profileFileHistory.Save(self.config)
299 profile.loadProfile(path)
300 self.updateProfileToControls()
302 def addToProfileMRU(self, file):
303 self.profileFileHistory.AddFileToHistory(file)
304 self.config.SetPath("/ProfileMRU")
305 self.profileFileHistory.Save(self.config)
308 def updateProfileToControls(self):
309 self.scene.updateProfileToControls()
310 self.normalSettingsPanel.updateProfileToControls()
311 self.simpleSettingsPanel.updateProfileToControls()
313 def OnLoadProfile(self, e):
314 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)
315 dlg.SetWildcard("ini files (*.ini)|*.ini")
316 if dlg.ShowModal() == wx.ID_OK:
317 profileFile = dlg.GetPath()
318 profile.loadProfile(profileFile)
319 self.updateProfileToControls()
321 # Update the Profile MRU
322 self.addToProfileMRU(profileFile)
325 def OnLoadProfileFromGcode(self, e):
326 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)
327 dlg.SetWildcard("gcode files (*.gcode)|*.gcode;*.g")
328 if dlg.ShowModal() == wx.ID_OK:
329 gcodeFile = dlg.GetPath()
330 f = open(gcodeFile, 'r')
333 if line.startswith(';CURA_PROFILE_STRING:'):
334 profile.loadProfileFromString(line[line.find(':')+1:].strip())
337 self.updateProfileToControls()
339 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)
342 def OnSaveProfile(self, e):
343 dlg=wx.FileDialog(self, "Select profile file to save", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE)
344 dlg.SetWildcard("ini files (*.ini)|*.ini")
345 if dlg.ShowModal() == wx.ID_OK:
346 profileFile = dlg.GetPath()
347 profile.saveProfile(profileFile)
350 def OnResetProfile(self, e):
351 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)
352 result = dlg.ShowModal() == wx.ID_YES
355 profile.resetProfile()
356 self.updateProfileToControls()
358 def OnBatchRun(self, e):
359 br = batchRun.batchRunWindow(self)
363 def OnSimpleSwitch(self, e):
364 profile.putPreference('startMode', 'Simple')
365 self.updateSliceMode()
367 def OnNormalSwitch(self, e):
368 profile.putPreference('startMode', 'Normal')
369 self.updateSliceMode()
371 def OnDefaultMarlinFirmware(self, e):
372 firmwareInstall.InstallFirmware()
374 def OnCustomFirmware(self, e):
375 if profile.getPreference('machine_type') == 'ultimaker':
376 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)
377 dlg=wx.FileDialog(self, "Open firmware to upload", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
378 dlg.SetWildcard("HEX file (*.hex)|*.hex;*.HEX")
379 if dlg.ShowModal() == wx.ID_OK:
380 filename = dlg.GetPath()
381 if not(os.path.exists(filename)):
383 #For some reason my Ubuntu 10.10 crashes here.
384 firmwareInstall.InstallFirmware(filename)
386 def OnFirstRunWizard(self, e):
387 configWizard.configWizard()
388 self.updateProfileToControls()
390 def OnBedLevelWizard(self, e):
391 configWizard.bedLevelWizard()
393 def OnHeadOffsetWizard(self, e):
394 configWizard.headOffsetWizard()
396 def OnExpertOpen(self, e):
397 ecw = expertConfig.expertConfigWindow(lambda : self.scene.sceneUpdated())
401 def OnMinecraftImport(self, e):
402 mi = minecraftImport.minecraftImportWindow(self)
406 def OnSuperformula(self, e):
407 sf = superformula.superformulaWindow(self)
408 #sf = superformula.superformulaEvolver(self)
412 def OnCheckForUpdate(self, e):
413 newVersion = version.checkForNewerVersion()
414 if newVersion is not None:
415 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:
416 webbrowser.open(newVersion)
418 wx.MessageBox('You are running the latest version of Cura!', 'Awesome!', wx.ICON_INFORMATION)
420 def OnAbout(self, e):
421 info = wx.AboutDialogInfo()
423 info.SetDescription('End solution for Open Source Fused Filament Fabrication 3D printing.')
424 info.SetWebSite('http://software.ultimaker.com/')
425 info.SetCopyright('Copyright (C) David Braam')
427 This program is free software: you can redistribute it and/or modify
428 it under the terms of the GNU Affero General Public License as published by
429 the Free Software Foundation, either version 3 of the License, or
430 (at your option) any later version.
432 This program is distributed in the hope that it will be useful,
433 but WITHOUT ANY WARRANTY; without even the implied warranty of
434 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
435 GNU Affero General Public License for more details.
437 You should have received a copy of the GNU Affero General Public License
438 along with this program. If not, see <http://www.gnu.org/licenses/>.
442 def OnClose(self, e):
443 profile.saveProfile(profile.getDefaultProfilePath())
445 # Save the window position, size & state from the preferences file
446 profile.putPreference('window_maximized', self.IsMaximized())
447 if not self.IsMaximized() and not self.IsIconized():
448 (posx, posy) = self.GetPosition()
449 profile.putPreference('window_pos_x', posx)
450 profile.putPreference('window_pos_y', posy)
451 (width, height) = self.GetSize()
452 profile.putPreference('window_width', width)
453 profile.putPreference('window_height', height)
455 # Save normal sash position. If in normal mode (!simple mode), get last position of sash before saving it...
456 isSimple = profile.getPreference('startMode') == 'Simple'
458 self.normalSashPos = self.splitter.GetSashPosition()
459 profile.putPreference('window_normal_sash', self.normalSashPos)
461 #HACK: Set the paint function of the glCanvas to nothing so it won't keep refreshing. Which keeps wxWidgets from quiting.
463 self.scene.OnPaint = lambda e : e
464 self.scene._slicer.cleanup()
470 class normalSettingsPanel(configBase.configPanelBase):
471 "Main user interface window"
472 def __init__(self, parent, callback = None):
473 super(normalSettingsPanel, self).__init__(parent, callback)
476 self.nb = wx.Notebook(self)
477 self.SetSizer(wx.BoxSizer(wx.HORIZONTAL))
478 self.GetSizer().Add(self.nb, 1, wx.EXPAND)
480 (left, right, self.printPanel) = self.CreateDynamicConfigTab(self.nb, 'Basic')
481 self._addSettingsToPanels('basic', left, right)
482 self.SizeLabelWidths(left, right)
484 (left, right, self.advancedPanel) = self.CreateDynamicConfigTab(self.nb, 'Advanced')
485 self._addSettingsToPanels('advanced', left, right)
486 self.SizeLabelWidths(left, right)
489 self.pluginPanel = pluginPanel.pluginPanel(self.nb, callback)
490 if len(self.pluginPanel.pluginList) > 0:
491 self.nb.AddPage(self.pluginPanel, "Plugins")
493 self.pluginPanel.Show(False)
496 self.alterationPanel = alterationPanel.alterationPanel(self.nb, callback)
497 self.nb.AddPage(self.alterationPanel, "Start/End-GCode")
499 self.Bind(wx.EVT_SIZE, self.OnSize)
501 self.nb.SetSize(self.GetSize())
502 self.UpdateSize(self.printPanel)
503 self.UpdateSize(self.advancedPanel)
505 def _addSettingsToPanels(self, category, left, right):
506 count = len(profile.getSubCategoriesFor(category)) + len(profile.getSettingsForCategory(category))
510 for title in profile.getSubCategoriesFor(category):
511 n += 1 + len(profile.getSettingsForCategory(category, title))
514 configBase.TitleRow(p, title)
515 for s in profile.getSettingsForCategory(category, title):
516 if s.checkConditions():
517 configBase.SettingRow(p, s.getName())
519 def SizeLabelWidths(self, left, right):
520 leftWidth = self.getLabelColumnWidth(left)
521 rightWidth = self.getLabelColumnWidth(right)
522 maxWidth = max(leftWidth, rightWidth)
523 self.setLabelColumnWidth(left, maxWidth)
524 self.setLabelColumnWidth(right, maxWidth)
527 # Make the size of the Notebook control the same size as this control
528 self.nb.SetSize(self.GetSize())
530 # Propegate the OnSize() event (just in case)
533 # Perform out resize magic
534 self.UpdateSize(self.printPanel)
535 self.UpdateSize(self.advancedPanel)
537 def UpdateSize(self, configPanel):
538 sizer = configPanel.GetSizer()
542 # if width(col1) < best_width(col1) || width(col2) < best_width(col2):
545 # if width(col1) > (best_width(col1) + best_width(col1)):
546 # switch to horizontal
549 col1 = configPanel.leftPanel
550 colSize1 = col1.GetSize()
551 colBestSize1 = col1.GetBestSize()
552 col2 = configPanel.rightPanel
553 colSize2 = col2.GetSize()
554 colBestSize2 = col2.GetBestSize()
556 orientation = sizer.GetOrientation()
558 if orientation == wx.HORIZONTAL:
559 if (colSize1[0] <= colBestSize1[0]) or (colSize2[0] <= colBestSize2[0]):
561 sizer = wx.BoxSizer(wx.VERTICAL)
562 sizer.Add(configPanel.leftPanel, flag=wx.EXPAND)
563 sizer.Add(configPanel.rightPanel, flag=wx.EXPAND)
564 configPanel.SetSizer(sizer)
570 if max(colSize1[0], colSize2[0]) > (colBestSize1[0] + colBestSize2[0]):
572 sizer = wx.BoxSizer(wx.HORIZONTAL)
573 sizer.Add(configPanel.leftPanel, proportion=1, border=35, flag=wx.EXPAND)
574 sizer.Add(configPanel.rightPanel, proportion=1, flag=wx.EXPAND)
575 configPanel.SetSizer(sizer)
581 def updateProfileToControls(self):
582 super(normalSettingsPanel, self).updateProfileToControls()
583 self.alterationPanel.updateProfileToControls()
584 self.pluginPanel.updateProfileToControls()