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.util import dropTarget
18 #from Cura.gui.tools import batchRun
19 from Cura.gui.tools import pidDebugger
20 from Cura.gui.tools import minecraftImport
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.getMachineSetting('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()
110 i = toolsMenu.Append(-1, _("Switch to quickprint..."))
111 self.switchToQuickprintMenuItem = i
112 self.Bind(wx.EVT_MENU, self.OnSimpleSwitch, i)
114 i = toolsMenu.Append(-1, _("Switch to full settings..."))
115 self.switchToNormalMenuItem = i
116 self.Bind(wx.EVT_MENU, self.OnNormalSwitch, i)
118 #toolsMenu.AppendSeparator()
119 #i = toolsMenu.Append(-1, 'Batch run...')
120 #self.Bind(wx.EVT_MENU, self.OnBatchRun, i)
121 #self.normalModeOnlyItems.append(i)
123 if minecraftImport.hasMinecraft():
124 i = toolsMenu.Append(-1, _("Minecraft import..."))
125 self.Bind(wx.EVT_MENU, self.OnMinecraftImport, i)
127 if version.isDevVersion():
128 i = toolsMenu.Append(-1, _("PID Debugger..."))
129 self.Bind(wx.EVT_MENU, self.OnPIDDebugger, i)
131 i = toolsMenu.Append(-1, _("Copy profile to clipboard"))
132 self.Bind(wx.EVT_MENU, self.onCopyProfileClipboard,i)
133 self.menubar.Append(toolsMenu, _("Tools"))
135 expertMenu = wx.Menu()
136 i = expertMenu.Append(-1, _("Open expert settings..."))
137 self.normalModeOnlyItems.append(i)
138 self.Bind(wx.EVT_MENU, self.OnExpertOpen, i)
139 expertMenu.AppendSeparator()
140 if firmwareInstall.getDefaultFirmware() is not None:
141 i = expertMenu.Append(-1, _("Install default Marlin firmware"))
142 self.Bind(wx.EVT_MENU, self.OnDefaultMarlinFirmware, i)
143 i = expertMenu.Append(-1, _("Install custom firmware"))
144 self.Bind(wx.EVT_MENU, self.OnCustomFirmware, i)
145 expertMenu.AppendSeparator()
146 i = expertMenu.Append(-1, _("Run first run wizard..."))
147 self.Bind(wx.EVT_MENU, self.OnFirstRunWizard, i)
148 i = expertMenu.Append(-1, _("Run bed leveling wizard..."))
149 self.Bind(wx.EVT_MENU, self.OnBedLevelWizard, i)
150 if self.extruderCount > 1:
151 i = expertMenu.Append(-1, _("Run head offset wizard..."))
152 self.Bind(wx.EVT_MENU, self.OnHeadOffsetWizard, i)
153 self.menubar.Append(expertMenu, _("Expert"))
156 i = helpMenu.Append(-1, _("Online documentation..."))
157 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('http://daid.github.com/Cura'), i)
158 i = helpMenu.Append(-1, _("Report a problem..."))
159 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i)
160 i = helpMenu.Append(-1, _("Check for update..."))
161 self.Bind(wx.EVT_MENU, self.OnCheckForUpdate, i)
162 i = helpMenu.Append(-1, _("Open YouMagine website..."))
163 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://www.youmagine.com/'), i)
164 i = helpMenu.Append(-1, _("About Cura..."))
165 self.Bind(wx.EVT_MENU, self.OnAbout, i)
166 self.menubar.Append(helpMenu, _("Help"))
167 self.SetMenuBar(self.menubar)
169 self.splitter = wx.SplitterWindow(self, style = wx.SP_3D | wx.SP_LIVE_UPDATE)
170 self.leftPane = wx.Panel(self.splitter, style=wx.BORDER_NONE)
171 self.rightPane = wx.Panel(self.splitter, style=wx.BORDER_NONE)
172 self.splitter.Bind(wx.EVT_SPLITTER_DCLICK, lambda evt: evt.Veto())
175 self.simpleSettingsPanel = simpleMode.simpleModePanel(self.leftPane, lambda : self.scene.sceneUpdated())
176 self.normalSettingsPanel = normalSettingsPanel(self.leftPane, lambda : self.scene.sceneUpdated())
178 self.leftSizer = wx.BoxSizer(wx.VERTICAL)
179 self.leftSizer.Add(self.simpleSettingsPanel, 1)
180 self.leftSizer.Add(self.normalSettingsPanel, 1, wx.EXPAND)
181 self.leftPane.SetSizer(self.leftSizer)
184 self.scene = sceneView.SceneView(self.rightPane)
186 #Main sizer, to position the preview window, buttons and tab control
187 sizer = wx.BoxSizer()
188 self.rightPane.SetSizer(sizer)
189 sizer.Add(self.scene, 1, flag=wx.EXPAND)
192 sizer = wx.BoxSizer(wx.VERTICAL)
194 sizer.Add(self.splitter, 1, wx.EXPAND)
198 self.updateProfileToAllControls()
200 self.SetBackgroundColour(self.normalSettingsPanel.GetBackgroundColour())
202 self.simpleSettingsPanel.Show(False)
203 self.normalSettingsPanel.Show(False)
205 # Set default window size & position
206 self.SetSize((wx.Display().GetClientArea().GetWidth()/2,wx.Display().GetClientArea().GetHeight()/2))
209 #Timer set; used to check if profile is on the clipboard
210 self.timer = wx.Timer(self)
211 self.Bind(wx.EVT_TIMER, self.onTimer)
212 self.timer.Start(1000)
213 self.lastTriedClipboard = profile.getProfileString()
215 # Restore the window position, size & state from the preferences file
217 if profile.getPreference('window_maximized') == 'True':
220 posx = int(profile.getPreference('window_pos_x'))
221 posy = int(profile.getPreference('window_pos_y'))
222 width = int(profile.getPreference('window_width'))
223 height = int(profile.getPreference('window_height'))
224 if posx > 0 or posy > 0:
225 self.SetPosition((posx,posy))
226 if width > 0 and height > 0:
227 self.SetSize((width,height))
229 self.normalSashPos = int(profile.getPreference('window_normal_sash'))
231 self.normalSashPos = 0
233 if self.normalSashPos < self.normalSettingsPanel.printPanel.GetBestSize()[0] + 5:
234 self.normalSashPos = self.normalSettingsPanel.printPanel.GetBestSize()[0] + 5
236 self.splitter.SplitVertically(self.leftPane, self.rightPane, self.normalSashPos)
238 if wx.Display.GetFromPoint(self.GetPosition()) < 0:
240 if wx.Display.GetFromPoint((self.GetPositionTuple()[0] + self.GetSizeTuple()[1], self.GetPositionTuple()[1] + self.GetSizeTuple()[1])) < 0:
242 if wx.Display.GetFromPoint(self.GetPosition()) < 0:
243 self.SetSize((800,600))
246 self.updateSliceMode()
248 def onTimer(self, e):
249 #Check if there is something in the clipboard
252 if not wx.TheClipboard.IsOpened():
253 wx.TheClipboard.Open()
254 do = wx.TextDataObject()
255 if wx.TheClipboard.GetData(do):
256 profileString = do.GetText()
257 wx.TheClipboard.Close()
259 if "CURA_PROFILE_STRING:" in profileString:
260 #print "Found correct syntax on clipboard"
261 profileString = profileString.replace("\n","")
262 profileString = profileString.replace("CURA_PROFILE_STRING:", "")
263 if profileString != self.lastTriedClipboard:
264 self.lastTriedClipboard = profileString
265 profile.setProfileFromString(profileString)
266 print "changed profile"
267 self.updateProfileToAllControls()
269 print "Unable to read from clipboard"
272 def updateSliceMode(self):
273 isSimple = profile.getPreference('startMode') == 'Simple'
275 self.normalSettingsPanel.Show(not isSimple)
276 self.simpleSettingsPanel.Show(isSimple)
277 self.leftPane.Layout()
279 for i in self.normalModeOnlyItems:
280 i.Enable(not isSimple)
281 self.switchToQuickprintMenuItem.Enable(not isSimple)
282 self.switchToNormalMenuItem.Enable(isSimple)
284 # Set splitter sash position & size
286 # Save normal mode sash
287 self.normalSashPos = self.splitter.GetSashPosition()
289 # Change location of sash to width of quick mode pane
290 (width, height) = self.simpleSettingsPanel.GetSizer().GetSize()
291 self.splitter.SetSashPosition(width, True)
294 self.splitter.SetSashSize(0)
296 self.splitter.SetSashPosition(self.normalSashPos, True)
298 self.splitter.SetSashSize(4)
299 self.scene.updateProfileToControls()
301 def OnPreferences(self, e):
302 prefDialog = preferencesDialog.preferencesDialog(self)
306 def OnDropFiles(self, files):
308 profile.setPluginConfig([])
309 self.updateProfileToAllControls()
310 self.scene.loadScene(files)
312 def OnModelMRU(self, e):
313 fileNum = e.GetId() - self.ID_MRU_MODEL1
314 path = self.modelFileHistory.GetHistoryFile(fileNum)
316 self.modelFileHistory.AddFileToHistory(path) # move up the list
317 self.config.SetPath("/ModelMRU")
318 self.modelFileHistory.Save(self.config)
321 profile.putPreference('lastFile', path)
323 self.scene.loadScene(filelist)
325 def addToModelMRU(self, file):
326 self.modelFileHistory.AddFileToHistory(file)
327 self.config.SetPath("/ModelMRU")
328 self.modelFileHistory.Save(self.config)
331 def OnProfileMRU(self, e):
332 fileNum = e.GetId() - self.ID_MRU_PROFILE1
333 path = self.profileFileHistory.GetHistoryFile(fileNum)
335 self.profileFileHistory.AddFileToHistory(path) # move up the list
336 self.config.SetPath("/ProfileMRU")
337 self.profileFileHistory.Save(self.config)
340 profile.loadProfile(path)
341 self.updateProfileToAllControls()
343 def addToProfileMRU(self, file):
344 self.profileFileHistory.AddFileToHistory(file)
345 self.config.SetPath("/ProfileMRU")
346 self.profileFileHistory.Save(self.config)
349 def updateProfileToAllControls(self):
350 self.scene.updateProfileToControls()
351 self.normalSettingsPanel.updateProfileToControls()
352 self.simpleSettingsPanel.updateProfileToControls()
354 def OnLoadProfile(self, e):
355 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)
356 dlg.SetWildcard("ini files (*.ini)|*.ini")
357 if dlg.ShowModal() == wx.ID_OK:
358 profileFile = dlg.GetPath()
359 profile.loadProfile(profileFile)
360 self.updateProfileToAllControls()
362 # Update the Profile MRU
363 self.addToProfileMRU(profileFile)
366 def OnLoadProfileFromGcode(self, e):
367 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)
368 dlg.SetWildcard("gcode files (*.gcode)|*.gcode;*.g")
369 if dlg.ShowModal() == wx.ID_OK:
370 gcodeFile = dlg.GetPath()
371 f = open(gcodeFile, 'r')
374 if line.startswith(';CURA_PROFILE_STRING:'):
375 profile.setProfileFromString(line[line.find(':')+1:].strip())
378 self.updateProfileToAllControls()
380 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)
383 def OnSaveProfile(self, e):
384 dlg=wx.FileDialog(self, _("Select profile file to save"), os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE)
385 dlg.SetWildcard("ini files (*.ini)|*.ini")
386 if dlg.ShowModal() == wx.ID_OK:
387 profileFile = dlg.GetPath()
388 profile.saveProfile(profileFile)
391 def OnResetProfile(self, e):
392 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)
393 result = dlg.ShowModal() == wx.ID_YES
396 profile.resetProfile()
397 self.updateProfileToAllControls()
399 def OnSimpleSwitch(self, e):
400 profile.putPreference('startMode', 'Simple')
401 self.updateSliceMode()
403 def OnNormalSwitch(self, e):
404 profile.putPreference('startMode', 'Normal')
405 self.updateSliceMode()
407 def OnDefaultMarlinFirmware(self, e):
408 firmwareInstall.InstallFirmware()
410 def OnCustomFirmware(self, e):
411 if profile.getPreference('machine_type').startswith('ultimaker'):
412 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)
413 dlg=wx.FileDialog(self, _("Open firmware to upload"), os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
414 dlg.SetWildcard("HEX file (*.hex)|*.hex;*.HEX")
415 if dlg.ShowModal() == wx.ID_OK:
416 filename = dlg.GetPath()
417 if not(os.path.exists(filename)):
419 #For some reason my Ubuntu 10.10 crashes here.
420 firmwareInstall.InstallFirmware(filename)
422 def OnFirstRunWizard(self, e):
423 configWizard.configWizard()
424 self.updateProfileToAllControls()
426 def OnBedLevelWizard(self, e):
427 configWizard.bedLevelWizard()
429 def OnHeadOffsetWizard(self, e):
430 configWizard.headOffsetWizard()
432 def OnExpertOpen(self, e):
433 ecw = expertConfig.expertConfigWindow(lambda : self.scene.sceneUpdated())
437 def OnMinecraftImport(self, e):
438 mi = minecraftImport.minecraftImportWindow(self)
442 def OnPIDDebugger(self, e):
443 debugger = pidDebugger.debuggerWindow(self)
447 def onCopyProfileClipboard(self, e):
449 if not wx.TheClipboard.IsOpened():
450 wx.TheClipboard.Open()
451 clipData = wx.TextDataObject()
452 self.lastTriedClipboard = profile.getProfileString()
453 profileString = profile.insertNewlines("CURA_PROFILE_STRING:" + self.lastTriedClipboard)
454 clipData.SetText(profileString)
455 wx.TheClipboard.SetData(clipData)
456 wx.TheClipboard.Close()
458 print "Could not write to clipboard, unable to get ownership. Another program is using the clipboard."
460 def OnCheckForUpdate(self, e):
461 newVersion = version.checkForNewerVersion()
462 if newVersion is not None:
463 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:
464 webbrowser.open(newVersion)
466 wx.MessageBox(_("You are running the latest version of Cura!"), _("Awesome!"), wx.ICON_INFORMATION)
468 def OnAbout(self, e):
469 info = wx.AboutDialogInfo()
471 info.SetDescription(_("End solution for Open Source Fused Filament Fabrication 3D printing."))
472 info.SetWebSite('http://software.ultimaker.com/')
473 info.SetCopyright(_("Copyright (C) David Braam"))
475 This program is free software: you can redistribute it and/or modify
476 it under the terms of the GNU Affero General Public License as published by
477 the Free Software Foundation, either version 3 of the License, or
478 (at your option) any later version.
480 This program is distributed in the hope that it will be useful,
481 but WITHOUT ANY WARRANTY; without even the implied warranty of
482 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
483 GNU Affero General Public License for more details.
485 You should have received a copy of the GNU Affero General Public License
486 along with this program. If not, see <http://www.gnu.org/licenses/>.
490 def OnClose(self, e):
491 profile.saveProfile(profile.getDefaultProfilePath())
493 # Save the window position, size & state from the preferences file
494 profile.putPreference('window_maximized', self.IsMaximized())
495 if not self.IsMaximized() and not self.IsIconized():
496 (posx, posy) = self.GetPosition()
497 profile.putPreference('window_pos_x', posx)
498 profile.putPreference('window_pos_y', posy)
499 (width, height) = self.GetSize()
500 profile.putPreference('window_width', width)
501 profile.putPreference('window_height', height)
503 # Save normal sash position. If in normal mode (!simple mode), get last position of sash before saving it...
504 isSimple = profile.getPreference('startMode') == 'Simple'
506 self.normalSashPos = self.splitter.GetSashPosition()
507 profile.putPreference('window_normal_sash', self.normalSashPos)
509 #HACK: Set the paint function of the glCanvas to nothing so it won't keep refreshing. Which keeps wxWidgets from quiting.
511 self.scene.OnPaint = lambda e : e
512 self.scene._slicer.cleanup()
518 class normalSettingsPanel(configBase.configPanelBase):
519 "Main user interface window"
520 def __init__(self, parent, callback = None):
521 super(normalSettingsPanel, self).__init__(parent, callback)
524 self.nb = wx.Notebook(self)
525 self.SetSizer(wx.BoxSizer(wx.HORIZONTAL))
526 self.GetSizer().Add(self.nb, 1, wx.EXPAND)
528 (left, right, self.printPanel) = self.CreateDynamicConfigTab(self.nb, 'Basic')
529 self._addSettingsToPanels('basic', left, right)
530 self.SizeLabelWidths(left, right)
532 (left, right, self.advancedPanel) = self.CreateDynamicConfigTab(self.nb, 'Advanced')
533 self._addSettingsToPanels('advanced', left, right)
534 self.SizeLabelWidths(left, right)
537 self.pluginPanel = pluginPanel.pluginPanel(self.nb, callback)
538 if len(self.pluginPanel.pluginList) > 0:
539 self.nb.AddPage(self.pluginPanel, "Plugins")
541 self.pluginPanel.Show(False)
544 if profile.getMachineSetting('gcode_flavor') == 'UltiGCode':
545 self.alterationPanel = None
547 self.alterationPanel = alterationPanel.alterationPanel(self.nb, callback)
548 self.nb.AddPage(self.alterationPanel, "Start/End-GCode")
550 self.Bind(wx.EVT_SIZE, self.OnSize)
552 self.nb.SetSize(self.GetSize())
553 self.UpdateSize(self.printPanel)
554 self.UpdateSize(self.advancedPanel)
556 def _addSettingsToPanels(self, category, left, right):
557 count = len(profile.getSubCategoriesFor(category)) + len(profile.getSettingsForCategory(category))
561 for title in profile.getSubCategoriesFor(category):
562 n += 1 + len(profile.getSettingsForCategory(category, title))
565 configBase.TitleRow(p, title)
566 for s in profile.getSettingsForCategory(category, title):
567 if s.checkConditions():
568 configBase.SettingRow(p, s.getName())
570 def SizeLabelWidths(self, left, right):
571 leftWidth = self.getLabelColumnWidth(left)
572 rightWidth = self.getLabelColumnWidth(right)
573 maxWidth = max(leftWidth, rightWidth)
574 self.setLabelColumnWidth(left, maxWidth)
575 self.setLabelColumnWidth(right, maxWidth)
578 # Make the size of the Notebook control the same size as this control
579 self.nb.SetSize(self.GetSize())
581 # Propegate the OnSize() event (just in case)
584 # Perform out resize magic
585 self.UpdateSize(self.printPanel)
586 self.UpdateSize(self.advancedPanel)
588 def UpdateSize(self, configPanel):
589 sizer = configPanel.GetSizer()
593 # if width(col1) < best_width(col1) || width(col2) < best_width(col2):
596 # if width(col1) > (best_width(col1) + best_width(col1)):
597 # switch to horizontal
600 col1 = configPanel.leftPanel
601 colSize1 = col1.GetSize()
602 colBestSize1 = col1.GetBestSize()
603 col2 = configPanel.rightPanel
604 colSize2 = col2.GetSize()
605 colBestSize2 = col2.GetBestSize()
607 orientation = sizer.GetOrientation()
609 if orientation == wx.HORIZONTAL:
610 if (colSize1[0] <= colBestSize1[0]) or (colSize2[0] <= colBestSize2[0]):
612 sizer = wx.BoxSizer(wx.VERTICAL)
613 sizer.Add(configPanel.leftPanel, flag=wx.EXPAND)
614 sizer.Add(configPanel.rightPanel, flag=wx.EXPAND)
615 configPanel.SetSizer(sizer)
621 if max(colSize1[0], colSize2[0]) > (colBestSize1[0] + colBestSize2[0]):
623 sizer = wx.BoxSizer(wx.HORIZONTAL)
624 sizer.Add(configPanel.leftPanel, proportion=1, border=35, flag=wx.EXPAND)
625 sizer.Add(configPanel.rightPanel, proportion=1, flag=wx.EXPAND)
626 configPanel.SetSizer(sizer)
632 def updateProfileToControls(self):
633 super(normalSettingsPanel, self).updateProfileToControls()
634 if self.alterationPanel is not None:
635 self.alterationPanel.updateProfileToControls()
636 self.pluginPanel.updateProfileToControls()