1 from __future__ import absolute_import
\r
4 import wx, os, platform, types, webbrowser, threading, time, re
\r
7 from gui import firmwareInstall
\r
8 from util import machineCom
\r
9 from util import profile
\r
11 class InfoPage(wx.wizard.WizardPageSimple):
\r
12 def __init__(self, parent, title):
\r
13 wx.wizard.WizardPageSimple.__init__(self, parent)
\r
15 sizer = wx.GridBagSizer(5, 5)
\r
17 self.SetSizer(sizer)
\r
18 sizer.AddGrowableCol(1)
\r
20 title = wx.StaticText(self, -1, title)
\r
21 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
\r
22 sizer.Add(title, pos=(0, 0), span=(1,2), flag=wx.ALIGN_CENTRE|wx.ALL)
\r
23 sizer.Add(wx.StaticLine(self, -1), pos=(1,0), span=(1,2), flag=wx.EXPAND|wx.ALL)
\r
27 def AddText(self,info):
\r
28 text = wx.StaticText(self, -1, info)
\r
29 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT|wx.RIGHT)
\r
33 def AddSeperator(self):
\r
34 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1,2), flag=wx.EXPAND|wx.ALL)
\r
37 def AddHiddenSeperator(self):
\r
40 def AddRadioButton(self, label, style = 0):
\r
41 radio = wx.RadioButton(self, -1, label, style=style)
\r
42 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1,2), flag=wx.EXPAND|wx.ALL)
\r
46 def AddButton(self, label):
\r
47 button = wx.Button(self, -1, label)
\r
48 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT)
\r
52 def AddDualButton(self, label1, label2):
\r
53 button1 = wx.Button(self, -1, label1)
\r
54 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
\r
55 button2 = wx.Button(self, -1, label2)
\r
56 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
\r
58 return button1, button2
\r
60 def AddTextCtrl(self, value):
\r
61 ret = wx.TextCtrl(self, -1, value)
\r
62 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1,2), flag=wx.LEFT)
\r
66 def AddLabelTextCtrl(self, info, value):
\r
67 text = wx.StaticText(self, -1, info)
\r
68 ret = wx.TextCtrl(self, -1, value)
\r
69 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT)
\r
70 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1,1), flag=wx.LEFT)
\r
74 def AddTextCtrlButton(self, value, buttonText):
\r
75 text = wx.TextCtrl(self, -1, value)
\r
76 button = wx.Button(self, -1, buttonText)
\r
77 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1,1), flag=wx.LEFT)
\r
78 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1,1), flag=wx.LEFT)
\r
81 def AllowNext(self):
\r
84 def StoreData(self):
\r
87 class FirstInfoPage(InfoPage):
\r
88 def __init__(self, parent):
\r
89 super(FirstInfoPage, self).__init__(parent, "First time run wizard")
\r
90 self.AddText('Welcome, and thanks for trying Cura!')
\r
92 self.AddText('This wizard will help you with the following steps:')
\r
93 self.AddText('* Configure Cura for your machine')
\r
94 self.AddText('* Upgrade your firmware')
\r
95 self.AddText('* Calibrate your machine')
\r
96 #self.AddText('* Do your first print')
\r
98 class RepRapInfoPage(InfoPage):
\r
99 def __init__(self, parent):
\r
100 super(RepRapInfoPage, self).__init__(parent, "RepRap information")
\r
101 self.AddText('RepRap machines are vastly different, and there is no\ndefault configuration in Cura for any of them.')
\r
102 self.AddText('If you like a default profile for your machine added,\nthen make an issue on github.')
\r
103 self.AddSeperator()
\r
104 self.AddText('You will have to manually install Marlin or Sprinter firmware.')
\r
105 self.AddSeperator()
\r
106 self.machineWidth = self.AddLabelTextCtrl('Machine width (mm)', '80')
\r
107 self.machineDepth = self.AddLabelTextCtrl('Machine depth (mm)', '80')
\r
108 self.machineHeight = self.AddLabelTextCtrl('Machine height (mm)', '60')
\r
109 self.nozzleSize = self.AddLabelTextCtrl('Nozzle size (mm)', '0.5')
\r
111 def StoreData(self):
\r
112 profile.putPreference('machine_width', self.machineWidth.GetValue())
\r
113 profile.putPreference('machine_depth', self.machineDepth.GetValue())
\r
114 profile.putPreference('machine_height', self.machineHeight.GetValue())
\r
115 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
\r
116 profile.putProfileSetting('machine_center_x', profile.getPreferenceFloat('machine_width') / 2)
\r
117 profile.putProfileSetting('machine_center_y', profile.getPreferenceFloat('machine_depth') / 2)
\r
118 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
\r
120 class MachineSelectPage(InfoPage):
\r
121 def __init__(self, parent):
\r
122 super(MachineSelectPage, self).__init__(parent, "Select your machine")
\r
123 self.AddText('What kind of machine do you have:')
\r
125 self.UltimakerRadio = self.AddRadioButton("Ultimaker", style=wx.RB_GROUP)
\r
126 self.UltimakerRadio.SetValue(True)
\r
127 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
\r
128 self.OtherRadio = self.AddRadioButton("Other (Ex: RepRap)")
\r
129 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
\r
131 def OnUltimakerSelect(self, e):
\r
132 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
\r
134 def OnOtherSelect(self, e):
\r
135 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().repRapInfoPage)
\r
137 def StoreData(self):
\r
138 if self.UltimakerRadio.GetValue():
\r
139 profile.putPreference('machine_width', '205')
\r
140 profile.putPreference('machine_depth', '205')
\r
141 profile.putPreference('machine_height', '200')
\r
142 profile.putPreference('machine_type', 'ultimaker')
\r
143 profile.putProfileSetting('nozzle_size', '0.4')
\r
144 profile.putProfileSetting('machine_center_x', '100')
\r
145 profile.putProfileSetting('machine_center_y', '100')
\r
147 profile.putPreference('machine_width', '80')
\r
148 profile.putPreference('machine_depth', '80')
\r
149 profile.putPreference('machine_height', '60')
\r
150 profile.putPreference('machine_type', 'reprap')
\r
151 profile.putProfileSetting('nozzle_size', '0.5')
\r
152 profile.putProfileSetting('machine_center_x', '40')
\r
153 profile.putProfileSetting('machine_center_y', '40')
\r
154 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
\r
156 class FirmwareUpgradePage(InfoPage):
\r
157 def __init__(self, parent):
\r
158 super(FirmwareUpgradePage, self).__init__(parent, "Upgrade Ultimaker Firmware")
\r
159 self.AddText('Firmware is the piece of software running directly on your 3D printer.\nThis firmware controls the step motors, regulates the temperature\nand ultimately makes your printer work.')
\r
160 self.AddHiddenSeperator()
\r
161 self.AddText('The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier.')
\r
162 self.AddHiddenSeperator()
\r
163 self.AddText('Cura requires these new features and thus\nyour firmware will most likely need to be upgraded.\nYou will get the chance to do so now.')
\r
164 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
\r
165 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
\r
166 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
\r
167 self.AddHiddenSeperator()
\r
168 self.AddText('Do not upgrade to this firmware if:')
\r
169 self.AddText('* You have an older machine based on ATMega1280')
\r
170 self.AddText('* Have other changes in the firmware')
\r
171 button = self.AddButton('Goto this page for a custom firmware')
\r
172 button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
\r
174 def AllowNext(self):
\r
177 def OnUpgradeClick(self, e):
\r
178 if firmwareInstall.InstallFirmware():
\r
179 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
181 def OnSkipClick(self, e):
\r
182 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
184 def OnUrlClick(self, e):
\r
185 webbrowser.open('http://daid.mine.nu/~daid/marlin_build/')
\r
187 class UltimakerCheckupPage(InfoPage):
\r
188 def __init__(self, parent):
\r
189 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")
\r
190 self.AddText('It is a good idea to do a few sanity checks now on your Ultimaker.\nYou can skip these if you know your machine is functional.')
\r
191 b1, b2 = self.AddDualButton('Run checks', 'Skip checks')
\r
192 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
\r
193 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
\r
194 self.AddSeperator()
\r
195 self.checkPanel = None
\r
197 def AllowNext(self):
\r
200 def OnSkipClick(self, e):
\r
201 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
\r
203 def OnCheckClick(self, e):
\r
204 if self.checkPanel != None:
\r
205 self.checkPanel.Destroy()
\r
206 self.checkPanel = wx.Panel(self)
\r
207 self.checkPanel.SetSizer(wx.BoxSizer(wx.VERTICAL))
\r
208 self.GetSizer().Add(self.checkPanel, 0, wx.LEFT|wx.RIGHT, 5)
\r
209 threading.Thread(target=self.OnRun).start()
\r
211 def AddProgressText(self, info):
\r
212 text = wx.StaticText(self.checkPanel, -1, info)
\r
213 self.checkPanel.GetSizer().Add(text, 0)
\r
214 self.checkPanel.Layout()
\r
218 wx.CallAfter(self.AddProgressText, "Connecting to machine...")
\r
219 self.comm = machineCom.MachineCom()
\r
221 if not self.comm.isOpen():
\r
222 wx.CallAfter(self.AddProgressText, "Error: Failed to open serial port to machine")
\r
223 wx.CallAfter(self.AddProgressText, "If this keeps happening, try disconnecting and reconnecting the USB cable")
\r
226 wx.CallAfter(self.AddProgressText, "Checking start message...")
\r
227 if self.DoCommCommandWithTimeout(None, 'start') == False:
\r
228 wx.CallAfter(self.AddProgressText, "Error: Missing start message.")
\r
232 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
\r
235 wx.CallAfter(self.AddProgressText, "Disabling step motors...")
\r
236 if self.DoCommCommandWithTimeout('M84') == False:
\r
237 wx.CallAfter(self.AddProgressText, "Error: Missing reply to Deactivate steppers (M84).")
\r
241 if self.DoCommCommandWithTimeout("M104 S0") == False:
\r
242 wx.CallAfter(self.AddProgressText, "Failed to set temperature")
\r
246 wx.MessageBox('Please move the printer head to the center of the machine\nalso move the platform so it is not at the highest or lowest position,\nand make sure the machine is powered on.', 'Machine check', wx.OK | wx.ICON_INFORMATION)
\r
248 idleTemp = self.readTemp()
\r
250 wx.CallAfter(self.AddProgressText, "Waiting for head to cool down before temperature test...")
\r
251 while idleTemp > 40:
\r
252 idleTemp = self.readTemp()
\r
255 wx.CallAfter(self.AddProgressText, "Checking heater and temperature sensor...")
\r
256 wx.CallAfter(self.AddProgressText, "(This takes about 30 seconds)")
\r
257 if self.DoCommCommandWithTimeout("M104 S100") == False:
\r
258 wx.CallAfter(self.AddProgressText, "Failed to set temperature")
\r
263 tempInc = self.readTemp() - idleTemp
\r
265 if self.DoCommCommandWithTimeout("M104 S0") == False:
\r
266 wx.CallAfter(self.AddProgressText, "Failed to set temperature")
\r
271 wx.CallAfter(self.AddProgressText, "Your temperature sensor or heater is not working!")
\r
274 wx.CallAfter(self.AddProgressText, "Heater and temperature sensor working\nWarning: head might still be hot!")
\r
276 wx.CallAfter(self.AddProgressText, "Checking endstops")
\r
277 if self.DoCommCommandWithTimeout('M119', 'x_min') != "x_min:L x_max:L y_min:L y_max:L z_min:L z_max:L":
\r
278 wx.CallAfter(self.AddProgressText, "Error: There is a problem in your endstops!\nOne of them seems to be pressed while it shouldn't\ncheck the cable connections and the switches themselfs.")
\r
281 wx.CallAfter(self.AddProgressText, "Please press the X end switch in the front left corner.")
\r
282 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:H x_max:L y_min:L y_max:L z_min:L z_max:L"):
\r
283 wx.CallAfter(self.AddProgressText, "Failed to check the x_min endstop!")
\r
286 wx.CallAfter(self.AddProgressText, "Please press the X end switch in the front right corner.")
\r
287 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:H y_min:L y_max:L z_min:L z_max:L"):
\r
288 wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")
\r
291 wx.CallAfter(self.AddProgressText, "Please press the Y end switch in the front left corner.")
\r
292 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:L y_min:H y_max:L z_min:L z_max:L"):
\r
293 wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")
\r
296 wx.CallAfter(self.AddProgressText, "Please press the Y end switch in the back left corner.")
\r
297 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:L y_min:L y_max:H z_min:L z_max:L"):
\r
298 wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")
\r
301 wx.CallAfter(self.AddProgressText, "Please press the Z end switch in the top.")
\r
302 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:L y_min:L y_max:L z_min:H z_max:L"):
\r
303 wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")
\r
306 wx.CallAfter(self.AddProgressText, "Please press the Z end switch in the bottom.")
\r
307 if not self.DoCommCommandAndWaitForReply('M119', 'x_min', "x_min:L x_max:L y_min:L y_max:L z_min:L z_max:H"):
\r
308 wx.CallAfter(self.AddProgressText, "Failed to check the x_max endstop!")
\r
311 wx.CallAfter(self.AddProgressText, "End stops are working.")
\r
313 wx.CallAfter(self.AddProgressText, "Done!")
\r
314 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
\r
317 def readTemp(self):
\r
318 line = self.DoCommCommandWithTimeout("M105", "ok T:")
\r
321 return int(re.search('T:([0-9]*)', line).group(1))
\r
323 def DoCommCommandAndWaitForReply(self, cmd, replyStart, reply):
\r
325 ret = self.DoCommCommandWithTimeout(cmd, replyStart)
\r
332 def DoCommCommandWithTimeout(self, cmd = None, replyStart = 'ok'):
\r
334 self.comm.sendCommand(cmd)
\r
335 t = threading.Timer(5, self.OnSerialTimeout)
\r
338 line = self.comm.readline()
\r
339 if line == '' or line == None:
\r
342 print line.rstrip()
\r
343 if replyStart in line:
\r
346 return line.rstrip()
\r
348 def OnSerialTimeout(self):
\r
351 class UltimakerCalibrationPage(InfoPage):
\r
352 def __init__(self, parent):
\r
353 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")
\r
355 self.AddText("Your Ultimaker requires some calibration.")
\r
356 self.AddText("This calibration is needed for a proper extrusion amount.")
\r
357 self.AddSeperator()
\r
358 self.AddText("The following values are needed:")
\r
359 self.AddText("* Diameter of filament")
\r
360 self.AddText("* Number of steps per mm of filament extrusion")
\r
361 self.AddSeperator()
\r
362 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
\r
363 self.AddSeperator()
\r
364 self.AddText("First we need the diameter of your filament:")
\r
365 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
\r
366 self.AddText("If you do not own digital Calipers that can measure\nat least 2 digits then use 2.89mm.\nWhich is the average diameter of most filament.")
\r
367 self.AddText("Note: This value can be changed later at any time.")
\r
369 def StoreData(self):
\r
370 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
\r
372 class UltimakerCalibrateStepsPerEPage(InfoPage):
\r
373 def __init__(self, parent):
\r
374 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")
\r
376 if profile.getPreference('steps_per_e') == '0':
\r
377 profile.putPreference('steps_per_e', '865.888')
\r
379 self.AddText("Calibrating the Steps Per E requires some manual actions.")
\r
380 self.AddText("First remove any filament from your machine.")
\r
381 self.AddText("Next put in your filament so the tip is aligned with the\ntop of the extruder drive.")
\r
382 self.AddText("We'll push the filament 100mm")
\r
383 self.extrudeButton = self.AddButton("Extrude 100mm filament")
\r
384 self.AddText("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)")
\r
385 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton('100', 'Save')
\r
386 self.AddText("This results in the following steps per E:")
\r
387 self.stepsPerEInput = self.AddTextCtrl(profile.getPreference('steps_per_e'))
\r
388 self.AddText("You can repeat these steps to get better calibration.")
\r
389 self.AddSeperator()
\r
390 self.AddText("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:")
\r
391 self.heatButton = self.AddButton("Heatup for filament removal")
\r
393 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
\r
394 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
\r
395 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
\r
397 def OnSaveLengthClick(self, e):
\r
398 currentEValue = float(self.stepsPerEInput.GetValue())
\r
399 realExtrudeLength = float(self.lengthInput.GetValue())
\r
400 newEValue = currentEValue * 100 / realExtrudeLength
\r
401 self.stepsPerEInput.SetValue(str(newEValue))
\r
402 self.lengthInput.SetValue("100")
\r
404 def OnExtrudeClick(self, e):
\r
405 threading.Thread(target=self.OnExtrudeRun).start()
\r
407 def OnExtrudeRun(self):
\r
408 self.heatButton.Enable(False)
\r
409 self.extrudeButton.Enable(False)
\r
410 currentEValue = float(self.stepsPerEInput.GetValue())
\r
411 self.comm = machineCom.MachineCom()
\r
412 if not self.comm.isOpen():
\r
413 wx.MessageBox("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable", 'Printer error', wx.OK | wx.ICON_INFORMATION)
\r
414 self.heatButton.Enable(True)
\r
415 self.extrudeButton.Enable(True)
\r
418 line = self.comm.readline()
\r
421 if 'start' in line:
\r
423 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
\r
426 self.sendGCommand('M302') #Disable cold extrusion protection
\r
427 self.sendGCommand("M92 E%f" % (currentEValue))
\r
428 self.sendGCommand("G92 E0")
\r
429 self.sendGCommand("G1 E100 F600")
\r
432 self.extrudeButton.Enable()
\r
433 self.heatButton.Enable()
\r
435 def OnHeatClick(self, e):
\r
436 threading.Thread(target=self.OnHeatRun).start()
\r
438 def OnHeatRun(self):
\r
439 self.heatButton.Enable(False)
\r
440 self.extrudeButton.Enable(False)
\r
441 self.comm = machineCom.MachineCom()
\r
442 if not self.comm.isOpen():
\r
443 wx.MessageBox("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable", 'Printer error', wx.OK | wx.ICON_INFORMATION)
\r
444 self.heatButton.Enable(True)
\r
445 self.extrudeButton.Enable(True)
\r
448 line = self.comm.readline()
\r
450 self.heatButton.Enable(True)
\r
451 self.extrudeButton.Enable(True)
\r
453 if 'start' in line:
\r
455 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
\r
458 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
\r
459 wx.MessageBox('Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)', 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
\r
460 self.sendGCommand('M104 S0')
\r
463 self.heatButton.Enable(True)
\r
464 self.extrudeButton.Enable(True)
\r
466 def sendGCommand(self, cmd):
\r
467 self.comm.sendCommand(cmd) #Disable cold extrusion protection
\r
469 line = self.comm.readline()
\r
472 if line.startswith('ok'):
\r
475 def StoreData(self):
\r
476 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
\r
478 class configWizard(wx.wizard.Wizard):
\r
479 def __init__(self):
\r
480 super(configWizard, self).__init__(None, -1, "Configuration Wizard")
\r
482 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
\r
483 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
\r
485 self.firstInfoPage = FirstInfoPage(self)
\r
486 self.machineSelectPage = MachineSelectPage(self)
\r
487 self.ultimakerFirmwareUpgradePage = FirmwareUpgradePage(self)
\r
488 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
\r
489 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
\r
490 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
\r
491 self.repRapInfoPage = RepRapInfoPage(self)
\r
493 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
\r
494 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerFirmwareUpgradePage)
\r
495 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
\r
496 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.ultimakerCalibrationPage)
\r
497 wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
\r
499 self.FitToPage(self.firstInfoPage)
\r
500 self.GetPageAreaSizer().Add(self.firstInfoPage)
\r
502 self.RunWizard(self.firstInfoPage)
\r
505 def OnPageChanging(self, e):
\r
506 e.GetPage().StoreData()
\r
508 def OnPageChanged(self, e):
\r
509 if e.GetPage().AllowNext():
\r
510 self.FindWindowById(wx.ID_FORWARD).Enable()
\r
512 self.FindWindowById(wx.ID_FORWARD).Disable()
\r
513 self.FindWindowById(wx.ID_BACKWARD).Disable()
\r