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.LulzbotTazRadio = self.AddRadioButton("LulzBot TAZ")
367 self.LulzbotTazRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
368 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2")
369 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
370 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
371 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
372 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
373 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
374 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
375 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
376 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
377 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
379 def OnUltimaker2Select(self, e):
380 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
382 def OnUltimakerSelect(self, e):
383 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
385 def OnUltimakerOPSelect(self, e):
386 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
388 def OnPrintrbotSelect(self, e):
389 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
391 def OnLulzbotSelect(self, e):
392 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
394 def OnOtherSelect(self, e):
395 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
398 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
402 profile.putProfileSetting('retraction_enable', 'True')
403 if self.Ultimaker2Radio.GetValue():
404 profile.putMachineSetting('machine_width', '230')
405 profile.putMachineSetting('machine_depth', '225')
406 profile.putMachineSetting('machine_height', '205')
407 profile.putMachineSetting('machine_name', 'ultimaker2')
408 profile.putMachineSetting('machine_type', 'ultimaker2')
409 profile.putMachineSetting('machine_center_is_zero', 'False')
410 profile.putMachineSetting('has_heated_bed', 'True')
411 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
412 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
413 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
414 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
415 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
416 profile.putMachineSetting('extruder_head_size_height', '48.0')
417 profile.putProfileSetting('nozzle_size', '0.4')
418 profile.putProfileSetting('fan_full_height', '5.0')
419 profile.putMachineSetting('extruder_offset_x1', '18.0')
420 profile.putMachineSetting('extruder_offset_y1', '0.0')
421 elif self.UltimakerRadio.GetValue():
422 profile.putMachineSetting('machine_width', '205')
423 profile.putMachineSetting('machine_depth', '205')
424 profile.putMachineSetting('machine_height', '200')
425 profile.putMachineSetting('machine_name', 'ultimaker original')
426 profile.putMachineSetting('machine_type', 'ultimaker')
427 profile.putMachineSetting('machine_center_is_zero', 'False')
428 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
429 profile.putProfileSetting('nozzle_size', '0.4')
430 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
431 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
432 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
433 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
434 profile.putMachineSetting('extruder_head_size_height', '55.0')
435 elif self.UltimakerOPRadio.GetValue():
436 profile.putMachineSetting('machine_width', '205')
437 profile.putMachineSetting('machine_depth', '205')
438 profile.putMachineSetting('machine_height', '200')
439 profile.putMachineSetting('machine_name', 'ultimaker original+')
440 profile.putMachineSetting('machine_type', 'ultimaker_plus')
441 profile.putMachineSetting('machine_center_is_zero', 'False')
442 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
443 profile.putProfileSetting('nozzle_size', '0.4')
444 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
445 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
446 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
447 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
448 profile.putMachineSetting('extruder_head_size_height', '55.0')
449 profile.putMachineSetting('has_heated_bed', 'True')
450 profile.putMachineSetting('extruder_amount', '1')
451 profile.putProfileSetting('retraction_enable', 'True')
452 elif self.LulzbotTazRadio.GetValue() or self.LulzbotMiniRadio.GetValue():
453 if self.LulzbotTazRadio.GetValue():
454 profile.putMachineSetting('machine_width', '298')
455 profile.putMachineSetting('machine_depth', '275')
456 profile.putMachineSetting('machine_height', '250')
457 profile.putProfileSetting('nozzle_size', '0.35')
458 profile.putMachineSetting('machine_name', 'LulzBot TAZ')
459 profile.putMachineSetting('machine_type', 'lulzbot_TAZ')
460 profile.putMachineSetting('serial_baud', '115200')
462 profile.putMachineSetting('machine_width', '155')
463 profile.putMachineSetting('machine_depth', '155')
464 profile.putMachineSetting('machine_height', '163')
465 profile.putProfileSetting('nozzle_size', '0.5')
466 profile.putMachineSetting('machine_name', 'LulzBot Mini')
467 profile.putMachineSetting('machine_type', 'lulzbot_mini')
468 profile.putMachineSetting('serial_baud', '115200')
469 profile.putMachineSetting('machine_center_is_zero', 'False')
470 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
471 profile.putMachineSetting('has_heated_bed', 'True')
472 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
473 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
474 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
475 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
476 profile.putMachineSetting('extruder_head_size_height', '0.0')
477 profile.putPreference('startMode', 'Simple')
479 profile.putMachineSetting('machine_width', '80')
480 profile.putMachineSetting('machine_depth', '80')
481 profile.putMachineSetting('machine_height', '60')
482 profile.putMachineSetting('machine_name', 'reprap')
483 profile.putMachineSetting('machine_type', 'reprap')
484 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
485 profile.putPreference('startMode', 'Normal')
486 profile.putProfileSetting('nozzle_size', '0.5')
487 profile.checkAndUpdateMachineName()
488 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
490 class SelectParts(InfoPage):
491 def __init__(self, parent):
492 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
493 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."))
495 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
496 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
497 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
498 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
500 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."))
501 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
502 self.springExtruder.SetValue(True)
505 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
506 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
507 profile.putMachineSetting('has_heated_bed', 'True')
509 profile.putMachineSetting('has_heated_bed', 'False')
510 if self.dualExtrusion.GetValue():
511 profile.putMachineSetting('extruder_amount', '2')
512 profile.putMachineSetting('machine_depth', '195')
514 profile.putMachineSetting('extruder_amount', '1')
515 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
516 profile.putProfileSetting('retraction_enable', 'True')
518 profile.putProfileSetting('retraction_enable', 'False')
521 class UltimakerFirmwareUpgradePage(InfoPage):
522 def __init__(self, parent):
523 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
524 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."))
525 self.AddHiddenSeperator()
526 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
527 self.AddHiddenSeperator()
528 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."))
529 upgradeButton, skipUpgradeButton = self.AddDualButton(_('Upgrade to Marlin firmware'), _('Skip upgrade'))
530 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
531 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
532 self.AddHiddenSeperator()
533 if profile.getMachineSetting('machine_type') == 'ultimaker':
534 self.AddText(_("Do not upgrade to this firmware if:"))
535 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
536 self.AddText(_("* Build your own heated bed"))
537 self.AddText(_("* Have other changes in the firmware"))
538 # button = self.AddButton('Goto this page for a custom firmware')
539 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
544 def OnUpgradeClick(self, e):
545 if firmwareInstall.InstallFirmware():
546 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
548 def OnSkipClick(self, e):
549 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
550 self.GetParent().ShowPage(self.GetNext())
552 def OnUrlClick(self, e):
553 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
555 class UltimakerCheckupPage(InfoPage):
556 def __init__(self, parent):
557 super(UltimakerCheckupPage, self).__init__(parent, _("Ultimaker Checkup"))
559 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
560 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
561 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
562 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
563 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
564 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
565 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
566 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
567 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
568 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
571 _("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."))
572 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
573 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
574 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
576 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
577 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
578 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
580 self.infoBox = self.AddInfoBox()
581 self.machineState = self.AddText("")
582 self.temperatureLabel = self.AddText("")
583 self.errorLogButton = self.AddButton(_("Show error log"))
584 self.errorLogButton.Show(False)
586 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
588 self.xMinStop = False
589 self.xMaxStop = False
590 self.yMinStop = False
591 self.yMaxStop = False
592 self.zMinStop = False
593 self.zMaxStop = False
595 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
598 if self.comm is not None:
602 self.endstopBitmap.Show(False)
605 def OnSkipClick(self, e):
606 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
607 self.GetParent().ShowPage(self.GetNext())
609 def OnCheckClick(self, e=None):
610 self.errorLogButton.Show(False)
611 if self.comm is not None:
615 wx.CallAfter(self.OnCheckClick)
617 self.infoBox.SetBusy(_("Connecting to machine."))
618 self.commState.SetBitmap(self.unknownBitmap)
619 self.tempState.SetBitmap(self.unknownBitmap)
620 self.stopState.SetBitmap(self.unknownBitmap)
621 self.checkupState = 0
622 self.checkExtruderNr = 0
623 self.comm = machineCom.MachineCom(callbackObject=self)
625 def OnErrorLog(self, e):
626 printWindow.LogWindow('\n'.join(self.comm.getLog()))
628 def mcLog(self, message):
631 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
632 if not self.comm.isOperational():
634 if self.checkupState == 0:
635 self.tempCheckTimeout = 20
636 if temp[self.checkExtruderNr] > 70:
637 self.checkupState = 1
638 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
639 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
640 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
642 self.startTemp = temp[self.checkExtruderNr]
643 self.checkupState = 2
644 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
645 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
646 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
647 elif self.checkupState == 1:
648 if temp[self.checkExtruderNr] < 60:
649 self.startTemp = temp[self.checkExtruderNr]
650 self.checkupState = 2
651 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
652 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
653 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
654 elif self.checkupState == 2:
655 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
656 if temp[self.checkExtruderNr] > self.startTemp + 40:
657 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
658 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
659 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
660 self.checkExtruderNr = 0
661 self.checkupState = 3
662 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
663 wx.CallAfter(self.endstopBitmap.Show, True)
664 wx.CallAfter(self.Layout)
665 self.comm.sendCommand('M119')
666 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
668 self.checkupState = 0
669 self.checkExtruderNr += 1
671 self.tempCheckTimeout -= 1
672 if self.tempCheckTimeout < 1:
673 self.checkupState = -1
674 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
675 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
676 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
677 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
678 elif self.checkupState >= 3 and self.checkupState < 10:
679 self.comm.sendCommand('M119')
680 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
682 def mcStateChange(self, state):
683 if self.comm is None:
685 if self.comm.isOperational():
686 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
687 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
688 elif self.comm.isError():
689 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
690 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
691 wx.CallAfter(self.endstopBitmap.Show, False)
692 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
693 wx.CallAfter(self.errorLogButton.Show, True)
694 wx.CallAfter(self.Layout)
696 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
698 def mcMessage(self, message):
699 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
700 for data in message.split(' '):
702 tag, value = data.split(':', 1)
704 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
706 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
708 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
710 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
712 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
714 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
716 tag, value = map(str.strip, message.split(':', 1))
718 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
720 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
722 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
724 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
726 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
728 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
729 if 'z_max' in message:
730 self.comm.sendCommand('M119')
732 if self.checkupState == 3:
733 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
734 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
735 self.checkupState = 5
736 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
737 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
739 self.checkupState = 4
740 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
741 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
742 elif self.checkupState == 4:
743 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
744 self.checkupState = 5
745 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
746 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
747 elif self.checkupState == 5:
748 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
749 self.checkupState = 6
750 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
751 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
752 elif self.checkupState == 6:
753 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
754 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
755 self.checkupState = 8
756 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
757 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
759 self.checkupState = 7
760 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
761 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
762 elif self.checkupState == 7:
763 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
764 self.checkupState = 8
765 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
766 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
767 elif self.checkupState == 8:
768 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
769 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
770 self.checkupState = 10
772 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
773 wx.CallAfter(self.infoBox.SetReadyIndicator)
774 wx.CallAfter(self.endstopBitmap.Show, False)
775 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
776 wx.CallAfter(self.OnSkipClick, None)
778 self.checkupState = 9
779 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
780 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
781 elif self.checkupState == 9:
782 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
783 self.checkupState = 10
785 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
786 wx.CallAfter(self.infoBox.SetReadyIndicator)
787 wx.CallAfter(self.endstopBitmap.Show, False)
788 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
789 wx.CallAfter(self.OnSkipClick, None)
791 def mcProgress(self, lineNr):
794 def mcZChange(self, newZ):
798 class UltimakerCalibrationPage(InfoPage):
799 def __init__(self, parent):
800 super(UltimakerCalibrationPage, self).__init__(parent, _("Ultimaker Calibration"))
802 self.AddText("Your Ultimaker requires some calibration.")
803 self.AddText("This calibration is needed for a proper extrusion amount.")
805 self.AddText("The following values are needed:")
806 self.AddText("* Diameter of filament")
807 self.AddText("* Number of steps per mm of filament extrusion")
809 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
811 self.AddText("First we need the diameter of your filament:")
812 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
814 "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.")
815 self.AddText("Note: This value can be changed later at any time.")
818 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
821 class UltimakerCalibrateStepsPerEPage(InfoPage):
822 def __init__(self, parent):
823 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, _("Ultimaker Calibration"))
825 #if profile.getMachineSetting('steps_per_e') == '0':
826 # profile.putMachineSetting('steps_per_e', '865.888')
828 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
829 self.AddText(_("First remove any filament from your machine."))
830 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
831 self.AddText(_("We'll push the filament 100mm"))
832 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
833 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
834 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
835 self.AddText(_("This results in the following steps per E:"))
836 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
837 self.AddText(_("You can repeat these steps to get better calibration."))
840 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
841 self.heatButton = self.AddButton(_("Heatup for filament removal"))
843 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
844 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
845 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
847 def OnSaveLengthClick(self, e):
848 currentEValue = float(self.stepsPerEInput.GetValue())
849 realExtrudeLength = float(self.lengthInput.GetValue())
850 newEValue = currentEValue * 100 / realExtrudeLength
851 self.stepsPerEInput.SetValue(str(newEValue))
852 self.lengthInput.SetValue("100")
854 def OnExtrudeClick(self, e):
855 t = threading.Thread(target=self.OnExtrudeRun)
859 def OnExtrudeRun(self):
860 self.heatButton.Enable(False)
861 self.extrudeButton.Enable(False)
862 currentEValue = float(self.stepsPerEInput.GetValue())
863 self.comm = machineCom.MachineCom()
864 if not self.comm.isOpen():
866 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
867 'Printer error', wx.OK | wx.ICON_INFORMATION)
868 self.heatButton.Enable(True)
869 self.extrudeButton.Enable(True)
872 line = self.comm.readline()
877 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
880 self.sendGCommand('M302') #Disable cold extrusion protection
881 self.sendGCommand("M92 E%f" % (currentEValue))
882 self.sendGCommand("G92 E0")
883 self.sendGCommand("G1 E100 F600")
886 self.extrudeButton.Enable()
887 self.heatButton.Enable()
889 def OnHeatClick(self, e):
890 t = threading.Thread(target=self.OnHeatRun)
895 self.heatButton.Enable(False)
896 self.extrudeButton.Enable(False)
897 self.comm = machineCom.MachineCom()
898 if not self.comm.isOpen():
900 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
901 'Printer error', wx.OK | wx.ICON_INFORMATION)
902 self.heatButton.Enable(True)
903 self.extrudeButton.Enable(True)
906 line = self.comm.readline()
908 self.heatButton.Enable(True)
909 self.extrudeButton.Enable(True)
913 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
916 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
918 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
919 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
920 self.sendGCommand('M104 S0')
923 self.heatButton.Enable(True)
924 self.extrudeButton.Enable(True)
926 def sendGCommand(self, cmd):
927 self.comm.sendCommand(cmd) #Disable cold extrusion protection
929 line = self.comm.readline()
932 if line.startswith('ok'):
936 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
938 class Ultimaker2ReadyPage(InfoPage):
939 def __init__(self, parent):
940 super(Ultimaker2ReadyPage, self).__init__(parent, _("Ultimaker2"))
941 self.AddText(_('Congratulations on your the purchase of your brand new Ultimaker2.'))
942 self.AddText(_('Cura is now ready to be used with your Ultimaker2.'))
945 class LulzbotReadyPage(InfoPage):
946 def __init__(self, parent):
947 super(LulzbotReadyPage, self).__init__(parent, _("LulzBot TAZ/Mini"))
948 self.AddText(_('Cura is now ready to be used with your LulzBot 3D printer.'))
950 self.AddText(_('For more information about using Cura with your LulzBot'))
951 self.AddText(_('3D printer, please visit www.LulzBot.com/cura'))
954 class ConfigWizard(wx.wizard.Wizard):
955 def __init__(self, addNew = False):
956 super(ConfigWizard, self).__init__(None, -1, _("Configuration Wizard"))
958 self._old_machine_index = int(profile.getPreferenceFloat('active_machine'))
960 profile.setActiveMachine(profile.getMachineCount())
962 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
963 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
964 self.Bind(wx.wizard.EVT_WIZARD_CANCEL, self.OnCancel)
966 self.machineSelectPage = MachineSelectPage(self)
967 self.ultimakerSelectParts = SelectParts(self)
968 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
969 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
970 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
971 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
972 self.bedLevelPage = bedLevelWizardMain(self)
973 self.headOffsetCalibration = headOffsetCalibrationPage(self)
974 self.printrbotSelectType = PrintrbotPage(self)
975 self.otherMachineSelectPage = OtherMachineSelectPage(self)
976 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
977 self.otherMachineInfoPage = OtherMachineInfoPage(self)
979 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
980 self.lulzbotReadyPage = LulzbotReadyPage(self)
982 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
983 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
984 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
985 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
986 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
987 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
988 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
989 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
991 self.FitToPage(self.machineSelectPage)
992 self.GetPageAreaSizer().Add(self.machineSelectPage)
994 self.RunWizard(self.machineSelectPage)
997 def OnPageChanging(self, e):
998 e.GetPage().StoreData()
1000 def OnPageChanged(self, e):
1001 if e.GetPage().AllowNext():
1002 self.FindWindowById(wx.ID_FORWARD).Enable()
1004 self.FindWindowById(wx.ID_FORWARD).Disable()
1005 if e.GetPage().AllowBack():
1006 self.FindWindowById(wx.ID_BACKWARD).Enable()
1008 self.FindWindowById(wx.ID_BACKWARD).Disable()
1010 def OnCancel(self, e):
1011 profile.setActiveMachine(self._old_machine_index)
1013 class bedLevelWizardMain(InfoPage):
1014 def __init__(self, parent):
1015 super(bedLevelWizardMain, self).__init__(parent, _("Bed leveling wizard"))
1017 self.AddText(_('This wizard will help you in leveling your printer bed'))
1019 self.AddText(_('It will do the following steps'))
1020 self.AddText(_('* Move the printer head to each corner'))
1021 self.AddText(_(' and let you adjust the height of the bed to the nozzle'))
1022 self.AddText(_('* Print a line around the bed to check if it is level'))
1025 self.connectButton = self.AddButton(_('Connect to printer'))
1028 self.infoBox = self.AddInfoBox()
1029 self.resumeButton = self.AddButton(_('Resume'))
1030 self.upButton, self.downButton = self.AddDualButton(_('Up 0.2mm'), _('Down 0.2mm'))
1031 self.upButton2, self.downButton2 = self.AddDualButton(_('Up 10mm'), _('Down 10mm'))
1032 self.resumeButton.Enable(False)
1034 self.upButton.Enable(False)
1035 self.downButton.Enable(False)
1036 self.upButton2.Enable(False)
1037 self.downButton2.Enable(False)
1039 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1040 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1041 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1042 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1043 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1044 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1046 def OnConnect(self, e = None):
1047 if self.comm is not None:
1051 wx.CallAfter(self.OnConnect)
1053 self.connectButton.Enable(False)
1054 self.comm = machineCom.MachineCom(callbackObject=self)
1055 self.infoBox.SetBusy(_('Connecting to machine.'))
1056 self._wizardState = 0
1058 def OnBedUp(self, e):
1059 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1060 self.comm.sendCommand('G92 Z10')
1061 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1062 self.comm.sendCommand('M400')
1064 def OnBedDown(self, e):
1065 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1066 self.comm.sendCommand('G92 Z10')
1067 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1068 self.comm.sendCommand('M400')
1070 def OnBedUp2(self, e):
1071 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1072 self.comm.sendCommand('G92 Z10')
1073 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1074 self.comm.sendCommand('M400')
1076 def OnBedDown2(self, e):
1077 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1078 self.comm.sendCommand('G92 Z10')
1079 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1080 self.comm.sendCommand('M400')
1082 def AllowNext(self):
1083 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1084 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1087 def OnResume(self, e):
1088 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1089 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1090 if self._wizardState == -1:
1091 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer...'))
1092 wx.CallAfter(self.upButton.Enable, False)
1093 wx.CallAfter(self.downButton.Enable, False)
1094 wx.CallAfter(self.upButton2.Enable, False)
1095 wx.CallAfter(self.downButton2.Enable, False)
1096 self.comm.sendCommand('M105')
1097 self.comm.sendCommand('G28')
1098 self._wizardState = 1
1099 elif self._wizardState == 2:
1100 if profile.getMachineSetting('has_heated_bed') == 'True':
1101 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back center...'))
1102 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1103 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1104 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1105 self.comm.sendCommand('M400')
1106 self._wizardState = 3
1108 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back left corner...'))
1109 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1110 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1111 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1112 self.comm.sendCommand('M400')
1113 self._wizardState = 3
1114 elif self._wizardState == 4:
1115 if profile.getMachineSetting('has_heated_bed') == 'True':
1116 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1117 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1118 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1119 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1120 self.comm.sendCommand('M400')
1121 self._wizardState = 7
1123 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to back right corner...'))
1124 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1125 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1126 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1127 self.comm.sendCommand('M400')
1128 self._wizardState = 5
1129 elif self._wizardState == 6:
1130 wx.CallAfter(self.infoBox.SetBusy, _('Moving head to front right corner...'))
1131 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1132 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1133 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1134 self.comm.sendCommand('M400')
1135 self._wizardState = 7
1136 elif self._wizardState == 8:
1137 wx.CallAfter(self.infoBox.SetBusy, _('Heating up printer...'))
1138 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1139 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1140 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1141 self._wizardState = 9
1142 elif self._wizardState == 10:
1143 self._wizardState = 11
1144 wx.CallAfter(self.infoBox.SetInfo, _('Printing a square on the printer bed at 0.3mm height.'))
1145 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1146 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1147 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1148 w = profile.getMachineSettingFloat('machine_width') - 10
1149 d = profile.getMachineSettingFloat('machine_depth')
1150 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1151 filamentArea = math.pi * filamentRadius * filamentRadius
1152 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1156 'G1 Z2 F%d' % (feedZ),
1158 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1159 'G1 Z0.3 F%d' % (feedZ)]
1161 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1163 for i in xrange(0, 3):
1164 dist = 5.0 + 0.4 * float(i)
1165 eValue += (d - 2.0*dist) * ePerMM
1166 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1167 eValue += (w - 2.0*dist) * ePerMM
1168 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1169 eValue += (d - 2.0*dist) * ePerMM
1170 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1171 eValue += (w - 2.0*dist) * ePerMM
1172 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1174 gcodeList.append('M400')
1175 self.comm.printGCode(gcodeList)
1176 self.resumeButton.Enable(False)
1178 def mcLog(self, message):
1179 print 'Log:', message
1181 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1182 if self._wizardState == 1:
1183 self._wizardState = 2
1184 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.'))
1185 wx.CallAfter(self.resumeButton.Enable, True)
1186 elif self._wizardState == 3:
1187 self._wizardState = 4
1188 if profile.getMachineSetting('has_heated_bed') == 'True':
1189 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.'))
1191 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.'))
1192 wx.CallAfter(self.resumeButton.Enable, True)
1193 elif self._wizardState == 5:
1194 self._wizardState = 6
1195 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.'))
1196 wx.CallAfter(self.resumeButton.Enable, True)
1197 elif self._wizardState == 7:
1198 self._wizardState = 8
1199 wx.CallAfter(self.infoBox.SetAttention, _('Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.'))
1200 wx.CallAfter(self.resumeButton.Enable, True)
1201 elif self._wizardState == 9:
1202 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1203 wx.CallAfter(self.infoBox.SetInfo, _('Heating up printer: %d/%d') % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1205 wx.CallAfter(self.infoBox.SetAttention, _('The printer is hot now. Please insert some PLA filament into the printer.'))
1206 wx.CallAfter(self.resumeButton.Enable, True)
1207 self._wizardState = 10
1209 def mcStateChange(self, state):
1210 if self.comm is None:
1212 if self.comm.isOperational():
1213 if self._wizardState == 0:
1214 wx.CallAfter(self.infoBox.SetAttention, _('Use the up/down buttons to move the bed and adjust your Z endstop.'))
1215 wx.CallAfter(self.upButton.Enable, True)
1216 wx.CallAfter(self.downButton.Enable, True)
1217 wx.CallAfter(self.upButton2.Enable, True)
1218 wx.CallAfter(self.downButton2.Enable, True)
1219 wx.CallAfter(self.resumeButton.Enable, True)
1220 self._wizardState = -1
1221 elif self._wizardState == 11 and not self.comm.isPrinting():
1222 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1223 self.comm.sendCommand('G92 E0')
1224 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1225 self.comm.sendCommand('M104 S0')
1226 wx.CallAfter(self.infoBox.SetInfo, _('Calibration finished.\nThe squares on the bed should slightly touch each other.'))
1227 wx.CallAfter(self.infoBox.SetReadyIndicator)
1228 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1229 wx.CallAfter(self.connectButton.Enable, True)
1230 self._wizardState = 12
1231 elif self.comm.isError():
1232 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1234 def mcMessage(self, message):
1237 def mcProgress(self, lineNr):
1240 def mcZChange(self, newZ):
1243 class headOffsetCalibrationPage(InfoPage):
1244 def __init__(self, parent):
1245 super(headOffsetCalibrationPage, self).__init__(parent, _("Printer head offset calibration"))
1247 self.AddText(_('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine'))
1250 self.connectButton = self.AddButton(_('Connect to printer'))
1253 self.infoBox = self.AddInfoBox()
1254 self.textEntry = self.AddTextCtrl('')
1255 self.textEntry.Enable(False)
1256 self.resumeButton = self.AddButton(_('Resume'))
1257 self.resumeButton.Enable(False)
1259 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1260 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1262 def AllowBack(self):
1265 def OnConnect(self, e = None):
1266 if self.comm is not None:
1270 wx.CallAfter(self.OnConnect)
1272 self.connectButton.Enable(False)
1273 self.comm = machineCom.MachineCom(callbackObject=self)
1274 self.infoBox.SetBusy(_('Connecting to machine.'))
1275 self._wizardState = 0
1277 def OnResume(self, e):
1278 if self._wizardState == 2:
1279 self._wizardState = 3
1280 wx.CallAfter(self.infoBox.SetBusy, _('Printing initial calibration cross'))
1282 w = profile.getMachineSettingFloat('machine_width')
1283 d = profile.getMachineSettingFloat('machine_depth')
1285 gcode = gcodeGenerator.gcodeGenerator()
1286 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1287 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1294 gcode.addMove(w/2, 5)
1295 gcode.addMove(z=0.2)
1297 gcode.addExtrude(w/2, d-5.0)
1299 gcode.addMove(5, d/2)
1301 gcode.addExtrude(w-5.0, d/2)
1302 gcode.addRetract(15)
1305 gcode.addMove(w/2, 5)
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)
1317 gcode.addCmd('M400')
1319 self.comm.printGCode(gcode.list())
1320 self.resumeButton.Enable(False)
1321 elif self._wizardState == 4:
1323 float(self.textEntry.GetValue())
1326 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1327 self._wizardState = 5
1328 self.infoBox.SetAttention(_('Please measure the distance between the horizontal lines in millimeters.'))
1329 self.textEntry.SetValue('0.0')
1330 self.textEntry.Enable(True)
1331 elif self._wizardState == 5:
1333 float(self.textEntry.GetValue())
1336 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1337 self._wizardState = 6
1338 self.infoBox.SetBusy(_('Printing the fine calibration lines.'))
1339 self.textEntry.SetValue('')
1340 self.textEntry.Enable(False)
1341 self.resumeButton.Enable(False)
1343 x = profile.getMachineSettingFloat('extruder_offset_x1')
1344 y = profile.getMachineSettingFloat('extruder_offset_y1')
1345 gcode = gcodeGenerator.gcodeGenerator()
1346 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1347 gcode.setPrintSpeed(25)
1350 gcode.addMove(50, 40, 0.2)
1352 for n in xrange(0, 10):
1353 gcode.addExtrude(50 + n * 10, 150)
1354 gcode.addExtrude(50 + n * 10 + 5, 150)
1355 gcode.addExtrude(50 + n * 10 + 5, 40)
1356 gcode.addExtrude(50 + n * 10 + 10, 40)
1357 gcode.addMove(40, 50)
1358 for n in xrange(0, 10):
1359 gcode.addExtrude(150, 50 + n * 10)
1360 gcode.addExtrude(150, 50 + n * 10 + 5)
1361 gcode.addExtrude(40, 50 + n * 10 + 5)
1362 gcode.addExtrude(40, 50 + n * 10 + 10)
1363 gcode.addRetract(15)
1366 gcode.addMove(50 - x, 30 - y, 0.2)
1368 for n in xrange(0, 10):
1369 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1370 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1371 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1372 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1373 gcode.addMove(30 - x, 50 - y, 0.2)
1374 for n in xrange(0, 10):
1375 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1376 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1377 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1378 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1379 gcode.addRetract(15)
1381 gcode.addCmd('M400')
1382 gcode.addCmd('M104 T0 S0')
1383 gcode.addCmd('M104 T1 S0')
1384 self.comm.printGCode(gcode.list())
1385 elif self._wizardState == 7:
1387 n = int(self.textEntry.GetValue()) - 1
1390 x = profile.getMachineSettingFloat('extruder_offset_x1')
1392 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1393 self.infoBox.SetAttention(_('Which horizontal line number lays perfect on top of each other? Front most line is zero.'))
1394 self.textEntry.SetValue('10')
1395 self._wizardState = 8
1396 elif self._wizardState == 8:
1398 n = int(self.textEntry.GetValue()) - 1
1401 y = profile.getMachineSettingFloat('extruder_offset_y1')
1403 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1404 self.infoBox.SetInfo(_('Calibration finished. Offsets are: %s %s') % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1405 self.infoBox.SetReadyIndicator()
1406 self._wizardState = 8
1408 self.resumeButton.Enable(False)
1410 def mcLog(self, message):
1411 print 'Log:', message
1413 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1414 if self._wizardState == 1:
1415 if temp[0] >= 210 and temp[1] >= 210:
1416 self._wizardState = 2
1417 wx.CallAfter(self.infoBox.SetAttention, _('Please load both extruders with PLA.'))
1418 wx.CallAfter(self.resumeButton.Enable, True)
1419 wx.CallAfter(self.resumeButton.SetFocus)
1421 def mcStateChange(self, state):
1422 if self.comm is None:
1424 if self.comm.isOperational():
1425 if self._wizardState == 0:
1426 wx.CallAfter(self.infoBox.SetInfo, _('Homing printer and heating up both extruders.'))
1427 self.comm.sendCommand('M105')
1428 self.comm.sendCommand('M104 S220 T0')
1429 self.comm.sendCommand('M104 S220 T1')
1430 self.comm.sendCommand('G28')
1431 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1432 self._wizardState = 1
1433 if not self.comm.isPrinting():
1434 if self._wizardState == 3:
1435 self._wizardState = 4
1436 wx.CallAfter(self.infoBox.SetAttention, _('Please measure the distance between the vertical lines in millimeters.'))
1437 wx.CallAfter(self.textEntry.SetValue, '0.0')
1438 wx.CallAfter(self.textEntry.Enable, True)
1439 wx.CallAfter(self.resumeButton.Enable, True)
1440 wx.CallAfter(self.resumeButton.SetFocus)
1441 elif self._wizardState == 6:
1442 self._wizardState = 7
1443 wx.CallAfter(self.infoBox.SetAttention, _('Which vertical line number lays perfect on top of each other? Leftmost line is zero.'))
1444 wx.CallAfter(self.textEntry.SetValue, '10')
1445 wx.CallAfter(self.textEntry.Enable, True)
1446 wx.CallAfter(self.resumeButton.Enable, True)
1447 wx.CallAfter(self.resumeButton.SetFocus)
1449 elif self.comm.isError():
1450 wx.CallAfter(self.infoBox.SetError, _('Failed to establish connection with the printer.'), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1452 def mcMessage(self, message):
1455 def mcProgress(self, lineNr):
1458 def mcZChange(self, newZ):
1461 class bedLevelWizard(wx.wizard.Wizard):
1463 super(bedLevelWizard, self).__init__(None, -1, _("Bed leveling wizard"))
1465 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1466 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1468 self.mainPage = bedLevelWizardMain(self)
1469 self.headOffsetCalibration = None
1471 self.FitToPage(self.mainPage)
1472 self.GetPageAreaSizer().Add(self.mainPage)
1474 self.RunWizard(self.mainPage)
1477 def OnPageChanging(self, e):
1478 e.GetPage().StoreData()
1480 def OnPageChanged(self, e):
1481 if e.GetPage().AllowNext():
1482 self.FindWindowById(wx.ID_FORWARD).Enable()
1484 self.FindWindowById(wx.ID_FORWARD).Disable()
1485 if e.GetPage().AllowBack():
1486 self.FindWindowById(wx.ID_BACKWARD).Enable()
1488 self.FindWindowById(wx.ID_BACKWARD).Disable()
1490 class headOffsetWizard(wx.wizard.Wizard):
1492 super(headOffsetWizard, self).__init__(None, -1, _("Head offset wizard"))
1494 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1495 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1497 self.mainPage = headOffsetCalibrationPage(self)
1499 self.FitToPage(self.mainPage)
1500 self.GetPageAreaSizer().Add(self.mainPage)
1502 self.RunWizard(self.mainPage)
1505 def OnPageChanging(self, e):
1506 e.GetPage().StoreData()
1508 def OnPageChanged(self, e):
1509 if e.GetPage().AllowNext():
1510 self.FindWindowById(wx.ID_FORWARD).Enable()
1512 self.FindWindowById(wx.ID_FORWARD).Disable()
1513 if e.GetPage().AllowBack():
1514 self.FindWindowById(wx.ID_BACKWARD).Enable()
1516 self.FindWindowById(wx.ID_BACKWARD).Disable()