1 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
12 from Cura.gui import firmwareInstall
13 from Cura.gui import printWindow
14 from Cura.util import machineCom
15 from Cura.util import profile
16 from Cura.util import gcodeGenerator
17 from Cura.util import resources
20 class InfoBox(wx.Panel):
21 def __init__(self, parent):
22 super(InfoBox, self).__init__(parent)
23 self.SetBackgroundColour('#FFFF80')
25 self.sizer = wx.GridBagSizer(5, 5)
26 self.SetSizer(self.sizer)
28 self.attentionBitmap = wx.Bitmap(resources.getPathForImage('attention.png'))
29 self.errorBitmap = wx.Bitmap(resources.getPathForImage('error.png'))
30 self.readyBitmap = wx.Bitmap(resources.getPathForImage('ready.png'))
32 wx.Bitmap(resources.getPathForImage('busy-0.png')),
33 wx.Bitmap(resources.getPathForImage('busy-1.png')),
34 wx.Bitmap(resources.getPathForImage('busy-2.png')),
35 wx.Bitmap(resources.getPathForImage('busy-3.png'))
38 self.bitmap = wx.StaticBitmap(self, -1, wx.EmptyBitmapRGBA(24, 24, red=255, green=255, blue=255, alpha=1))
39 self.text = wx.StaticText(self, -1, '')
40 self.extraInfoButton = wx.Button(self, -1, 'i', style=wx.BU_EXACTFIT)
41 self.sizer.Add(self.bitmap, pos=(0, 0), flag=wx.ALL, border=5)
42 self.sizer.Add(self.text, pos=(0, 1), flag=wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER_VERTICAL, border=5)
43 self.sizer.Add(self.extraInfoButton, pos=(0,2), flag=wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, border=5)
44 self.sizer.AddGrowableCol(1)
46 self.extraInfoButton.Show(False)
48 self.extraInfoUrl = ''
50 self.timer = wx.Timer(self)
51 self.Bind(wx.EVT_TIMER, self.doBusyUpdate, self.timer)
52 self.Bind(wx.EVT_BUTTON, self.doExtraInfo, self.extraInfoButton)
55 def SetInfo(self, info):
56 self.SetBackgroundColour('#FFFF80')
57 self.text.SetLabel(info)
58 self.extraInfoButton.Show(False)
61 def SetError(self, info, extraInfoUrl):
62 self.extraInfoUrl = extraInfoUrl
63 self.SetBackgroundColour('#FF8080')
64 self.text.SetLabel(info)
65 self.extraInfoButton.Show(True)
67 self.SetErrorIndicator()
70 def SetAttention(self, info):
71 self.SetBackgroundColour('#FFFF80')
72 self.text.SetLabel(info)
73 self.extraInfoButton.Show(False)
74 self.SetAttentionIndicator()
78 def SetBusy(self, info):
80 self.SetBusyIndicator()
82 def SetBusyIndicator(self):
84 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
86 def doExtraInfo(self, e):
87 webbrowser.open(self.extraInfoUrl)
89 def doBusyUpdate(self, e):
90 if self.busyState is None:
93 if self.busyState >= len(self.busyBitmap):
95 self.bitmap.SetBitmap(self.busyBitmap[self.busyState])
97 def SetReadyIndicator(self):
99 self.bitmap.SetBitmap(self.readyBitmap)
101 def SetErrorIndicator(self):
102 self.busyState = None
103 self.bitmap.SetBitmap(self.errorBitmap)
105 def SetAttentionIndicator(self):
106 self.busyState = None
107 self.bitmap.SetBitmap(self.attentionBitmap)
110 class InfoPage(wx.wizard.WizardPageSimple):
111 def __init__(self, parent, title):
112 wx.wizard.WizardPageSimple.__init__(self, parent)
114 sizer = wx.GridBagSizer(5, 5)
118 title = wx.StaticText(self, -1, title)
119 title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
120 sizer.Add(title, pos=(0, 0), span=(1, 2), flag=wx.ALIGN_CENTRE | wx.ALL)
121 sizer.Add(wx.StaticLine(self, -1), pos=(1, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
122 sizer.AddGrowableCol(1)
126 def AddText(self, info):
127 text = wx.StaticText(self, -1, info)
128 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
132 def AddSeperator(self):
133 self.GetSizer().Add(wx.StaticLine(self, -1), pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
136 def AddHiddenSeperator(self):
139 def AddInfoBox(self):
140 infoBox = InfoBox(self)
141 self.GetSizer().Add(infoBox, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT | wx.EXPAND)
145 def AddRadioButton(self, label, style=0):
146 radio = wx.RadioButton(self, -1, label, style=style)
147 self.GetSizer().Add(radio, pos=(self.rowNr, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL)
151 def AddCheckbox(self, label, checked=False):
152 check = wx.CheckBox(self, -1)
153 text = wx.StaticText(self, -1, label)
154 check.SetValue(checked)
155 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
156 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 2), flag=wx.ALL)
160 def AddButton(self, label):
161 button = wx.Button(self, -1, label)
162 self.GetSizer().Add(button, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
166 def AddDualButton(self, label1, label2):
167 button1 = wx.Button(self, -1, label1)
168 self.GetSizer().Add(button1, pos=(self.rowNr, 0), flag=wx.RIGHT)
169 button2 = wx.Button(self, -1, label2)
170 self.GetSizer().Add(button2, pos=(self.rowNr, 1))
172 return button1, button2
174 def AddTextCtrl(self, value):
175 ret = wx.TextCtrl(self, -1, value)
176 self.GetSizer().Add(ret, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT)
180 def AddLabelTextCtrl(self, info, value):
181 text = wx.StaticText(self, -1, info)
182 ret = wx.TextCtrl(self, -1, value)
183 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
184 self.GetSizer().Add(ret, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
188 def AddTextCtrlButton(self, value, buttonText):
189 text = wx.TextCtrl(self, -1, value)
190 button = wx.Button(self, -1, buttonText)
191 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT)
192 self.GetSizer().Add(button, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT)
196 def AddBitmap(self, bitmap):
197 bitmap = wx.StaticBitmap(self, -1, bitmap)
198 self.GetSizer().Add(bitmap, pos=(self.rowNr, 0), span=(1, 2), flag=wx.LEFT | wx.RIGHT)
202 def AddCheckmark(self, label, bitmap):
203 check = wx.StaticBitmap(self, -1, bitmap)
204 text = wx.StaticText(self, -1, label)
205 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
206 self.GetSizer().Add(check, pos=(self.rowNr, 1), span=(1, 1), flag=wx.ALL)
210 def AddCombo(self, label, options):
211 combo = wx.ComboBox(self, -1, options[0], choices=options, style=wx.CB_DROPDOWN|wx.CB_READONLY)
212 text = wx.StaticText(self, -1, label)
213 self.GetSizer().Add(text, pos=(self.rowNr, 0), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
214 self.GetSizer().Add(combo, pos=(self.rowNr, 1), span=(1, 1), flag=wx.LEFT | wx.RIGHT)
227 class PrintrbotPage(InfoPage):
228 def __init__(self, parent):
229 self._printer_info = [
230 # X, Y, Z, Filament Diameter, PrintTemperature, Print Speed, Travel Speed, Retract speed, Retract amount
231 ("Simple Metal", 150, 150, 150, 1.75, 208, 40, 70, 30, 1),
232 ("Metal Plus", 250, 250, 250, 1.75, 208, 40, 70, 30, 1),
233 ("Simple Makers Kit", 100, 100, 100, 1.75, 208, 40, 70, 30, 1),
234 (":" + _("Older models"),),
235 ("Original", 130, 130, 130, 2.95, 208, 40, 70, 30, 1),
236 ("Simple Maker's Edition v1", 100, 100, 100, 1.75, 208, 40, 70, 30, 1),
237 ("Simple Maker's Edition v2 (2013 Printrbot Simple)", 100, 100, 100, 1.75, 208, 40, 70, 30, 1),
238 ("Simple Maker's Edition v3 (2014 Printrbot Simple)", 100, 100, 100, 1.75, 208, 40, 70, 30, 1),
239 ("Simple Maker's Edition v4 (Model 1405)", 100, 100, 100, 1.75, 208, 40, 70, 30, 1),
240 ("Jr v1", 150, 100, 80, 1.75, 208, 40, 70, 30, 1),
241 ("Jr v2", 150, 150, 150, 1.75, 208, 40, 70, 30, 1),
242 ("LC v2", 150, 150, 150, 1.75, 208, 40, 70, 30, 1),
243 ("Plus v2", 200, 200, 200, 1.75, 208, 40, 70, 30, 1),
244 ("Plus v2.1", 200, 200, 200, 1.75, 208, 40, 70, 30, 1),
245 ("Plus v2.2 (Model 1404/140422)", 250, 250, 250, 1.75, 208, 40, 70, 30, 1),
246 ("Plus v2.3 (Model 140501)", 250, 250, 250, 1.75, 208, 40, 70, 30, 1),
247 ("Plus v2.4 (Model 140507)", 250, 250, 250, 1.75, 208, 40, 70, 30, 1),
248 ("Go v2 Large", 609, 305, 305, 1.75, 208, 35, 70, 30, 1),
251 super(PrintrbotPage, self).__init__(parent, _("Printrbot Selection"))
252 self.AddBitmap(wx.Bitmap(resources.getPathForImage('Printrbot_logo.png')))
253 self.AddText(_("Select which Printrbot machine you have:"))
255 for printer in self._printer_info:
256 if printer[0].startswith(":"):
258 self.AddText(printer[0][1:])
260 item = self.AddRadioButton(printer[0])
261 item.data = printer[1:]
262 self._items.append(item)
265 profile.putMachineSetting('machine_name', 'Printrbot ???')
266 for item in self._items:
269 profile.putMachineSetting('machine_name', 'Printrbot ' + item.GetLabel())
270 profile.putMachineSetting('machine_width', data[0])
271 profile.putMachineSetting('machine_depth', data[1])
272 profile.putMachineSetting('machine_height', data[2])
273 profile.putProfileSetting('nozzle_size', '0.5')
274 profile.putProfileSetting('filament_diameter', data[3])
275 profile.putProfileSetting('print_temperature', data[4])
276 profile.putProfileSetting('print_speed', data[5])
277 profile.putProfileSetting('travel_speed', data[6])
278 profile.putProfileSetting('retraction_speed', data[7])
279 profile.putProfileSetting('retraction_amount', data[8])
280 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
281 profile.putMachineSetting('has_heated_bed', 'False')
282 profile.putMachineSetting('machine_center_is_zero', 'False')
283 profile.putMachineSetting('extruder_head_size_min_x', '0')
284 profile.putMachineSetting('extruder_head_size_min_y', '0')
285 profile.putMachineSetting('extruder_head_size_max_x', '0')
286 profile.putMachineSetting('extruder_head_size_max_y', '0')
287 profile.putMachineSetting('extruder_head_size_height', '0')
289 class OtherMachineSelectPage(InfoPage):
290 def __init__(self, parent):
291 super(OtherMachineSelectPage, self).__init__(parent, _("Other machine information"))
292 self.AddText(_("The following pre-defined machine profiles are available"))
293 self.AddText(_("Note that these profiles are not guaranteed to give good results,\nor work at all. Extra tweaks might be required.\nIf you find issues with the predefined profiles,\nor want an extra profile.\nPlease report it at the github issue tracker."))
295 machines = resources.getDefaultMachineProfiles()
297 for filename in machines:
298 name = os.path.splitext(os.path.basename(filename))[0]
299 item = self.AddRadioButton(name)
300 item.filename = filename
301 item.Bind(wx.EVT_RADIOBUTTON, self.OnProfileSelect)
302 self.options.append(item)
304 item = self.AddRadioButton(_('Custom...'))
306 item.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
308 def OnProfileSelect(self, e):
309 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineInfoPage)
311 def OnOtherSelect(self, e):
312 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().customRepRapInfoPage)
315 for option in self.options:
316 if option.GetValue():
317 profile.loadProfile(option.filename)
318 profile.loadMachineSettings(option.filename)
320 class OtherMachineInfoPage(InfoPage):
321 def __init__(self, parent):
322 super(OtherMachineInfoPage, self).__init__(parent, _("Cura Ready!"))
323 self.AddText(_("Cura is now ready to be used!"))
325 class CustomRepRapInfoPage(InfoPage):
326 def __init__(self, parent):
327 super(CustomRepRapInfoPage, self).__init__(parent, _("Custom RepRap information"))
328 self.AddText(_("RepRap machines can be vastly different, so here you can set your own settings."))
329 self.AddText(_("Be sure to review the default profile before running it on your machine."))
330 self.AddText(_("If you like a default profile for your machine added,\nthen make an issue on github."))
332 self.AddText(_("You will have to manually install Marlin or Sprinter firmware."))
334 self.machineName = self.AddLabelTextCtrl(_("Machine name"), "RepRap")
335 self.machineWidth = self.AddLabelTextCtrl(_("Machine width (mm)"), "80")
336 self.machineDepth = self.AddLabelTextCtrl(_("Machine depth (mm)"), "80")
337 self.machineHeight = self.AddLabelTextCtrl(_("Machine height (mm)"), "55")
338 self.nozzleSize = self.AddLabelTextCtrl(_("Nozzle size (mm)"), "0.5")
339 self.heatedBed = self.AddCheckbox(_("Heated bed"))
340 self.HomeAtCenter = self.AddCheckbox(_("Bed center is 0,0,0 (RoStock)"))
343 profile.putMachineSetting('machine_name', self.machineName.GetValue())
344 profile.putMachineSetting('machine_width', self.machineWidth.GetValue())
345 profile.putMachineSetting('machine_depth', self.machineDepth.GetValue())
346 profile.putMachineSetting('machine_height', self.machineHeight.GetValue())
347 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
348 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
349 profile.putMachineSetting('has_heated_bed', str(self.heatedBed.GetValue()))
350 profile.putMachineSetting('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
351 profile.putMachineSetting('extruder_head_size_min_x', '0')
352 profile.putMachineSetting('extruder_head_size_min_y', '0')
353 profile.putMachineSetting('extruder_head_size_max_x', '0')
354 profile.putMachineSetting('extruder_head_size_max_y', '0')
355 profile.putMachineSetting('extruder_head_size_height', '0')
356 profile.checkAndUpdateMachineName()
358 class MachineSelectPage(InfoPage):
359 def __init__(self, parent):
360 super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
361 self.AddText(_("What kind of machine do you have:"))
363 self.LulzbotMiniRadio = self.AddRadioButton("LulzBot Mini", style=wx.RB_GROUP)
364 self.LulzbotMiniRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
365 self.LulzbotMiniRadio.SetValue(True)
366 self.LulzbotTaz5Radio = self.AddRadioButton("LulzBot TAZ 5")
367 self.LulzbotTaz5Radio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
368 self.LulzbotTaz4Radio = self.AddRadioButton("LulzBot TAZ 4")
369 self.LulzbotTaz4Radio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
370 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2")
371 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
372 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
373 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
374 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
375 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
376 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
377 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
378 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
379 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
381 def OnUltimaker2Select(self, e):
382 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
384 def OnUltimakerSelect(self, e):
385 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
387 def OnUltimakerOPSelect(self, e):
388 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
390 def OnPrintrbotSelect(self, e):
391 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
393 def OnLulzbotSelect(self, e):
394 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
396 def OnOtherSelect(self, e):
397 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
400 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
404 profile.putProfileSetting('retraction_enable', 'True')
405 if self.Ultimaker2Radio.GetValue():
406 profile.putMachineSetting('machine_width', '230')
407 profile.putMachineSetting('machine_depth', '225')
408 profile.putMachineSetting('machine_height', '205')
409 profile.putMachineSetting('machine_name', 'ultimaker2')
410 profile.putMachineSetting('machine_type', 'ultimaker2')
411 profile.putMachineSetting('machine_center_is_zero', 'False')
412 profile.putMachineSetting('has_heated_bed', 'True')
413 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
414 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
415 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
416 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
417 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
418 profile.putMachineSetting('extruder_head_size_height', '48.0')
419 profile.putProfileSetting('nozzle_size', '0.4')
420 profile.putProfileSetting('fan_full_height', '5.0')
421 profile.putMachineSetting('extruder_offset_x1', '18.0')
422 profile.putMachineSetting('extruder_offset_y1', '0.0')
423 elif self.UltimakerRadio.GetValue():
424 profile.putMachineSetting('machine_width', '205')
425 profile.putMachineSetting('machine_depth', '205')
426 profile.putMachineSetting('machine_height', '200')
427 profile.putMachineSetting('machine_name', 'ultimaker original')
428 profile.putMachineSetting('machine_type', 'ultimaker')
429 profile.putMachineSetting('machine_center_is_zero', 'False')
430 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
431 profile.putProfileSetting('nozzle_size', '0.4')
432 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
433 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
434 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
435 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
436 profile.putMachineSetting('extruder_head_size_height', '55.0')
437 elif self.UltimakerOPRadio.GetValue():
438 profile.putMachineSetting('machine_width', '205')
439 profile.putMachineSetting('machine_depth', '205')
440 profile.putMachineSetting('machine_height', '200')
441 profile.putMachineSetting('machine_name', 'ultimaker original+')
442 profile.putMachineSetting('machine_type', 'ultimaker_plus')
443 profile.putMachineSetting('machine_center_is_zero', 'False')
444 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
445 profile.putProfileSetting('nozzle_size', '0.4')
446 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
447 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
448 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
449 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
450 profile.putMachineSetting('extruder_head_size_height', '55.0')
451 profile.putMachineSetting('has_heated_bed', 'True')
452 profile.putMachineSetting('extruder_amount', '1')
453 profile.putProfileSetting('retraction_enable', 'True')
454 elif self.LulzbotTaz4Radio.GetValue() or self.LulzbotTaz5Radio.GetValue() or self.LulzbotMiniRadio.GetValue():
455 if self.LulzbotTaz4Radio.GetValue():
456 profile.putMachineSetting('machine_width', '298')
457 profile.putMachineSetting('machine_depth', '275')
458 profile.putMachineSetting('machine_height', '250')
459 profile.putProfileSetting('nozzle_size', '0.35')
460 profile.putMachineSetting('machine_name', 'LulzBot TAZ 4')
461 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_4')
462 profile.putMachineSetting('serial_baud', '115200')
463 elif self.LulzbotTaz5Radio.GetValue():
464 profile.putMachineSetting('machine_width', '298')
465 profile.putMachineSetting('machine_depth', '275')
466 profile.putMachineSetting('machine_height', '250')
467 profile.putProfileSetting('nozzle_size', '0.35')
468 profile.putMachineSetting('machine_name', 'LulzBot TAZ 5')
469 profile.putMachineSetting('machine_type', 'lulzbot_TAZ_5')
470 profile.putMachineSetting('serial_baud', '115200')
472 profile.putMachineSetting('machine_width', '155')
473 profile.putMachineSetting('machine_depth', '155')
474 profile.putMachineSetting('machine_height', '163')
475 profile.putProfileSetting('nozzle_size', '0.5')
476 profile.putMachineSetting('machine_name', 'LulzBot Mini')
477 profile.putMachineSetting('machine_type', 'lulzbot_mini')
478 profile.putMachineSetting('serial_baud', '115200')
479 profile.putMachineSetting('machine_center_is_zero', 'False')
480 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
481 profile.putMachineSetting('has_heated_bed', 'True')
482 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
483 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
484 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
485 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
486 profile.putMachineSetting('extruder_head_size_height', '0.0')
487 profile.putPreference('startMode', 'Simple')
489 profile.putMachineSetting('machine_width', '80')
490 profile.putMachineSetting('machine_depth', '80')
491 profile.putMachineSetting('machine_height', '60')
492 profile.putMachineSetting('machine_name', 'reprap')
493 profile.putMachineSetting('machine_type', 'reprap')
494 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
495 profile.putPreference('startMode', 'Normal')
496 profile.putProfileSetting('nozzle_size', '0.5')
497 profile.checkAndUpdateMachineName()
498 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
500 class SelectParts(InfoPage):
501 def __init__(self, parent):
502 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
503 self.AddText(_("To assist you in having better default settings for your Ultimaker\nCura would like to know which upgrades you have in your machine."))
505 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
506 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
507 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
508 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
510 self.AddText(_("If you have an Ultimaker bought after october 2012 you will have the\nExtruder drive upgrade. If you do not have this upgrade,\nit is highly recommended to improve reliability."))
511 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
512 self.springExtruder.SetValue(True)
515 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
516 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
517 profile.putMachineSetting('has_heated_bed', 'True')
519 profile.putMachineSetting('has_heated_bed', 'False')
520 if self.dualExtrusion.GetValue():
521 profile.putMachineSetting('extruder_amount', '2')
522 profile.putMachineSetting('machine_depth', '195')
524 profile.putMachineSetting('extruder_amount', '1')
525 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
526 profile.putProfileSetting('retraction_enable', 'True')
528 profile.putProfileSetting('retraction_enable', 'False')
531 class UltimakerFirmwareUpgradePage(InfoPage):
532 def __init__(self, parent):
533 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
534 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."))
535 self.AddHiddenSeperator()
536 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
537 self.AddHiddenSeperator()
538 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."))
539 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Upgrade to Marlin firmware'), _('Skip upgrade'))
540 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
541 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
542 self.AddHiddenSeperator()
543 if profile.getMachineSetting('machine_type') == 'ultimaker':
544 self.AddText(_("Do not upgrade to this firmware if:"))
545 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
546 self.AddText(_("* Build your own heated bed"))
547 self.AddText(_("* Have other changes in the firmware"))
548 # button = self.AddButton('Goto this page for a custom firmware')
549 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
554 def OnUpgradeClick(self, e):
555 if firmwareInstall.InstallFirmware():
556 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
558 def OnSkipClick(self, e):
559 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
560 self.GetParent().ShowPage(self.GetNext())
562 def OnUrlClick(self, e):
563 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
565 class UltimakerCheckupPage(InfoPage):
566 def __init__(self, parent):
567 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
569 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
570 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
571 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
572 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
573 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
574 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
575 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
576 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
577 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
578 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
581 _("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."))
582 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
583 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
584 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
586 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
587 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
588 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
590 self.infoBox = self.AddInfoBox()
591 self.machineState = self.AddText("")
592 self.temperatureLabel = self.AddText("")
593 self.errorLogButton = self.AddButton(_("Show error log"))
594 self.errorLogButton.Show(False)
596 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
598 self.xMinStop = False
599 self.xMaxStop = False
600 self.yMinStop = False
601 self.yMaxStop = False
602 self.zMinStop = False
603 self.zMaxStop = False
605 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
608 if self.comm is not None:
612 self.endstopBitmap.Show(False)
615 def OnSkipClick(self, e):
616 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
617 self.GetParent().ShowPage(self.GetNext())
619 def OnCheckClick(self, e=None):
620 self.errorLogButton.Show(False)
621 if self.comm is not None:
625 wx.CallAfter(self.OnCheckClick)
627 self.infoBox.SetBusy(_("Connecting to machine."))
628 self.commState.SetBitmap(self.unknownBitmap)
629 self.tempState.SetBitmap(self.unknownBitmap)
630 self.stopState.SetBitmap(self.unknownBitmap)
631 self.checkupState = 0
632 self.checkExtruderNr = 0
633 self.comm = machineCom.MachineCom(callbackObject=self)
635 def OnErrorLog(self, e):
636 printWindow.LogWindow('\n'.join(self.comm.getLog()))
638 def mcLog(self, message):
641 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
642 if not self.comm.isOperational():
644 if self.checkupState == 0:
645 self.tempCheckTimeout = 20
646 if temp[self.checkExtruderNr] > 70:
647 self.checkupState = 1
648 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
649 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
650 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
652 self.startTemp = temp[self.checkExtruderNr]
653 self.checkupState = 2
654 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
655 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
656 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
657 elif self.checkupState == 1:
658 if temp[self.checkExtruderNr] < 60:
659 self.startTemp = temp[self.checkExtruderNr]
660 self.checkupState = 2
661 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
662 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
663 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
664 elif self.checkupState == 2:
665 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
666 if temp[self.checkExtruderNr] > self.startTemp + 40:
667 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
668 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
669 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
670 self.checkExtruderNr = 0
671 self.checkupState = 3
672 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
673 wx.CallAfter(self.endstopBitmap.Show, True)
674 wx.CallAfter(self.Layout)
675 self.comm.sendCommand('M119')
676 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
678 self.checkupState = 0
679 self.checkExtruderNr += 1
681 self.tempCheckTimeout -= 1
682 if self.tempCheckTimeout < 1:
683 self.checkupState = -1
684 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
685 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
686 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
687 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
688 elif self.checkupState >= 3 and self.checkupState < 10:
689 self.comm.sendCommand('M119')
690 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
692 def mcStateChange(self, state):
693 if self.comm is None:
695 if self.comm.isOperational():
696 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
697 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
698 elif self.comm.isError():
699 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
700 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
701 wx.CallAfter(self.endstopBitmap.Show, False)
702 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
703 wx.CallAfter(self.errorLogButton.Show, True)
704 wx.CallAfter(self.Layout)
706 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
708 def mcMessage(self, message):
709 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
710 for data in message.split(' '):
712 tag, value = data.split(':', 1)
714 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
716 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
718 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
720 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
722 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
724 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
726 tag, value = map(str.strip, message.split(':', 1))
728 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
730 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
732 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
734 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
736 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
738 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
739 if 'z_max' in message:
740 self.comm.sendCommand('M119')
742 if self.checkupState == 3:
743 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
744 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
745 self.checkupState = 5
746 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
747 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
749 self.checkupState = 4
750 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
751 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
752 elif self.checkupState == 4:
753 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
754 self.checkupState = 5
755 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
756 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
757 elif self.checkupState == 5:
758 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
759 self.checkupState = 6
760 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
761 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
762 elif self.checkupState == 6:
763 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
764 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
765 self.checkupState = 8
766 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
767 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
769 self.checkupState = 7
770 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
771 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
772 elif self.checkupState == 7:
773 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
774 self.checkupState = 8
775 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
776 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
777 elif self.checkupState == 8:
778 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
779 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
780 self.checkupState = 10
782 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
783 wx.CallAfter(self.infoBox.SetReadyIndicator)
784 wx.CallAfter(self.endstopBitmap.Show, False)
785 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
786 wx.CallAfter(self.OnSkipClick, None)
788 self.checkupState = 9
789 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
790 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
791 elif self.checkupState == 9:
792 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
793 self.checkupState = 10
795 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
796 wx.CallAfter(self.infoBox.SetReadyIndicator)
797 wx.CallAfter(self.endstopBitmap.Show, False)
798 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
799 wx.CallAfter(self.OnSkipClick, None)
801 def mcProgress(self, lineNr):
804 def mcZChange(self, newZ):
808 class UltimakerCalibrationPage(InfoPage):
809 def __init__(self, parent):
810 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
812 self.AddText("Your Ultimaker requires some calibration.")
813 self.AddText("This calibration is needed for a proper extrusion amount.")
815 self.AddText("The following values are needed:")
816 self.AddText("* Diameter of filament")
817 self.AddText("* Number of steps per mm of filament extrusion")
819 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
821 self.AddText("First we need the diameter of your filament:")
822 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
824 "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.")
825 self.AddText("Note: This value can be changed later at any time.")
828 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
831 class UltimakerCalibrateStepsPerEPage(InfoPage):
832 def __init__(self, parent):
833 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
835 #if profile.getMachineSetting('steps_per_e') == '0':
836 # profile.putMachineSetting('steps_per_e', '865.888')
838 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
839 self.AddText(_("First remove any filament from your machine."))
840 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
841 self.AddText(_("We'll push the filament 100mm"))
842 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
843 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
844 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
845 self.AddText(_("This results in the following steps per E:"))
846 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
847 self.AddText(_("You can repeat these steps to get better calibration."))
850 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
851 self.heatButton = self.AddButton(_("Heatup for filament removal"))
853 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
854 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
855 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
857 def OnSaveLengthClick(self, e):
858 currentEValue = float(self.stepsPerEInput.GetValue())
859 realExtrudeLength = float(self.lengthInput.GetValue())
860 newEValue = currentEValue * 100 / realExtrudeLength
861 self.stepsPerEInput.SetValue(str(newEValue))
862 self.lengthInput.SetValue("100")
864 def OnExtrudeClick(self, e):
865 t = threading.Thread(target=self.OnExtrudeRun)
869 def OnExtrudeRun(self):
870 self.heatButton.Enable(False)
871 self.extrudeButton.Enable(False)
872 currentEValue = float(self.stepsPerEInput.GetValue())
873 self.comm = machineCom.MachineCom()
874 if not self.comm.isOpen():
876 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
877 'Printer error', wx.OK | wx.ICON_INFORMATION)
878 self.heatButton.Enable(True)
879 self.extrudeButton.Enable(True)
882 line = self.comm.readline()
887 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
890 self.sendGCommand('M302') #Disable cold extrusion protection
891 self.sendGCommand("M92 E%f" % (currentEValue))
892 self.sendGCommand("G92 E0")
893 self.sendGCommand("G1 E100 F600")
896 self.extrudeButton.Enable()
897 self.heatButton.Enable()
899 def OnHeatClick(self, e):
900 t = threading.Thread(target=self.OnHeatRun)
905 self.heatButton.Enable(False)
906 self.extrudeButton.Enable(False)
907 self.comm = machineCom.MachineCom()
908 if not self.comm.isOpen():
910 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
911 'Printer error', wx.OK | wx.ICON_INFORMATION)
912 self.heatButton.Enable(True)
913 self.extrudeButton.Enable(True)
916 line = self.comm.readline()
918 self.heatButton.Enable(True)
919 self.extrudeButton.Enable(True)
923 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
926 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
928 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
929 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
930 self.sendGCommand('M104 S0')
933 self.heatButton.Enable(True)
934 self.extrudeButton.Enable(True)
936 def sendGCommand(self, cmd):
937 self.comm.sendCommand(cmd) #Disable cold extrusion protection
939 line = self.comm.readline()
942 if line.startswith('ok'):
946 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
948 class Ultimaker2ReadyPage(InfoPage):
949 def __init__(self, parent):
950 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
951 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
952 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
955 class LulzbotReadyPage(InfoPage):
956 def __init__(self, parent):
957 super(LulzbotReadyPage, self).__init__(parent, _("LulzBot TAZ/Mini"))
958 self.AddText(_('Cura is now ready to be used with your LulzBot 3D printer.'))
960 self.AddText(_('For more information about using Cura with your LulzBot'))
961 self.AddText(_('3D printer, please visit www.LulzBot.com/cura'))
964 class ConfigWizard(wx.wizard.Wizard):
965 def __init__(self, addNew = False):
966 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
968 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
970 profile.setActiveMachine(profile.getMachineCount())
972 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
973 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
974 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
976 self.machineSelectPage = MachineSelectPage(self)
977 self.ultimakerSelectParts = SelectParts(self)
978 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
979 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
980 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
981 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
982 self.bedLevelPage = bedLevelWizardMain(self)
983 self.headOffsetCalibration = headOffsetCalibrationPage(self)
984 self.printrbotSelectType = PrintrbotPage(self)
985 self.otherMachineSelectPage = OtherMachineSelectPage(self)
986 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
987 self.otherMachineInfoPage = OtherMachineInfoPage(self)
989 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
990 self.lulzbotReadyPage = LulzbotReadyPage(self)
992 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
993 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
994 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
995 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
996 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
997 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
998 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
999 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1001 self.FitToPage(self.machineSelectPage)
1002 self.GetPageAreaSizer().Add(self.machineSelectPage)
1004 self.RunWizard(self.machineSelectPage)
1007 def OnPageChanging(self, e):
1008 e.GetPage().StoreData()
1010 def OnPageChanged(self, e):
1011 if e.GetPage().AllowNext():
1012 self.FindWindowById(wx.ID_FORWARD).Enable()
1014 self.FindWindowById(wx.ID_FORWARD).Disable()
1015 if e.GetPage().AllowBack():
1016 self.FindWindowById(wx.ID_BACKWARD).Enable()
1018 self.FindWindowById(wx.ID_BACKWARD).Disable()
1020 def OnCancel(self, e):
1021 profile.setActiveMachine(self._old_machine_index)
1023 class bedLevelWizardMain(InfoPage):
1024 def __init__(self, parent):
1025 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1027 self.AddText(_('This wizard will help you in leveling your printer bed'))
1029 self.AddText(_('It will do the following steps'))
1030 self.AddText(_('* Move the printer head to each corner'))
1031 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1032 self.AddText(_('* Print a line around the bed to check if it is level'))
1035 self.connectButton = self.AddButton(_('Connect to printer'))
1038 self.infoBox = self.AddInfoBox()
1039 self.resumeButton = self.AddButton(_('Resume'))
1040 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1041 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1042 self.resumeButton.Enable(False)
1044 self.upButton.Enable(False)
1045 self.downButton.Enable(False)
1046 self.upButton2.Enable(False)
1047 self.downButton2.Enable(False)
1049 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1050 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1051 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1052 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1053 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1054 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1056 def OnConnect(self, e = None):
1057 if self.comm is not None:
1061 wx.CallAfter(self.OnConnect)
1063 self.connectButton.Enable(False)
1064 self.comm = machineCom.MachineCom(callbackObject=self)
1065 self.infoBox.SetBusy(_('Connecting to machine.'))
1066 self._wizardState = 0
1068 def OnBedUp(self, e):
1069 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1070 self.comm.sendCommand('G92 Z10')
1071 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1072 self.comm.sendCommand('M400')
1074 def OnBedDown(self, e):
1075 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1076 self.comm.sendCommand('G92 Z10')
1077 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1078 self.comm.sendCommand('M400')
1080 def OnBedUp2(self, e):
1081 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1082 self.comm.sendCommand('G92 Z10')
1083 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1084 self.comm.sendCommand('M400')
1086 def OnBedDown2(self, e):
1087 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1088 self.comm.sendCommand('G92 Z10')
1089 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1090 self.comm.sendCommand('M400')
1092 def AllowNext(self):
1093 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1094 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1097 def OnResume(self, e):
1098 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1099 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1100 if self._wizardState == -1:
1101 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1102 wx.CallAfter(self.upButton.Enable, False)
1103 wx.CallAfter(self.downButton.Enable, False)
1104 wx.CallAfter(self.upButton2.Enable, False)
1105 wx.CallAfter(self.downButton2.Enable, False)
1106 self.comm.sendCommand('M105')
1107 self.comm.sendCommand('G28')
1108 self._wizardState = 1
1109 elif self._wizardState == 2:
1110 if profile.getMachineSetting('has_heated_bed') == 'True':
1111 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1112 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1113 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1114 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1115 self.comm.sendCommand('M400')
1116 self._wizardState = 3
1118 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1119 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1120 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1121 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1122 self.comm.sendCommand('M400')
1123 self._wizardState = 3
1124 elif self._wizardState == 4:
1125 if profile.getMachineSetting('has_heated_bed') == 'True':
1126 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1127 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1128 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1129 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1130 self.comm.sendCommand('M400')
1131 self._wizardState = 7
1133 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1134 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1135 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1136 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1137 self.comm.sendCommand('M400')
1138 self._wizardState = 5
1139 elif self._wizardState == 6:
1140 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1141 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1142 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1143 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1144 self.comm.sendCommand('M400')
1145 self._wizardState = 7
1146 elif self._wizardState == 8:
1147 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1148 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1149 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1150 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1151 self._wizardState = 9
1152 elif self._wizardState == 10:
1153 self._wizardState = 11
1154 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1155 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1156 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1157 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1158 w = profile.getMachineSettingFloat('machine_width') - 10
1159 d = profile.getMachineSettingFloat('machine_depth')
1160 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1161 filamentArea = math.pi * filamentRadius * filamentRadius
1162 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1166 'G1 Z2 F%d' % (feedZ),
1168 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1169 'G1 Z0.3 F%d' % (feedZ)]
1171 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1173 for i in xrange(0, 3):
1174 dist = 5.0 + 0.4 * float(i)
1175 eValue += (d - 2.0*dist) * ePerMM
1176 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1177 eValue += (w - 2.0*dist) * ePerMM
1178 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1179 eValue += (d - 2.0*dist) * ePerMM
1180 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1181 eValue += (w - 2.0*dist) * ePerMM
1182 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1184 gcodeList.append('M400')
1185 self.comm.printGCode(gcodeList)
1186 self.resumeButton.Enable(False)
1188 def mcLog(self, message):
1189 print 'Log:', message
1191 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1192 if self._wizardState == 1:
1193 self._wizardState = 2
1194 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1195 wx.CallAfter(self.resumeButton.Enable, True)
1196 elif self._wizardState == 3:
1197 self._wizardState = 4
1198 if profile.getMachineSetting('has_heated_bed') == 'True':
1199 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1201 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1202 wx.CallAfter(self.resumeButton.Enable, True)
1203 elif self._wizardState == 5:
1204 self._wizardState = 6
1205 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1206 wx.CallAfter(self.resumeButton.Enable, True)
1207 elif self._wizardState == 7:
1208 self._wizardState = 8
1209 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1210 wx.CallAfter(self.resumeButton.Enable, True)
1211 elif self._wizardState == 9:
1212 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1213 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1215 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1216 wx.CallAfter(self.resumeButton.Enable, True)
1217 self._wizardState = 10
1219 def mcStateChange(self, state):
1220 if self.comm is None:
1222 if self.comm.isOperational():
1223 if self._wizardState == 0:
1224 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1225 wx.CallAfter(self.upButton.Enable, True)
1226 wx.CallAfter(self.downButton.Enable, True)
1227 wx.CallAfter(self.upButton2.Enable, True)
1228 wx.CallAfter(self.downButton2.Enable, True)
1229 wx.CallAfter(self.resumeButton.Enable, True)
1230 self._wizardState = -1
1231 elif self._wizardState == 11 and not self.comm.isPrinting():
1232 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1233 self.comm.sendCommand('G92 E0')
1234 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1235 self.comm.sendCommand('M104 S0')
1236 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1237 wx.CallAfter(self.infoBox.SetReadyIndicator)
1238 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1239 wx.CallAfter(self.connectButton.Enable, True)
1240 self._wizardState = 12
1241 elif self.comm.isError():
1242 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1244 def mcMessage(self, message):
1247 def mcProgress(self, lineNr):
1250 def mcZChange(self, newZ):
1253 class headOffsetCalibrationPage(InfoPage):
1254 def __init__(self, parent):
1255 super(headOffsetCalibrationPage, self).__init__(parent, _("Printer head offset calibration"))
1257 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1260 self.connectButton = self.AddButton(_('Connect to printer'))
1263 self.infoBox = self.AddInfoBox()
1264 self.textEntry = self.AddTextCtrl('')
1265 self.textEntry.Enable(False)
1266 self.resumeButton = self.AddButton(_('Resume'))
1267 self.resumeButton.Enable(False)
1269 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1270 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1272 def AllowBack(self):
1275 def OnConnect(self, e = None):
1276 if self.comm is not None:
1280 wx.CallAfter(self.OnConnect)
1282 self.connectButton.Enable(False)
1283 self.comm = machineCom.MachineCom(callbackObject=self)
1284 self.infoBox.SetBusy(_('Connecting to machine.'))
1285 self._wizardState = 0
1287 def OnResume(self, e):
1288 if self._wizardState == 2:
1289 self._wizardState = 3
1290 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1292 w = profile.getMachineSettingFloat('machine_width')
1293 d = profile.getMachineSettingFloat('machine_depth')
1295 gcode = gcodeGenerator.gcodeGenerator()
1296 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1297 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1304 gcode.addMove(w/2, 5)
1305 gcode.addMove(z=0.2)
1307 gcode.addExtrude(w/2, d-5.0)
1309 gcode.addMove(5, d/2)
1311 gcode.addExtrude(w-5.0, d/2)
1312 gcode.addRetract(15)
1315 gcode.addMove(w/2, 5)
1317 gcode.addExtrude(w/2, d-5.0)
1319 gcode.addMove(5, d/2)
1321 gcode.addExtrude(w-5.0, d/2)
1322 gcode.addRetract(15)
1327 gcode.addCmd('M400')
1329 self.comm.printGCode(gcode.list())
1330 self.resumeButton.Enable(False)
1331 elif self._wizardState == 4:
1333 float(self.textEntry.GetValue())
1336 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1337 self._wizardState = 5
1338 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1339 self.textEntry.SetValue('0.0')
1340 self.textEntry.Enable(True)
1341 elif self._wizardState == 5:
1343 float(self.textEntry.GetValue())
1346 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1347 self._wizardState = 6
1348 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1349 self.textEntry.SetValue('')
1350 self.textEntry.Enable(False)
1351 self.resumeButton.Enable(False)
1353 x = profile.getMachineSettingFloat('extruder_offset_x1')
1354 y = profile.getMachineSettingFloat('extruder_offset_y1')
1355 gcode = gcodeGenerator.gcodeGenerator()
1356 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1357 gcode.setPrintSpeed(25)
1360 gcode.addMove(50, 40, 0.2)
1362 for n in xrange(0, 10):
1363 gcode.addExtrude(50 + n * 10, 150)
1364 gcode.addExtrude(50 + n * 10 + 5, 150)
1365 gcode.addExtrude(50 + n * 10 + 5, 40)
1366 gcode.addExtrude(50 + n * 10 + 10, 40)
1367 gcode.addMove(40, 50)
1368 for n in xrange(0, 10):
1369 gcode.addExtrude(150, 50 + n * 10)
1370 gcode.addExtrude(150, 50 + n * 10 + 5)
1371 gcode.addExtrude(40, 50 + n * 10 + 5)
1372 gcode.addExtrude(40, 50 + n * 10 + 10)
1373 gcode.addRetract(15)
1376 gcode.addMove(50 - x, 30 - y, 0.2)
1378 for n in xrange(0, 10):
1379 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1380 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1381 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1382 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1383 gcode.addMove(30 - x, 50 - y, 0.2)
1384 for n in xrange(0, 10):
1385 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1386 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1387 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1388 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1389 gcode.addRetract(15)
1391 gcode.addCmd('M400')
1392 gcode.addCmd('M104 T0 S0')
1393 gcode.addCmd('M104 T1 S0')
1394 self.comm.printGCode(gcode.list())
1395 elif self._wizardState == 7:
1397 n = int(self.textEntry.GetValue()) - 1
1400 x = profile.getMachineSettingFloat('extruder_offset_x1')
1402 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1403 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1404 self.textEntry.SetValue('10')
1405 self._wizardState = 8
1406 elif self._wizardState == 8:
1408 n = int(self.textEntry.GetValue()) - 1
1411 y = profile.getMachineSettingFloat('extruder_offset_y1')
1413 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1414 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1415 self.infoBox.SetReadyIndicator()
1416 self._wizardState = 8
1418 self.resumeButton.Enable(False)
1420 def mcLog(self, message):
1421 print 'Log:', message
1423 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1424 if self._wizardState == 1:
1425 if temp[0] >= 210 and temp[1] >= 210:
1426 self._wizardState = 2
1427 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1428 wx.CallAfter(self.resumeButton.Enable, True)
1429 wx.CallAfter(self.resumeButton.SetFocus)
1431 def mcStateChange(self, state):
1432 if self.comm is None:
1434 if self.comm.isOperational():
1435 if self._wizardState == 0:
1436 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1437 self.comm.sendCommand('M105')
1438 self.comm.sendCommand('M104 S220 T0')
1439 self.comm.sendCommand('M104 S220 T1')
1440 self.comm.sendCommand('G28')
1441 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1442 self._wizardState = 1
1443 if not self.comm.isPrinting():
1444 if self._wizardState == 3:
1445 self._wizardState = 4
1446 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1447 wx.CallAfter(self.textEntry.SetValue, '0.0')
1448 wx.CallAfter(self.textEntry.Enable, True)
1449 wx.CallAfter(self.resumeButton.Enable, True)
1450 wx.CallAfter(self.resumeButton.SetFocus)
1451 elif self._wizardState == 6:
1452 self._wizardState = 7
1453 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1454 wx.CallAfter(self.textEntry.SetValue, '10')
1455 wx.CallAfter(self.textEntry.Enable, True)
1456 wx.CallAfter(self.resumeButton.Enable, True)
1457 wx.CallAfter(self.resumeButton.SetFocus)
1459 elif self.comm.isError():
1460 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1462 def mcMessage(self, message):
1465 def mcProgress(self, lineNr):
1468 def mcZChange(self, newZ):
1471 class bedLevelWizard(wx.wizard.Wizard):
1473 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1475 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1476 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1478 self.mainPage = bedLevelWizardMain(self)
1479 self.headOffsetCalibration = None
1481 self.FitToPage(self.mainPage)
1482 self.GetPageAreaSizer().Add(self.mainPage)
1484 self.RunWizard(self.mainPage)
1487 def OnPageChanging(self, e):
1488 e.GetPage().StoreData()
1490 def OnPageChanged(self, e):
1491 if e.GetPage().AllowNext():
1492 self.FindWindowById(wx.ID_FORWARD).Enable()
1494 self.FindWindowById(wx.ID_FORWARD).Disable()
1495 if e.GetPage().AllowBack():
1496 self.FindWindowById(wx.ID_BACKWARD).Enable()
1498 self.FindWindowById(wx.ID_BACKWARD).Disable()
1500 class headOffsetWizard(wx.wizard.Wizard):
1502 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
1504 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1505 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1507 self.mainPage = headOffsetCalibrationPage(self)
1509 self.FitToPage(self.mainPage)
1510 self.GetPageAreaSizer().Add(self.mainPage)
1512 self.RunWizard(self.mainPage)
1515 def OnPageChanging(self, e):
1516 e.GetPage().StoreData()
1518 def OnPageChanged(self, e):
1519 if e.GetPage().AllowNext():
1520 self.FindWindowById(wx.ID_FORWARD).Enable()
1522 self.FindWindowById(wx.ID_FORWARD).Disable()
1523 if e.GetPage().AllowBack():
1524 self.FindWindowById(wx.ID_BACKWARD).Enable()
1526 self.FindWindowById(wx.ID_BACKWARD).Disable()