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() + ['.g', '.gcode', '.ini']))
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)
154 i = expertMenu.Append(-1, _("Add new machine..."))
155 self.Bind(wx.EVT_MENU, self.OnAddNewMachine, i)
157 self.menubar.Append(expertMenu, _("Expert"))
160 i = helpMenu.Append(-1, _("Online documentation..."))
161 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('http://daid.github.com/Cura'), i)
162 i = helpMenu.Append(-1, _("Report a problem..."))
163 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://github.com/daid/Cura/issues'), i)
164 i = helpMenu.Append(-1, _("Check for update..."))
165 self.Bind(wx.EVT_MENU, self.OnCheckForUpdate, i)
166 i = helpMenu.Append(-1, _("Open YouMagine website..."))
167 self.Bind(wx.EVT_MENU, lambda e: webbrowser.open('https://www.youmagine.com/'), i)
168 i = helpMenu.Append(-1, _("About Cura..."))
169 self.Bind(wx.EVT_MENU, self.OnAbout, i)
170 self.menubar.Append(helpMenu, _("Help"))
171 self.SetMenuBar(self.menubar)
173 self.splitter = wx.SplitterWindow(self, style = wx.SP_3D | wx.SP_LIVE_UPDATE)
174 self.leftPane = wx.Panel(self.splitter, style=wx.BORDER_NONE)
175 self.rightPane = wx.Panel(self.splitter, style=wx.BORDER_NONE)
176 self.splitter.Bind(wx.EVT_SPLITTER_DCLICK, lambda evt: evt.Veto())
179 self.simpleSettingsPanel = simpleMode.simpleModePanel(self.leftPane, lambda : self.scene.sceneUpdated())
180 self.normalSettingsPanel = normalSettingsPanel(self.leftPane, lambda : self.scene.sceneUpdated())
182 self.leftSizer = wx.BoxSizer(wx.VERTICAL)
183 self.leftSizer.Add(self.simpleSettingsPanel, 1)
184 self.leftSizer.Add(self.normalSettingsPanel, 1, wx.EXPAND)
185 self.leftPane.SetSizer(self.leftSizer)
188 self.scene = sceneView.SceneView(self.rightPane)
190 #Main sizer, to position the preview window, buttons and tab control
191 sizer = wx.BoxSizer()
192 self.rightPane.SetSizer(sizer)
193 sizer.Add(self.scene, 1, flag=wx.EXPAND)
196 sizer = wx.BoxSizer(wx.VERTICAL)
198 sizer.Add(self.splitter, 1, wx.EXPAND)
202 self.updateProfileToAllControls()
204 self.SetBackgroundColour(self.normalSettingsPanel.GetBackgroundColour())
206 self.simpleSettingsPanel.Show(False)
207 self.normalSettingsPanel.Show(False)
209 # Set default window size & position
210 self.SetSize((wx.Display().GetClientArea().GetWidth()/2,wx.Display().GetClientArea().GetHeight()/2))
213 #Timer set; used to check if profile is on the clipboard
214 self.timer = wx.Timer(self)
215 self.Bind(wx.EVT_TIMER, self.onTimer)
216 self.timer.Start(1000)
217 self.lastTriedClipboard = profile.getProfileString()
219 # Restore the window position, size & state from the preferences file
221 if profile.getPreference('window_maximized') == 'True':
224 posx = int(profile.getPreference('window_pos_x'))
225 posy = int(profile.getPreference('window_pos_y'))
226 width = int(profile.getPreference('window_width'))
227 height = int(profile.getPreference('window_height'))
228 if posx > 0 or posy > 0:
229 self.SetPosition((posx,posy))
230 if width > 0 and height > 0:
231 self.SetSize((width,height))
233 self.normalSashPos = int(profile.getPreference('window_normal_sash'))
235 self.normalSashPos = 0
237 if self.normalSashPos < self.normalSettingsPanel.printPanel.GetBestSize()[0] + 5:
238 self.normalSashPos = self.normalSettingsPanel.printPanel.GetBestSize()[0] + 5
240 self.splitter.SplitVertically(self.leftPane, self.rightPane, self.normalSashPos)
242 if wx.Display.GetFromPoint(self.GetPosition()) < 0:
244 if wx.Display.GetFromPoint((self.GetPositionTuple()[0] + self.GetSizeTuple()[1], self.GetPositionTuple()[1] + self.GetSizeTuple()[1])) < 0:
246 if wx.Display.GetFromPoint(self.GetPosition()) < 0:
247 self.SetSize((800,600))
250 self.updateSliceMode()
252 def onTimer(self, e):
253 #Check if there is something in the clipboard
256 if not wx.TheClipboard.IsOpened():
257 wx.TheClipboard.Open()
258 do = wx.TextDataObject()
259 if wx.TheClipboard.GetData(do):
260 profileString = do.GetText()
261 wx.TheClipboard.Close()
263 if "CURA_PROFILE_STRING:" in profileString:
264 #print "Found correct syntax on clipboard"
265 profileString = profileString.replace("\n","")
266 profileString = profileString.replace("CURA_PROFILE_STRING:", "")
267 if profileString != self.lastTriedClipboard:
268 self.lastTriedClipboard = profileString
269 profile.setProfileFromString(profileString)
270 print "changed profile"
271 self.updateProfileToAllControls()
273 print "Unable to read from clipboard"
276 def updateSliceMode(self):
277 isSimple = profile.getPreference('startMode') == 'Simple'
279 self.normalSettingsPanel.Show(not isSimple)
280 self.simpleSettingsPanel.Show(isSimple)
281 self.leftPane.Layout()
283 for i in self.normalModeOnlyItems:
284 i.Enable(not isSimple)
285 self.switchToQuickprintMenuItem.Enable(not isSimple)
286 self.switchToNormalMenuItem.Enable(isSimple)
288 # Set splitter sash position & size
290 # Save normal mode sash
291 self.normalSashPos = self.splitter.GetSashPosition()
293 # Change location of sash to width of quick mode pane
294 (width, height) = self.simpleSettingsPanel.GetSizer().GetSize()
295 self.splitter.SetSashPosition(width, True)
298 self.splitter.SetSashSize(0)
300 self.splitter.SetSashPosition(self.normalSashPos, True)
302 self.splitter.SetSashSize(4)
303 self.scene.updateProfileToControls()
305 def OnPreferences(self, e):
306 prefDialog = preferencesDialog.preferencesDialog(self)
310 def OnDropFiles(self, files):
312 profile.setPluginConfig([])
313 self.updateProfileToAllControls()
314 self.scene.loadFiles(files)
316 def OnModelMRU(self, e):
317 fileNum = e.GetId() - self.ID_MRU_MODEL1
318 path = self.modelFileHistory.GetHistoryFile(fileNum)
320 self.modelFileHistory.AddFileToHistory(path) # move up the list
321 self.config.SetPath("/ModelMRU")
322 self.modelFileHistory.Save(self.config)
325 profile.putPreference('lastFile', path)
327 self.scene.loadFiles(filelist)
329 def addToModelMRU(self, file):
330 self.modelFileHistory.AddFileToHistory(file)
331 self.config.SetPath("/ModelMRU")
332 self.modelFileHistory.Save(self.config)
335 def OnProfileMRU(self, e):
336 fileNum = e.GetId() - self.ID_MRU_PROFILE1
337 path = self.profileFileHistory.GetHistoryFile(fileNum)
339 self.profileFileHistory.AddFileToHistory(path) # move up the list
340 self.config.SetPath("/ProfileMRU")
341 self.profileFileHistory.Save(self.config)
344 profile.loadProfile(path)
345 self.updateProfileToAllControls()
347 def addToProfileMRU(self, file):
348 self.profileFileHistory.AddFileToHistory(file)
349 self.config.SetPath("/ProfileMRU")
350 self.profileFileHistory.Save(self.config)
353 def updateProfileToAllControls(self):
354 self.scene.updateProfileToControls()
355 self.normalSettingsPanel.updateProfileToControls()
356 self.simpleSettingsPanel.updateProfileToControls()
358 def OnLoadProfile(self, e):
359 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)
360 dlg.SetWildcard("ini files (*.ini)|*.ini")
361 if dlg.ShowModal() == wx.ID_OK:
362 profileFile = dlg.GetPath()
363 profile.loadProfile(profileFile)
364 self.updateProfileToAllControls()
366 # Update the Profile MRU
367 self.addToProfileMRU(profileFile)
370 def OnLoadProfileFromGcode(self, e):
371 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)
372 dlg.SetWildcard("gcode files (*.gcode)|*.gcode;*.g")
373 if dlg.ShowModal() == wx.ID_OK:
374 gcodeFile = dlg.GetPath()
375 f = open(gcodeFile, 'r')
378 if line.startswith(';CURA_PROFILE_STRING:'):
379 profile.setProfileFromString(line[line.find(':')+1:].strip())
382 self.updateProfileToAllControls()
384 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)
387 def OnSaveProfile(self, e):
388 dlg=wx.FileDialog(self, _("Select profile file to save"), os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_SAVE)
389 dlg.SetWildcard("ini files (*.ini)|*.ini")
390 if dlg.ShowModal() == wx.ID_OK:
391 profileFile = dlg.GetPath()
392 profile.saveProfile(profileFile)
395 def OnResetProfile(self, e):
396 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)
397 result = dlg.ShowModal() == wx.ID_YES
400 profile.resetProfile()
401 self.updateProfileToAllControls()
403 def OnSimpleSwitch(self, e):
404 profile.putPreference('startMode', 'Simple')
405 self.updateSliceMode()
407 def OnNormalSwitch(self, e):
408 profile.putPreference('startMode', 'Normal')
409 self.updateSliceMode()
411 def OnDefaultMarlinFirmware(self, e):
412 firmwareInstall.InstallFirmware()
414 def OnCustomFirmware(self, e):
415 if profile.getMachineSetting('machine_type').startswith('ultimaker'):
416 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)
417 dlg=wx.FileDialog(self, _("Open firmware to upload"), os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
418 dlg.SetWildcard("HEX file (*.hex)|*.hex;*.HEX")
419 if dlg.ShowModal() == wx.ID_OK:
420 filename = dlg.GetPath()
421 if not(os.path.exists(filename)):
423 #For some reason my Ubuntu 10.10 crashes here.
424 firmwareInstall.InstallFirmware(filename)
426 def OnFirstRunWizard(self, e):
428 configWizard.configWizard()
430 self.updateProfileToAllControls()
432 def OnAddNewMachine(self, e):
435 while profile.getMachineSetting('machine_name', n) != '':
437 profile.setActiveMachine(n)
438 configWizard.configWizard(True)
440 self.updateProfileToAllControls()
442 def OnBedLevelWizard(self, e):
443 configWizard.bedLevelWizard()
445 def OnHeadOffsetWizard(self, e):
446 configWizard.headOffsetWizard()
448 def OnExpertOpen(self, e):
449 ecw = expertConfig.expertConfigWindow(lambda : self.scene.sceneUpdated())
453 def OnMinecraftImport(self, e):
454 mi = minecraftImport.minecraftImportWindow(self)
458 def OnPIDDebugger(self, e):
459 debugger = pidDebugger.debuggerWindow(self)
463 def onCopyProfileClipboard(self, e):
465 if not wx.TheClipboard.IsOpened():
466 wx.TheClipboard.Open()
467 clipData = wx.TextDataObject()
468 self.lastTriedClipboard = profile.getProfileString()
469 profileString = profile.insertNewlines("CURA_PROFILE_STRING:" + self.lastTriedClipboard)
470 clipData.SetText(profileString)
471 wx.TheClipboard.SetData(clipData)
472 wx.TheClipboard.Close()
474 print "Could not write to clipboard, unable to get ownership. Another program is using the clipboard."
476 def OnCheckForUpdate(self, e):
477 newVersion = version.checkForNewerVersion()
478 if newVersion is not None:
479 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:
480 webbrowser.open(newVersion)
482 wx.MessageBox(_("You are running the latest version of Cura!"), _("Awesome!"), wx.ICON_INFORMATION)
484 def OnAbout(self, e):
485 info = wx.AboutDialogInfo()
487 info.SetDescription(_("End solution for Open Source Fused Filament Fabrication 3D printing."))
488 info.SetWebSite('http://software.ultimaker.com/')
489 info.SetCopyright(_("Copyright (C) David Braam"))
491 This program is free software: you can redistribute it and/or modify
492 it under the terms of the GNU Affero General Public License as published by
493 the Free Software Foundation, either version 3 of the License, or
494 (at your option) any later version.
496 This program is distributed in the hope that it will be useful,
497 but WITHOUT ANY WARRANTY; without even the implied warranty of
498 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
499 GNU Affero General Public License for more details.
501 You should have received a copy of the GNU Affero General Public License
502 along with this program. If not, see <http://www.gnu.org/licenses/>.
506 def OnClose(self, e):
507 profile.saveProfile(profile.getDefaultProfilePath())
509 # Save the window position, size & state from the preferences file
510 profile.putPreference('window_maximized', self.IsMaximized())
511 if not self.IsMaximized() and not self.IsIconized():
512 (posx, posy) = self.GetPosition()
513 profile.putPreference('window_pos_x', posx)
514 profile.putPreference('window_pos_y', posy)
515 (width, height) = self.GetSize()
516 profile.putPreference('window_width', width)
517 profile.putPreference('window_height', height)
519 # Save normal sash position. If in normal mode (!simple mode), get last position of sash before saving it...
520 isSimple = profile.getPreference('startMode') == 'Simple'
522 self.normalSashPos = self.splitter.GetSashPosition()
523 profile.putPreference('window_normal_sash', self.normalSashPos)
525 #HACK: Set the paint function of the glCanvas to nothing so it won't keep refreshing. Which keeps wxWidgets from quiting.
527 self.scene.OnPaint = lambda e : e
528 self.scene._slicer.cleanup()
534 class normalSettingsPanel(configBase.configPanelBase):
535 "Main user interface window"
536 def __init__(self, parent, callback = None):
537 super(normalSettingsPanel, self).__init__(parent, callback)
540 self.nb = wx.Notebook(self)
541 self.SetSizer(wx.BoxSizer(wx.HORIZONTAL))
542 self.GetSizer().Add(self.nb, 1, wx.EXPAND)
544 (left, right, self.printPanel) = self.CreateDynamicConfigTab(self.nb, 'Basic')
545 self._addSettingsToPanels('basic', left, right)
546 self.SizeLabelWidths(left, right)
548 (left, right, self.advancedPanel) = self.CreateDynamicConfigTab(self.nb, 'Advanced')
549 self._addSettingsToPanels('advanced', left, right)
550 self.SizeLabelWidths(left, right)
553 self.pluginPanel = pluginPanel.pluginPanel(self.nb, callback)
554 if len(self.pluginPanel.pluginList) > 0:
555 self.nb.AddPage(self.pluginPanel, "Plugins")
557 self.pluginPanel.Show(False)
560 if profile.getMachineSetting('gcode_flavor') == 'UltiGCode':
561 self.alterationPanel = None
563 self.alterationPanel = alterationPanel.alterationPanel(self.nb, callback)
564 self.nb.AddPage(self.alterationPanel, "Start/End-GCode")
566 self.Bind(wx.EVT_SIZE, self.OnSize)
568 self.nb.SetSize(self.GetSize())
569 self.UpdateSize(self.printPanel)
570 self.UpdateSize(self.advancedPanel)
572 def _addSettingsToPanels(self, category, left, right):
573 count = len(profile.getSubCategoriesFor(category)) + len(profile.getSettingsForCategory(category))
577 for title in profile.getSubCategoriesFor(category):
578 n += 1 + len(profile.getSettingsForCategory(category, title))
581 configBase.TitleRow(p, title)
582 for s in profile.getSettingsForCategory(category, title):
583 if s.checkConditions():
584 configBase.SettingRow(p, s.getName())
586 def SizeLabelWidths(self, left, right):
587 leftWidth = self.getLabelColumnWidth(left)
588 rightWidth = self.getLabelColumnWidth(right)
589 maxWidth = max(leftWidth, rightWidth)
590 self.setLabelColumnWidth(left, maxWidth)
591 self.setLabelColumnWidth(right, maxWidth)
594 # Make the size of the Notebook control the same size as this control
595 self.nb.SetSize(self.GetSize())
597 # Propegate the OnSize() event (just in case)
600 # Perform out resize magic
601 self.UpdateSize(self.printPanel)
602 self.UpdateSize(self.advancedPanel)
604 def UpdateSize(self, configPanel):
605 sizer = configPanel.GetSizer()
609 # if width(col1) < best_width(col1) || width(col2) < best_width(col2):
612 # if width(col1) > (best_width(col1) + best_width(col1)):
613 # switch to horizontal
616 col1 = configPanel.leftPanel
617 colSize1 = col1.GetSize()
618 colBestSize1 = col1.GetBestSize()
619 col2 = configPanel.rightPanel
620 colSize2 = col2.GetSize()
621 colBestSize2 = col2.GetBestSize()
623 orientation = sizer.GetOrientation()
625 if orientation == wx.HORIZONTAL:
626 if (colSize1[0] <= colBestSize1[0]) or (colSize2[0] <= colBestSize2[0]):
628 sizer = wx.BoxSizer(wx.VERTICAL)
629 sizer.Add(configPanel.leftPanel, flag=wx.EXPAND)
630 sizer.Add(configPanel.rightPanel, flag=wx.EXPAND)
631 configPanel.SetSizer(sizer)
637 if max(colSize1[0], colSize2[0]) > (colBestSize1[0] + colBestSize2[0]):
639 sizer = wx.BoxSizer(wx.HORIZONTAL)
640 sizer.Add(configPanel.leftPanel, proportion=1, border=35, flag=wx.EXPAND)
641 sizer.Add(configPanel.rightPanel, proportion=1, flag=wx.EXPAND)
642 configPanel.SetSizer(sizer)
648 def updateProfileToControls(self):
649 super(normalSettingsPanel, self).updateProfileToControls()
650 if self.alterationPanel is not None:
651 self.alterationPanel.updateProfileToControls()
652 self.pluginPanel.updateProfileToControls()