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", 150, 150, 150, 1.75, 208, 40, 70, 30, 1),#TODO: Check info
233 ("Simple Makers Kit", 150, 150, 150, 1.75, 208, 40, 70, 30, 1),#TODO: Check info
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),
250 super(PrintrbotPage, self).__init__(parent, _("Printrbot Selection"))
251 self.AddText(_("Select which Printrbot machine you have:"))
253 for printer in self._printer_info:
254 if printer[0].startswith(":"):
256 self.AddText(printer[0][1:])
258 item = self.AddRadioButton(printer[0])
259 item.data = printer[1:]
260 self._items.append(item)
263 profile.putMachineSetting('machine_name', 'Printrbot ???')
264 for item in self._items:
267 profile.putMachineSetting('machine_name', 'Printrbot ' + item.GetLabel())
268 profile.putMachineSetting('machine_width', data[0])
269 profile.putMachineSetting('machine_depth', data[1])
270 profile.putMachineSetting('machine_height', data[2])
271 profile.putProfileSetting('nozzle_size', '0.5')
272 profile.putProfileSetting('filament_diameter', data[3])
273 profile.putProfileSetting('print_temperature', data[4])
274 profile.putProfileSetting('print_speed', data[5])
275 profile.putProfileSetting('travel_speed', data[6])
276 profile.putProfileSetting('retraction_speed', data[7])
277 profile.putProfileSetting('retraction_amount', data[8])
278 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
279 profile.putMachineSetting('has_heated_bed', 'False')
280 profile.putMachineSetting('machine_center_is_zero', 'False')
281 profile.putMachineSetting('extruder_head_size_min_x', '0')
282 profile.putMachineSetting('extruder_head_size_min_y', '0')
283 profile.putMachineSetting('extruder_head_size_max_x', '0')
284 profile.putMachineSetting('extruder_head_size_max_y', '0')
285 profile.putMachineSetting('extruder_head_size_height', '0')
287 class OtherMachineSelectPage(InfoPage):
288 def __init__(self, parent):
289 super(OtherMachineSelectPage, self).__init__(parent, _("Other machine information"))
290 self.AddText(_("The following pre-defined machine profiles are available"))
291 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."))
293 machines = resources.getDefaultMachineProfiles()
295 for filename in machines:
296 name = os.path.splitext(os.path.basename(filename))[0]
297 item = self.AddRadioButton(name)
298 item.filename = filename
299 item.Bind(wx.EVT_RADIOBUTTON, self.OnProfileSelect)
300 self.options.append(item)
302 item = self.AddRadioButton(_('Custom...'))
304 item.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
306 def OnProfileSelect(self, e):
307 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineInfoPage)
309 def OnOtherSelect(self, e):
310 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().customRepRapInfoPage)
313 for option in self.options:
314 if option.GetValue():
315 profile.loadProfile(option.filename)
316 profile.loadMachineSettings(option.filename)
318 class OtherMachineInfoPage(InfoPage):
319 def __init__(self, parent):
320 super(OtherMachineInfoPage, self).__init__(parent, _("Cura Ready!"))
321 self.AddText(_("Cura is now ready to be used!"))
323 class CustomRepRapInfoPage(InfoPage):
324 def __init__(self, parent):
325 super(CustomRepRapInfoPage, self).__init__(parent, _("Custom RepRap information"))
326 self.AddText(_("RepRap machines can be vastly different, so here you can set your own settings."))
327 self.AddText(_("Be sure to review the default profile before running it on your machine."))
328 self.AddText(_("If you like a default profile for your machine added,\nthen make an issue on github."))
330 self.AddText(_("You will have to manually install Marlin or Sprinter firmware."))
332 self.machineName = self.AddLabelTextCtrl(_("Machine name"), "RepRap")
333 self.machineWidth = self.AddLabelTextCtrl(_("Machine width (mm)"), "80")
334 self.machineDepth = self.AddLabelTextCtrl(_("Machine depth (mm)"), "80")
335 self.machineHeight = self.AddLabelTextCtrl(_("Machine height (mm)"), "55")
336 self.nozzleSize = self.AddLabelTextCtrl(_("Nozzle size (mm)"), "0.5")
337 self.heatedBed = self.AddCheckbox(_("Heated bed"))
338 self.HomeAtCenter = self.AddCheckbox(_("Bed center is 0,0,0 (RoStock)"))
341 profile.putMachineSetting('machine_name', self.machineName.GetValue())
342 profile.putMachineSetting('machine_width', self.machineWidth.GetValue())
343 profile.putMachineSetting('machine_depth', self.machineDepth.GetValue())
344 profile.putMachineSetting('machine_height', self.machineHeight.GetValue())
345 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
346 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
347 profile.putMachineSetting('has_heated_bed', str(self.heatedBed.GetValue()))
348 profile.putMachineSetting('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
349 profile.putMachineSetting('extruder_head_size_min_x', '0')
350 profile.putMachineSetting('extruder_head_size_min_y', '0')
351 profile.putMachineSetting('extruder_head_size_max_x', '0')
352 profile.putMachineSetting('extruder_head_size_max_y', '0')
353 profile.putMachineSetting('extruder_head_size_height', '0')
354 profile.checkAndUpdateMachineName()
356 class MachineSelectPage(InfoPage):
357 def __init__(self, parent):
358 super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
359 self.AddText(_("What kind of machine do you have:"))
361 self.LulzbotMiniRadio = self.AddRadioButton("LulzBot Mini", style=wx.RB_GROUP)
362 self.LulzbotMiniRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
363 self.LulzbotMiniRadio.SetValue(True)
364 self.LulzbotTazRadio = self.AddRadioButton("LulzBot TAZ")
365 self.LulzbotTazRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
366 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2")
367 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
368 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
369 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
370 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
371 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
372 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
373 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
374 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
375 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
377 def OnUltimaker2Select(self, e):
378 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
380 def OnUltimakerSelect(self, e):
381 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
383 def OnUltimakerOPSelect(self, e):
384 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
386 def OnPrintrbotSelect(self, e):
387 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
389 def OnLulzbotSelect(self, e):
390 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
392 def OnOtherSelect(self, e):
393 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
396 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
400 profile.putProfileSetting('retraction_enable', 'True')
401 if self.Ultimaker2Radio.GetValue():
402 profile.putMachineSetting('machine_width', '230')
403 profile.putMachineSetting('machine_depth', '225')
404 profile.putMachineSetting('machine_height', '205')
405 profile.putMachineSetting('machine_name', 'ultimaker2')
406 profile.putMachineSetting('machine_type', 'ultimaker2')
407 profile.putMachineSetting('machine_center_is_zero', 'False')
408 profile.putMachineSetting('has_heated_bed', 'True')
409 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
410 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
411 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
412 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
413 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
414 profile.putMachineSetting('extruder_head_size_height', '48.0')
415 profile.putProfileSetting('nozzle_size', '0.4')
416 profile.putProfileSetting('fan_full_height', '5.0')
417 profile.putMachineSetting('extruder_offset_x1', '18.0')
418 profile.putMachineSetting('extruder_offset_y1', '0.0')
419 elif self.UltimakerRadio.GetValue():
420 profile.putMachineSetting('machine_width', '205')
421 profile.putMachineSetting('machine_depth', '205')
422 profile.putMachineSetting('machine_height', '200')
423 profile.putMachineSetting('machine_name', 'ultimaker original')
424 profile.putMachineSetting('machine_type', 'ultimaker')
425 profile.putMachineSetting('machine_center_is_zero', 'False')
426 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
427 profile.putProfileSetting('nozzle_size', '0.4')
428 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
429 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
430 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
431 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
432 profile.putMachineSetting('extruder_head_size_height', '55.0')
433 elif self.UltimakerOPRadio.GetValue():
434 profile.putMachineSetting('machine_width', '205')
435 profile.putMachineSetting('machine_depth', '205')
436 profile.putMachineSetting('machine_height', '200')
437 profile.putMachineSetting('machine_name', 'ultimaker original+')
438 profile.putMachineSetting('machine_type', 'ultimaker_plus')
439 profile.putMachineSetting('machine_center_is_zero', 'False')
440 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
441 profile.putProfileSetting('nozzle_size', '0.4')
442 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
443 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
444 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
445 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
446 profile.putMachineSetting('extruder_head_size_height', '55.0')
447 profile.putMachineSetting('has_heated_bed', 'True')
448 profile.putMachineSetting('extruder_amount', '1')
449 profile.putProfileSetting('retraction_enable', 'True')
450 elif self.LulzbotTazRadio.GetValue() or self.LulzbotMiniRadio.GetValue():
451 if self.LulzbotTazRadio.GetValue():
452 profile.putMachineSetting('machine_width', '298')
453 profile.putMachineSetting('machine_depth', '275')
454 profile.putMachineSetting('machine_height', '250')
455 profile.putProfileSetting('nozzle_size', '0.35')
456 profile.putMachineSetting('machine_name', 'LulzBot TAZ')
457 profile.putMachineSetting('machine_type', 'lulzbot_TAZ')
458 profile.putMachineSetting('serial_baud', '115200')
460 profile.putMachineSetting('machine_width', '155')
461 profile.putMachineSetting('machine_depth', '155')
462 profile.putMachineSetting('machine_height', '163')
463 profile.putProfileSetting('nozzle_size', '0.5')
464 profile.putMachineSetting('machine_name', 'LulzBot Mini')
465 profile.putMachineSetting('machine_type', 'lulzbot_mini')
466 profile.putMachineSetting('serial_baud', '115200')
467 profile.putMachineSetting('machine_center_is_zero', 'False')
468 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
469 profile.putMachineSetting('has_heated_bed', 'True')
470 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
471 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
472 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
473 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
474 profile.putMachineSetting('extruder_head_size_height', '0.0')
476 profile.putMachineSetting('machine_width', '80')
477 profile.putMachineSetting('machine_depth', '80')
478 profile.putMachineSetting('machine_height', '60')
479 profile.putMachineSetting('machine_name', 'reprap')
480 profile.putMachineSetting('machine_type', 'reprap')
481 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
482 profile.putPreference('startMode', 'Normal')
483 profile.putProfileSetting('nozzle_size', '0.5')
484 profile.checkAndUpdateMachineName()
485 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
487 class SelectParts(InfoPage):
488 def __init__(self, parent):
489 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
490 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."))
492 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
493 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
494 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
495 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
497 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."))
498 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
499 self.springExtruder.SetValue(True)
502 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
503 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
504 profile.putMachineSetting('has_heated_bed', 'True')
506 profile.putMachineSetting('has_heated_bed', 'False')
507 if self.dualExtrusion.GetValue():
508 profile.putMachineSetting('extruder_amount', '2')
509 profile.putMachineSetting('machine_depth', '195')
511 profile.putMachineSetting('extruder_amount', '1')
512 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
513 profile.putProfileSetting('retraction_enable', 'True')
515 profile.putProfileSetting('retraction_enable', 'False')
518 class UltimakerFirmwareUpgradePage(InfoPage):
519 def __init__(self, parent):
520 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
521 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."))
522 self.AddHiddenSeperator()
523 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
524 self.AddHiddenSeperator()
525 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."))
526 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Upgrade to Marlin firmware'), _('Skip upgrade'))
527 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
528 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
529 self.AddHiddenSeperator()
530 if profile.getMachineSetting('machine_type') == 'ultimaker':
531 self.AddText(_("Do not upgrade to this firmware if:"))
532 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
533 self.AddText(_("* Build your own heated bed"))
534 self.AddText(_("* Have other changes in the firmware"))
535 # button = self.AddButton('Goto this page for a custom firmware')
536 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
541 def OnUpgradeClick(self, e):
542 if firmwareInstall.InstallFirmware():
543 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
545 def OnSkipClick(self, e):
546 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
547 self.GetParent().ShowPage(self.GetNext())
549 def OnUrlClick(self, e):
550 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
552 class UltimakerCheckupPage(InfoPage):
553 def __init__(self, parent):
554 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
556 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
557 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
558 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
559 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
560 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
561 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
562 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
563 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
564 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
565 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
568 _("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."))
569 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
570 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
571 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
573 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
574 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
575 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
577 self.infoBox = self.AddInfoBox()
578 self.machineState = self.AddText("")
579 self.temperatureLabel = self.AddText("")
580 self.errorLogButton = self.AddButton(_("Show error log"))
581 self.errorLogButton.Show(False)
583 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
585 self.xMinStop = False
586 self.xMaxStop = False
587 self.yMinStop = False
588 self.yMaxStop = False
589 self.zMinStop = False
590 self.zMaxStop = False
592 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
595 if self.comm is not None:
599 self.endstopBitmap.Show(False)
602 def OnSkipClick(self, e):
603 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
604 self.GetParent().ShowPage(self.GetNext())
606 def OnCheckClick(self, e=None):
607 self.errorLogButton.Show(False)
608 if self.comm is not None:
612 wx.CallAfter(self.OnCheckClick)
614 self.infoBox.SetBusy(_("Connecting to machine."))
615 self.commState.SetBitmap(self.unknownBitmap)
616 self.tempState.SetBitmap(self.unknownBitmap)
617 self.stopState.SetBitmap(self.unknownBitmap)
618 self.checkupState = 0
619 self.checkExtruderNr = 0
620 self.comm = machineCom.MachineCom(callbackObject=self)
622 def OnErrorLog(self, e):
623 printWindow.LogWindow('\n'.join(self.comm.getLog()))
625 def mcLog(self, message):
628 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
629 if not self.comm.isOperational():
631 if self.checkupState == 0:
632 self.tempCheckTimeout = 20
633 if temp[self.checkExtruderNr] > 70:
634 self.checkupState = 1
635 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
636 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
637 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
639 self.startTemp = temp[self.checkExtruderNr]
640 self.checkupState = 2
641 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
642 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
643 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
644 elif self.checkupState == 1:
645 if temp[self.checkExtruderNr] < 60:
646 self.startTemp = temp[self.checkExtruderNr]
647 self.checkupState = 2
648 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
649 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
650 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
651 elif self.checkupState == 2:
652 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
653 if temp[self.checkExtruderNr] > self.startTemp + 40:
654 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
655 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
656 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
657 self.checkExtruderNr = 0
658 self.checkupState = 3
659 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
660 wx.CallAfter(self.endstopBitmap.Show, True)
661 wx.CallAfter(self.Layout)
662 self.comm.sendCommand('M119')
663 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
665 self.checkupState = 0
666 self.checkExtruderNr += 1
668 self.tempCheckTimeout -= 1
669 if self.tempCheckTimeout < 1:
670 self.checkupState = -1
671 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
672 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
673 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
674 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
675 elif self.checkupState >= 3 and self.checkupState < 10:
676 self.comm.sendCommand('M119')
677 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
679 def mcStateChange(self, state):
680 if self.comm is None:
682 if self.comm.isOperational():
683 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
684 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
685 elif self.comm.isError():
686 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
687 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
688 wx.CallAfter(self.endstopBitmap.Show, False)
689 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
690 wx.CallAfter(self.errorLogButton.Show, True)
691 wx.CallAfter(self.Layout)
693 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
695 def mcMessage(self, message):
696 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
697 for data in message.split(' '):
699 tag, value = data.split(':', 1)
701 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
703 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
705 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
707 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
709 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
711 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
713 tag, value = map(str.strip, message.split(':', 1))
715 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
717 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
719 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
721 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
723 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
725 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
726 if 'z_max' in message:
727 self.comm.sendCommand('M119')
729 if self.checkupState == 3:
730 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
731 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
732 self.checkupState = 5
733 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
734 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
736 self.checkupState = 4
737 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
738 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
739 elif self.checkupState == 4:
740 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
741 self.checkupState = 5
742 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
743 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
744 elif self.checkupState == 5:
745 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
746 self.checkupState = 6
747 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
748 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
749 elif self.checkupState == 6:
750 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
751 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
752 self.checkupState = 8
753 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
754 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
756 self.checkupState = 7
757 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
758 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
759 elif self.checkupState == 7:
760 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
761 self.checkupState = 8
762 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
763 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
764 elif self.checkupState == 8:
765 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
766 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
767 self.checkupState = 10
769 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
770 wx.CallAfter(self.infoBox.SetReadyIndicator)
771 wx.CallAfter(self.endstopBitmap.Show, False)
772 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
773 wx.CallAfter(self.OnSkipClick, None)
775 self.checkupState = 9
776 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
777 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
778 elif self.checkupState == 9:
779 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
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 def mcProgress(self, lineNr):
791 def mcZChange(self, newZ):
795 class UltimakerCalibrationPage(InfoPage):
796 def __init__(self, parent):
797 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
799 self.AddText("Your Ultimaker requires some calibration.")
800 self.AddText("This calibration is needed for a proper extrusion amount.")
802 self.AddText("The following values are needed:")
803 self.AddText("* Diameter of filament")
804 self.AddText("* Number of steps per mm of filament extrusion")
806 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
808 self.AddText("First we need the diameter of your filament:")
809 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
811 "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.")
812 self.AddText("Note: This value can be changed later at any time.")
815 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
818 class UltimakerCalibrateStepsPerEPage(InfoPage):
819 def __init__(self, parent):
820 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
822 #if profile.getMachineSetting('steps_per_e') == '0':
823 # profile.putMachineSetting('steps_per_e', '865.888')
825 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
826 self.AddText(_("First remove any filament from your machine."))
827 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
828 self.AddText(_("We'll push the filament 100mm"))
829 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
830 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
831 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
832 self.AddText(_("This results in the following steps per E:"))
833 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
834 self.AddText(_("You can repeat these steps to get better calibration."))
837 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
838 self.heatButton = self.AddButton(_("Heatup for filament removal"))
840 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
841 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
842 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
844 def OnSaveLengthClick(self, e):
845 currentEValue = float(self.stepsPerEInput.GetValue())
846 realExtrudeLength = float(self.lengthInput.GetValue())
847 newEValue = currentEValue * 100 / realExtrudeLength
848 self.stepsPerEInput.SetValue(str(newEValue))
849 self.lengthInput.SetValue("100")
851 def OnExtrudeClick(self, e):
852 t = threading.Thread(target=self.OnExtrudeRun)
856 def OnExtrudeRun(self):
857 self.heatButton.Enable(False)
858 self.extrudeButton.Enable(False)
859 currentEValue = float(self.stepsPerEInput.GetValue())
860 self.comm = machineCom.MachineCom()
861 if not self.comm.isOpen():
863 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
864 'Printer error', wx.OK | wx.ICON_INFORMATION)
865 self.heatButton.Enable(True)
866 self.extrudeButton.Enable(True)
869 line = self.comm.readline()
874 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
877 self.sendGCommand('M302') #Disable cold extrusion protection
878 self.sendGCommand("M92 E%f" % (currentEValue))
879 self.sendGCommand("G92 E0")
880 self.sendGCommand("G1 E100 F600")
883 self.extrudeButton.Enable()
884 self.heatButton.Enable()
886 def OnHeatClick(self, e):
887 t = threading.Thread(target=self.OnHeatRun)
892 self.heatButton.Enable(False)
893 self.extrudeButton.Enable(False)
894 self.comm = machineCom.MachineCom()
895 if not self.comm.isOpen():
897 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
898 'Printer error', wx.OK | wx.ICON_INFORMATION)
899 self.heatButton.Enable(True)
900 self.extrudeButton.Enable(True)
903 line = self.comm.readline()
905 self.heatButton.Enable(True)
906 self.extrudeButton.Enable(True)
910 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
913 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
915 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
916 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
917 self.sendGCommand('M104 S0')
920 self.heatButton.Enable(True)
921 self.extrudeButton.Enable(True)
923 def sendGCommand(self, cmd):
924 self.comm.sendCommand(cmd) #Disable cold extrusion protection
926 line = self.comm.readline()
929 if line.startswith('ok'):
933 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
935 class Ultimaker2ReadyPage(InfoPage):
936 def __init__(self, parent):
937 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
938 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
939 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
942 class LulzbotReadyPage(InfoPage):
943 def __init__(self, parent):
944 super(LulzbotReadyPage, self).__init__(parent, _("LulzBot TAZ/Mini"))
945 self.AddText(_('Cura is now ready to be used with your LulzBot 3D printer.'))
947 self.AddText(_('For more information about using Cura with your LulzBot'))
948 self.AddText(_('3D printer, please visit www.LulzBot.com/cura'))
951 class ConfigWizard(wx.wizard.Wizard):
952 def __init__(self, addNew = False):
953 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
955 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
957 profile.setActiveMachine(profile.getMachineCount())
959 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
960 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
961 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
963 self.machineSelectPage = MachineSelectPage(self)
964 self.ultimakerSelectParts = SelectParts(self)
965 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
966 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
967 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
968 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
969 self.bedLevelPage = bedLevelWizardMain(self)
970 self.headOffsetCalibration = headOffsetCalibrationPage(self)
971 self.printrbotSelectType = PrintrbotPage(self)
972 self.otherMachineSelectPage = OtherMachineSelectPage(self)
973 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
974 self.otherMachineInfoPage = OtherMachineInfoPage(self)
976 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
977 self.lulzbotReadyPage = LulzbotReadyPage(self)
979 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
980 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
981 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
982 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
983 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
984 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
985 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
986 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
988 self.FitToPage(self.machineSelectPage)
989 self.GetPageAreaSizer().Add(self.machineSelectPage)
991 self.RunWizard(self.machineSelectPage)
994 def OnPageChanging(self, e):
995 e.GetPage().StoreData()
997 def OnPageChanged(self, e):
998 if e.GetPage().AllowNext():
999 self.FindWindowById(wx.ID_FORWARD).Enable()
1001 self.FindWindowById(wx.ID_FORWARD).Disable()
1002 if e.GetPage().AllowBack():
1003 self.FindWindowById(wx.ID_BACKWARD).Enable()
1005 self.FindWindowById(wx.ID_BACKWARD).Disable()
1007 def OnCancel(self, e):
1008 profile.setActiveMachine(self._old_machine_index)
1010 class bedLevelWizardMain(InfoPage):
1011 def __init__(self, parent):
1012 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1014 self.AddText(_('This wizard will help you in leveling your printer bed'))
1016 self.AddText(_('It will do the following steps'))
1017 self.AddText(_('* Move the printer head to each corner'))
1018 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1019 self.AddText(_('* Print a line around the bed to check if it is level'))
1022 self.connectButton = self.AddButton(_('Connect to printer'))
1025 self.infoBox = self.AddInfoBox()
1026 self.resumeButton = self.AddButton(_('Resume'))
1027 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1028 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1029 self.resumeButton.Enable(False)
1031 self.upButton.Enable(False)
1032 self.downButton.Enable(False)
1033 self.upButton2.Enable(False)
1034 self.downButton2.Enable(False)
1036 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1037 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1038 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1039 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1040 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1041 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1043 def OnConnect(self, e = None):
1044 if self.comm is not None:
1048 wx.CallAfter(self.OnConnect)
1050 self.connectButton.Enable(False)
1051 self.comm = machineCom.MachineCom(callbackObject=self)
1052 self.infoBox.SetBusy(_('Connecting to machine.'))
1053 self._wizardState = 0
1055 def OnBedUp(self, e):
1056 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1057 self.comm.sendCommand('G92 Z10')
1058 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1059 self.comm.sendCommand('M400')
1061 def OnBedDown(self, e):
1062 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1063 self.comm.sendCommand('G92 Z10')
1064 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1065 self.comm.sendCommand('M400')
1067 def OnBedUp2(self, e):
1068 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1069 self.comm.sendCommand('G92 Z10')
1070 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1071 self.comm.sendCommand('M400')
1073 def OnBedDown2(self, e):
1074 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1075 self.comm.sendCommand('G92 Z10')
1076 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1077 self.comm.sendCommand('M400')
1079 def AllowNext(self):
1080 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1081 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1084 def OnResume(self, e):
1085 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1086 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1087 if self._wizardState == -1:
1088 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1089 wx.CallAfter(self.upButton.Enable, False)
1090 wx.CallAfter(self.downButton.Enable, False)
1091 wx.CallAfter(self.upButton2.Enable, False)
1092 wx.CallAfter(self.downButton2.Enable, False)
1093 self.comm.sendCommand('M105')
1094 self.comm.sendCommand('G28')
1095 self._wizardState = 1
1096 elif self._wizardState == 2:
1097 if profile.getMachineSetting('has_heated_bed') == 'True':
1098 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1099 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1100 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1101 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1102 self.comm.sendCommand('M400')
1103 self._wizardState = 3
1105 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1106 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1107 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1108 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1109 self.comm.sendCommand('M400')
1110 self._wizardState = 3
1111 elif self._wizardState == 4:
1112 if profile.getMachineSetting('has_heated_bed') == 'True':
1113 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1114 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1115 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1116 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1117 self.comm.sendCommand('M400')
1118 self._wizardState = 7
1120 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1121 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1122 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1123 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1124 self.comm.sendCommand('M400')
1125 self._wizardState = 5
1126 elif self._wizardState == 6:
1127 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1128 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1129 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1130 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1131 self.comm.sendCommand('M400')
1132 self._wizardState = 7
1133 elif self._wizardState == 8:
1134 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1135 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1136 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1137 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1138 self._wizardState = 9
1139 elif self._wizardState == 10:
1140 self._wizardState = 11
1141 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1142 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1143 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1144 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1145 w = profile.getMachineSettingFloat('machine_width') - 10
1146 d = profile.getMachineSettingFloat('machine_depth')
1147 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1148 filamentArea = math.pi * filamentRadius * filamentRadius
1149 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1153 'G1 Z2 F%d' % (feedZ),
1155 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1156 'G1 Z0.3 F%d' % (feedZ)]
1158 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1160 for i in xrange(0, 3):
1161 dist = 5.0 + 0.4 * float(i)
1162 eValue += (d - 2.0*dist) * ePerMM
1163 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1164 eValue += (w - 2.0*dist) * ePerMM
1165 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1166 eValue += (d - 2.0*dist) * ePerMM
1167 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1168 eValue += (w - 2.0*dist) * ePerMM
1169 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1171 gcodeList.append('M400')
1172 self.comm.printGCode(gcodeList)
1173 self.resumeButton.Enable(False)
1175 def mcLog(self, message):
1176 print 'Log:', message
1178 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1179 if self._wizardState == 1:
1180 self._wizardState = 2
1181 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1182 wx.CallAfter(self.resumeButton.Enable, True)
1183 elif self._wizardState == 3:
1184 self._wizardState = 4
1185 if profile.getMachineSetting('has_heated_bed') == 'True':
1186 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1188 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1189 wx.CallAfter(self.resumeButton.Enable, True)
1190 elif self._wizardState == 5:
1191 self._wizardState = 6
1192 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1193 wx.CallAfter(self.resumeButton.Enable, True)
1194 elif self._wizardState == 7:
1195 self._wizardState = 8
1196 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1197 wx.CallAfter(self.resumeButton.Enable, True)
1198 elif self._wizardState == 9:
1199 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1200 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1202 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1203 wx.CallAfter(self.resumeButton.Enable, True)
1204 self._wizardState = 10
1206 def mcStateChange(self, state):
1207 if self.comm is None:
1209 if self.comm.isOperational():
1210 if self._wizardState == 0:
1211 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1212 wx.CallAfter(self.upButton.Enable, True)
1213 wx.CallAfter(self.downButton.Enable, True)
1214 wx.CallAfter(self.upButton2.Enable, True)
1215 wx.CallAfter(self.downButton2.Enable, True)
1216 wx.CallAfter(self.resumeButton.Enable, True)
1217 self._wizardState = -1
1218 elif self._wizardState == 11 and not self.comm.isPrinting():
1219 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1220 self.comm.sendCommand('G92 E0')
1221 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1222 self.comm.sendCommand('M104 S0')
1223 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1224 wx.CallAfter(self.infoBox.SetReadyIndicator)
1225 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1226 wx.CallAfter(self.connectButton.Enable, True)
1227 self._wizardState = 12
1228 elif self.comm.isError():
1229 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1231 def mcMessage(self, message):
1234 def mcProgress(self, lineNr):
1237 def mcZChange(self, newZ):
1240 class headOffsetCalibrationPage(InfoPage):
1241 def __init__(self, parent):
1242 super(headOffsetCalibrationPage, self).__init__(parent, _("Printer head offset calibration"))
1244 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1247 self.connectButton = self.AddButton(_('Connect to printer'))
1250 self.infoBox = self.AddInfoBox()
1251 self.textEntry = self.AddTextCtrl('')
1252 self.textEntry.Enable(False)
1253 self.resumeButton = self.AddButton(_('Resume'))
1254 self.resumeButton.Enable(False)
1256 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1257 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1259 def AllowBack(self):
1262 def OnConnect(self, e = None):
1263 if self.comm is not None:
1267 wx.CallAfter(self.OnConnect)
1269 self.connectButton.Enable(False)
1270 self.comm = machineCom.MachineCom(callbackObject=self)
1271 self.infoBox.SetBusy(_('Connecting to machine.'))
1272 self._wizardState = 0
1274 def OnResume(self, e):
1275 if self._wizardState == 2:
1276 self._wizardState = 3
1277 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1279 w = profile.getMachineSettingFloat('machine_width')
1280 d = profile.getMachineSettingFloat('machine_depth')
1282 gcode = gcodeGenerator.gcodeGenerator()
1283 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1284 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1291 gcode.addMove(w/2, 5)
1292 gcode.addMove(z=0.2)
1294 gcode.addExtrude(w/2, d-5.0)
1296 gcode.addMove(5, d/2)
1298 gcode.addExtrude(w-5.0, d/2)
1299 gcode.addRetract(15)
1302 gcode.addMove(w/2, 5)
1304 gcode.addExtrude(w/2, d-5.0)
1306 gcode.addMove(5, d/2)
1308 gcode.addExtrude(w-5.0, d/2)
1309 gcode.addRetract(15)
1314 gcode.addCmd('M400')
1316 self.comm.printGCode(gcode.list())
1317 self.resumeButton.Enable(False)
1318 elif self._wizardState == 4:
1320 float(self.textEntry.GetValue())
1323 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1324 self._wizardState = 5
1325 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1326 self.textEntry.SetValue('0.0')
1327 self.textEntry.Enable(True)
1328 elif self._wizardState == 5:
1330 float(self.textEntry.GetValue())
1333 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1334 self._wizardState = 6
1335 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1336 self.textEntry.SetValue('')
1337 self.textEntry.Enable(False)
1338 self.resumeButton.Enable(False)
1340 x = profile.getMachineSettingFloat('extruder_offset_x1')
1341 y = profile.getMachineSettingFloat('extruder_offset_y1')
1342 gcode = gcodeGenerator.gcodeGenerator()
1343 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1344 gcode.setPrintSpeed(25)
1347 gcode.addMove(50, 40, 0.2)
1349 for n in xrange(0, 10):
1350 gcode.addExtrude(50 + n * 10, 150)
1351 gcode.addExtrude(50 + n * 10 + 5, 150)
1352 gcode.addExtrude(50 + n * 10 + 5, 40)
1353 gcode.addExtrude(50 + n * 10 + 10, 40)
1354 gcode.addMove(40, 50)
1355 for n in xrange(0, 10):
1356 gcode.addExtrude(150, 50 + n * 10)
1357 gcode.addExtrude(150, 50 + n * 10 + 5)
1358 gcode.addExtrude(40, 50 + n * 10 + 5)
1359 gcode.addExtrude(40, 50 + n * 10 + 10)
1360 gcode.addRetract(15)
1363 gcode.addMove(50 - x, 30 - y, 0.2)
1365 for n in xrange(0, 10):
1366 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1367 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1368 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1369 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1370 gcode.addMove(30 - x, 50 - y, 0.2)
1371 for n in xrange(0, 10):
1372 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1373 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1374 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1375 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1376 gcode.addRetract(15)
1378 gcode.addCmd('M400')
1379 gcode.addCmd('M104 T0 S0')
1380 gcode.addCmd('M104 T1 S0')
1381 self.comm.printGCode(gcode.list())
1382 elif self._wizardState == 7:
1384 n = int(self.textEntry.GetValue()) - 1
1387 x = profile.getMachineSettingFloat('extruder_offset_x1')
1389 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1390 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1391 self.textEntry.SetValue('10')
1392 self._wizardState = 8
1393 elif self._wizardState == 8:
1395 n = int(self.textEntry.GetValue()) - 1
1398 y = profile.getMachineSettingFloat('extruder_offset_y1')
1400 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1401 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1402 self.infoBox.SetReadyIndicator()
1403 self._wizardState = 8
1405 self.resumeButton.Enable(False)
1407 def mcLog(self, message):
1408 print 'Log:', message
1410 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1411 if self._wizardState == 1:
1412 if temp[0] >= 210 and temp[1] >= 210:
1413 self._wizardState = 2
1414 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1415 wx.CallAfter(self.resumeButton.Enable, True)
1416 wx.CallAfter(self.resumeButton.SetFocus)
1418 def mcStateChange(self, state):
1419 if self.comm is None:
1421 if self.comm.isOperational():
1422 if self._wizardState == 0:
1423 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1424 self.comm.sendCommand('M105')
1425 self.comm.sendCommand('M104 S220 T0')
1426 self.comm.sendCommand('M104 S220 T1')
1427 self.comm.sendCommand('G28')
1428 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1429 self._wizardState = 1
1430 if not self.comm.isPrinting():
1431 if self._wizardState == 3:
1432 self._wizardState = 4
1433 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1434 wx.CallAfter(self.textEntry.SetValue, '0.0')
1435 wx.CallAfter(self.textEntry.Enable, True)
1436 wx.CallAfter(self.resumeButton.Enable, True)
1437 wx.CallAfter(self.resumeButton.SetFocus)
1438 elif self._wizardState == 6:
1439 self._wizardState = 7
1440 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1441 wx.CallAfter(self.textEntry.SetValue, '10')
1442 wx.CallAfter(self.textEntry.Enable, True)
1443 wx.CallAfter(self.resumeButton.Enable, True)
1444 wx.CallAfter(self.resumeButton.SetFocus)
1446 elif self.comm.isError():
1447 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1449 def mcMessage(self, message):
1452 def mcProgress(self, lineNr):
1455 def mcZChange(self, newZ):
1458 class bedLevelWizard(wx.wizard.Wizard):
1460 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1462 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1463 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1465 self.mainPage = bedLevelWizardMain(self)
1466 self.headOffsetCalibration = None
1468 self.FitToPage(self.mainPage)
1469 self.GetPageAreaSizer().Add(self.mainPage)
1471 self.RunWizard(self.mainPage)
1474 def OnPageChanging(self, e):
1475 e.GetPage().StoreData()
1477 def OnPageChanged(self, e):
1478 if e.GetPage().AllowNext():
1479 self.FindWindowById(wx.ID_FORWARD).Enable()
1481 self.FindWindowById(wx.ID_FORWARD).Disable()
1482 if e.GetPage().AllowBack():
1483 self.FindWindowById(wx.ID_BACKWARD).Enable()
1485 self.FindWindowById(wx.ID_BACKWARD).Disable()
1487 class headOffsetWizard(wx.wizard.Wizard):
1489 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
1491 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1492 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1494 self.mainPage = headOffsetCalibrationPage(self)
1496 self.FitToPage(self.mainPage)
1497 self.GetPageAreaSizer().Add(self.mainPage)
1499 self.RunWizard(self.mainPage)
1502 def OnPageChanging(self, e):
1503 e.GetPage().StoreData()
1505 def OnPageChanged(self, e):
1506 if e.GetPage().AllowNext():
1507 self.FindWindowById(wx.ID_FORWARD).Enable()
1509 self.FindWindowById(wx.ID_FORWARD).Disable()
1510 if e.GetPage().AllowBack():
1511 self.FindWindowById(wx.ID_BACKWARD).Enable()
1513 self.FindWindowById(wx.ID_BACKWARD).Disable()