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)
228 class FirstInfoPage(InfoPage):
229 def __init__(self, parent, addNew):
231 super(FirstInfoPage, self).__init__(parent, _("Add new machine wizard"))
233 super(FirstInfoPage, self).__init__(parent, _("First time run wizard"))
234 self.AddText(_("Welcome, and thanks for trying Cura!"))
236 self.AddText(_("This wizard will help you in setting up Cura for your machine."))
239 self._language_option = self.AddCombo(_("Select your language:"), map(lambda o: o[1], resources.getLanguageOptions()))
241 self._language_option = None
242 # self.AddText(_("This wizard will help you with the following steps:"))
243 # self.AddText(_("* Configure Cura for your machine"))
244 # self.AddText(_("* Optionally upgrade your firmware"))
245 # self.AddText(_("* Optionally check if your machine is working safely"))
246 # self.AddText(_("* Optionally level your printer bed"))
248 #self.AddText('* Calibrate your machine')
249 #self.AddText('* Do your first print')
255 if self._language_option is not None:
256 profile.putPreference('language', self._language_option.GetValue())
257 resources.setupLocalization(self._language_option.GetValue())
259 class PrintrbotPage(InfoPage):
260 def __init__(self, parent):
261 self._printer_info = {
262 # X, Y, Z, Filament Diameter, PrintTemperature, Print Speed, Travel Speed, Retract speed, Retract amount
263 "Original": (130, 130, 130, 2.95, 208, 40, 70, 30, 1),
264 "Simple Maker's Edition v1": (100, 100, 100, 1.75, 208, 40, 70, 30, 1),
265 "Simple Maker's Edition v2 (2013 Printrbot Simple)": (100, 100, 100, 1.75, 208, 40, 70, 30, 1),
266 "Simple Maker's Edition v3 (2014 Printrbot Simple)": (100, 100, 100, 1.75, 208, 40, 70, 30, 1),
267 "Simple Maker's Edition v4 (Model 1405)": (100, 100, 100, 1.75, 208, 40, 70, 30, 1),
268 "Simple Metal": (150, 150, 150, 1.75, 208, 40, 70, 30, 1),
269 "Jr v1": (150, 100, 80, 1.75, 208, 40, 70, 30, 1),
270 "Jr v2": (150, 150, 150, 1.75, 208, 40, 70, 30, 1),
271 "LC v2": (150, 150, 150, 1.75, 208, 40, 70, 30, 1),
272 "Plus v2": (200, 200, 200, 1.75, 208, 40, 70, 30, 1),
273 "Plus v2.1": (200, 200, 200, 1.75, 208, 40, 70, 30, 1),
274 "Plus v2.2 (Model 1404/140422)": (250, 250, 250, 1.75, 208, 40, 70, 30, 1),
275 "Plus v2.3 (Model 140501)": (250, 250, 250, 1.75, 208, 40, 70, 30, 1),
276 "Plus v2.4 (Model 140507)": (250, 250, 250, 1.75, 208, 40, 70, 30, 1),
279 super(PrintrbotPage, self).__init__(parent, "Printrbot Selection")
280 self.AddText(_("Select which Printrbot machine you have:"))
281 keys = self._printer_info.keys()
285 item = self.AddRadioButton(name)
286 item.data = self._printer_info[name]
287 self._items.append(item)
290 profile.putMachineSetting('machine_name', 'Printrbot ???')
291 for item in self._items:
294 profile.putMachineSetting('machine_name', 'Printrbot ' + item.GetLabel())
295 profile.putMachineSetting('machine_width', data[0])
296 profile.putMachineSetting('machine_depth', data[1])
297 profile.putMachineSetting('machine_height', data[2])
298 profile.putProfileSetting('nozzle_size', '0.5')
299 profile.putProfileSetting('filament_diameter', data[3])
300 profile.putProfileSetting('print_temperature', data[4])
301 profile.putProfileSetting('print_speed', data[5])
302 profile.putProfileSetting('travel_speed', data[6])
303 profile.putProfileSetting('retraction_speed', data[7])
304 profile.putProfileSetting('retraction_amount', data[8])
305 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
306 profile.putMachineSetting('has_heated_bed', 'False')
307 profile.putMachineSetting('machine_center_is_zero', 'False')
308 profile.putMachineSetting('extruder_head_size_min_x', '0')
309 profile.putMachineSetting('extruder_head_size_min_y', '0')
310 profile.putMachineSetting('extruder_head_size_max_x', '0')
311 profile.putMachineSetting('extruder_head_size_max_y', '0')
312 profile.putMachineSetting('extruder_head_size_height', '0')
314 class OtherMachineSelectPage(InfoPage):
315 def __init__(self, parent):
316 super(OtherMachineSelectPage, self).__init__(parent, "Other machine information")
317 self.AddText(_("The following pre-defined machine profiles are available"))
318 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."))
320 machines = resources.getDefaultMachineProfiles()
322 for filename in machines:
323 name = os.path.splitext(os.path.basename(filename))[0]
324 item = self.AddRadioButton(name)
325 item.filename = filename
326 item.Bind(wx.EVT_RADIOBUTTON, self.OnProfileSelect)
327 self.options.append(item)
329 item = self.AddRadioButton('Custom...')
331 item.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
333 def OnProfileSelect(self, e):
334 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineInfoPage)
336 def OnOtherSelect(self, e):
337 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().customRepRapInfoPage)
340 for option in self.options:
341 if option.GetValue():
342 profile.loadProfile(option.filename)
343 profile.loadMachineSettings(option.filename)
345 class OtherMachineInfoPage(InfoPage):
346 def __init__(self, parent):
347 super(OtherMachineInfoPage, self).__init__(parent, "Cura Ready!")
348 self.AddText(_("Cura is now ready to be used!"))
350 class CustomRepRapInfoPage(InfoPage):
351 def __init__(self, parent):
352 super(CustomRepRapInfoPage, self).__init__(parent, "Custom RepRap information")
353 self.AddText(_("RepRap machines can be vastly different, so here you can set your own settings."))
354 self.AddText(_("Be sure to review the default profile before running it on your machine."))
355 self.AddText(_("If you like a default profile for your machine added,\nthen make an issue on github."))
357 self.AddText(_("You will have to manually install Marlin or Sprinter firmware."))
359 self.machineName = self.AddLabelTextCtrl(_("Machine name"), "RepRap")
360 self.machineWidth = self.AddLabelTextCtrl(_("Machine width (mm)"), "80")
361 self.machineDepth = self.AddLabelTextCtrl(_("Machine depth (mm)"), "80")
362 self.machineHeight = self.AddLabelTextCtrl(_("Machine height (mm)"), "55")
363 self.nozzleSize = self.AddLabelTextCtrl(_("Nozzle size (mm)"), "0.5")
364 self.heatedBed = self.AddCheckbox(_("Heated bed"))
365 self.HomeAtCenter = self.AddCheckbox(_("Bed center is 0,0,0 (RoStock)"))
368 profile.putMachineSetting('machine_name', self.machineName.GetValue())
369 profile.putMachineSetting('machine_width', self.machineWidth.GetValue())
370 profile.putMachineSetting('machine_depth', self.machineDepth.GetValue())
371 profile.putMachineSetting('machine_height', self.machineHeight.GetValue())
372 profile.putProfileSetting('nozzle_size', self.nozzleSize.GetValue())
373 profile.putProfileSetting('wall_thickness', float(profile.getProfileSettingFloat('nozzle_size')) * 2)
374 profile.putMachineSetting('has_heated_bed', str(self.heatedBed.GetValue()))
375 profile.putMachineSetting('machine_center_is_zero', str(self.HomeAtCenter.GetValue()))
376 profile.putMachineSetting('extruder_head_size_min_x', '0')
377 profile.putMachineSetting('extruder_head_size_min_y', '0')
378 profile.putMachineSetting('extruder_head_size_max_x', '0')
379 profile.putMachineSetting('extruder_head_size_max_y', '0')
380 profile.putMachineSetting('extruder_head_size_height', '0')
381 profile.checkAndUpdateMachineName()
383 class MachineSelectPage(InfoPage):
384 def __init__(self, parent):
385 super(MachineSelectPage, self).__init__(parent, _("Select your machine"))
386 self.AddText(_("What kind of machine do you have:"))
388 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2", style=wx.RB_GROUP)
389 self.Ultimaker2Radio.SetValue(True)
390 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
391 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
392 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
393 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
394 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
395 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
396 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
397 self.LulzbotTazRadio = self.AddRadioButton("Lulzbot TAZ")
398 self.LulzbotTazRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
399 self.LulzbotMiniRadio = self.AddRadioButton("Lulzbot Mini")
400 self.LulzbotMiniRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
401 self.OtherRadio = self.AddRadioButton(_("Other (Ex: RepRap, MakerBot, Witbox)"))
402 self.OtherRadio.Bind(wx.EVT_RADIOBUTTON, self.OnOtherSelect)
404 self.AddText(_("The collection of anonymous usage information helps with the continued improvement of Cura."))
405 self.AddText(_("This does NOT submit your models online nor gathers any privacy related information."))
406 self.SubmitUserStats = self.AddCheckbox(_("Submit anonymous usage information:"))
407 self.AddText(_("For full details see: http://wiki.ultimaker.com/Cura:stats"))
408 self.SubmitUserStats.SetValue(True)
410 def OnUltimaker2Select(self, e):
411 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
413 def OnUltimakerSelect(self, e):
414 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerSelectParts)
416 def OnUltimakerOPSelect(self, e):
417 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimakerFirmwareUpgradePage)
419 def OnPrintrbotSelect(self, e):
420 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().printrbotSelectType)
422 def OnLulzbotSelect(self, e):
423 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().lulzbotReadyPage)
425 def OnOtherSelect(self, e):
426 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().otherMachineSelectPage)
429 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().ultimaker2ReadyPage)
433 profile.putProfileSetting('retraction_enable', 'True')
434 if self.Ultimaker2Radio.GetValue():
435 profile.putMachineSetting('machine_width', '230')
436 profile.putMachineSetting('machine_depth', '225')
437 profile.putMachineSetting('machine_height', '205')
438 profile.putMachineSetting('machine_name', 'ultimaker2')
439 profile.putMachineSetting('machine_type', 'ultimaker2')
440 profile.putMachineSetting('machine_center_is_zero', 'False')
441 profile.putMachineSetting('has_heated_bed', 'True')
442 profile.putMachineSetting('gcode_flavor', 'UltiGCode')
443 profile.putMachineSetting('extruder_head_size_min_x', '40.0')
444 profile.putMachineSetting('extruder_head_size_min_y', '10.0')
445 profile.putMachineSetting('extruder_head_size_max_x', '60.0')
446 profile.putMachineSetting('extruder_head_size_max_y', '30.0')
447 profile.putMachineSetting('extruder_head_size_height', '48.0')
448 profile.putProfileSetting('nozzle_size', '0.4')
449 profile.putProfileSetting('fan_full_height', '5.0')
450 profile.putMachineSetting('extruder_offset_x1', '18.0')
451 profile.putMachineSetting('extruder_offset_y1', '0.0')
452 elif self.UltimakerRadio.GetValue():
453 profile.putMachineSetting('machine_width', '205')
454 profile.putMachineSetting('machine_depth', '205')
455 profile.putMachineSetting('machine_height', '200')
456 profile.putMachineSetting('machine_name', 'ultimaker original')
457 profile.putMachineSetting('machine_type', 'ultimaker')
458 profile.putMachineSetting('machine_center_is_zero', 'False')
459 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
460 profile.putProfileSetting('nozzle_size', '0.4')
461 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
462 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
463 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
464 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
465 profile.putMachineSetting('extruder_head_size_height', '55.0')
466 elif self.UltimakerOPRadio.GetValue():
467 profile.putMachineSetting('machine_width', '205')
468 profile.putMachineSetting('machine_depth', '205')
469 profile.putMachineSetting('machine_height', '200')
470 profile.putMachineSetting('machine_name', 'ultimaker original+')
471 profile.putMachineSetting('machine_type', 'ultimaker_plus')
472 profile.putMachineSetting('machine_center_is_zero', 'False')
473 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
474 profile.putProfileSetting('nozzle_size', '0.4')
475 profile.putMachineSetting('extruder_head_size_min_x', '75.0')
476 profile.putMachineSetting('extruder_head_size_min_y', '18.0')
477 profile.putMachineSetting('extruder_head_size_max_x', '18.0')
478 profile.putMachineSetting('extruder_head_size_max_y', '35.0')
479 profile.putMachineSetting('extruder_head_size_height', '55.0')
480 profile.putMachineSetting('has_heated_bed', 'True')
481 profile.putMachineSetting('extruder_amount', '1')
482 profile.putProfileSetting('retraction_enable', 'True')
483 elif self.LulzbotTazRadio.GetValue() or self.LulzbotMiniRadio.GetValue():
484 if self.LulzbotTazRadio.GetValue():
485 profile.putMachineSetting('machine_width', '298')
486 profile.putMachineSetting('machine_depth', '275')
487 profile.putMachineSetting('machine_height', '250')
488 profile.putMachineSetting('machine_name', 'Lulzbot TAZ')
490 profile.putMachineSetting('machine_width', '160')
491 profile.putMachineSetting('machine_depth', '160')
492 profile.putMachineSetting('machine_height', '160')
493 profile.putMachineSetting('machine_name', 'Lulzbot Mini')
494 profile.putMachineSetting('machine_type', 'Aleph Objects')
495 profile.putMachineSetting('machine_center_is_zero', 'False')
496 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
497 profile.putMachineSetting('has_heated_bed', 'True')
498 profile.putProfileSetting('nozzle_size', '0.4')
499 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
500 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
501 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
502 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
503 profile.putMachineSetting('extruder_head_size_height', '0.0')
505 profile.putMachineSetting('machine_width', '80')
506 profile.putMachineSetting('machine_depth', '80')
507 profile.putMachineSetting('machine_height', '60')
508 profile.putMachineSetting('machine_name', 'reprap')
509 profile.putMachineSetting('machine_type', 'reprap')
510 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
511 profile.putPreference('startMode', 'Normal')
512 profile.putProfileSetting('nozzle_size', '0.5')
513 profile.checkAndUpdateMachineName()
514 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
515 if self.SubmitUserStats.GetValue():
516 profile.putPreference('submit_slice_information', 'True')
518 profile.putPreference('submit_slice_information', 'False')
521 class SelectParts(InfoPage):
522 def __init__(self, parent):
523 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
524 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."))
526 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
527 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
528 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
529 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
531 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."))
532 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
533 self.springExtruder.SetValue(True)
536 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
537 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
538 profile.putMachineSetting('has_heated_bed', 'True')
540 profile.putMachineSetting('has_heated_bed', 'False')
541 if self.dualExtrusion.GetValue():
542 profile.putMachineSetting('extruder_amount', '2')
543 profile.putMachineSetting('machine_depth', '195')
545 profile.putMachineSetting('extruder_amount', '1')
546 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
547 profile.putProfileSetting('retraction_enable', 'True')
549 profile.putProfileSetting('retraction_enable', 'False')
552 class UltimakerFirmwareUpgradePage(InfoPage):
553 def __init__(self, parent):
554 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
555 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."))
556 self.AddHiddenSeperator()
557 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
558 self.AddHiddenSeperator()
559 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."))
560 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
561 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
562 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
563 self.AddHiddenSeperator()
564 if profile.getMachineSetting('machine_type') == 'ultimaker':
565 self.AddText(_("Do not upgrade to this firmware if:"))
566 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
567 self.AddText(_("* Build your own heated bed"))
568 self.AddText(_("* Have other changes in the firmware"))
569 # button = self.AddButton('Goto this page for a custom firmware')
570 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
575 def OnUpgradeClick(self, e):
576 if firmwareInstall.InstallFirmware():
577 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
579 def OnSkipClick(self, e):
580 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
581 self.GetParent().ShowPage(self.GetNext())
583 def OnUrlClick(self, e):
584 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
586 class UltimakerCheckupPage(InfoPage):
587 def __init__(self, parent):
588 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")
590 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
591 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
592 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
593 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
594 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
595 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
596 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
597 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
598 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
599 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
602 _("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."))
603 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
604 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
605 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
607 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
608 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
609 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
611 self.infoBox = self.AddInfoBox()
612 self.machineState = self.AddText("")
613 self.temperatureLabel = self.AddText("")
614 self.errorLogButton = self.AddButton(_("Show error log"))
615 self.errorLogButton.Show(False)
617 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
619 self.xMinStop = False
620 self.xMaxStop = False
621 self.yMinStop = False
622 self.yMaxStop = False
623 self.zMinStop = False
624 self.zMaxStop = False
626 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
629 if self.comm is not None:
633 self.endstopBitmap.Show(False)
636 def OnSkipClick(self, e):
637 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
638 self.GetParent().ShowPage(self.GetNext())
640 def OnCheckClick(self, e=None):
641 self.errorLogButton.Show(False)
642 if self.comm is not None:
646 wx.CallAfter(self.OnCheckClick)
648 self.infoBox.SetBusy(_("Connecting to machine."))
649 self.commState.SetBitmap(self.unknownBitmap)
650 self.tempState.SetBitmap(self.unknownBitmap)
651 self.stopState.SetBitmap(self.unknownBitmap)
652 self.checkupState = 0
653 self.checkExtruderNr = 0
654 self.comm = machineCom.MachineCom(callbackObject=self)
656 def OnErrorLog(self, e):
657 printWindow.LogWindow('\n'.join(self.comm.getLog()))
659 def mcLog(self, message):
662 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
663 if not self.comm.isOperational():
665 if self.checkupState == 0:
666 self.tempCheckTimeout = 20
667 if temp[self.checkExtruderNr] > 70:
668 self.checkupState = 1
669 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
670 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
671 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
673 self.startTemp = temp[self.checkExtruderNr]
674 self.checkupState = 2
675 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
676 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
677 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
678 elif self.checkupState == 1:
679 if temp[self.checkExtruderNr] < 60:
680 self.startTemp = temp[self.checkExtruderNr]
681 self.checkupState = 2
682 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
683 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
684 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
685 elif self.checkupState == 2:
686 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
687 if temp[self.checkExtruderNr] > self.startTemp + 40:
688 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
689 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
690 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
691 self.checkExtruderNr = 0
692 self.checkupState = 3
693 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
694 wx.CallAfter(self.endstopBitmap.Show, True)
695 wx.CallAfter(self.Layout)
696 self.comm.sendCommand('M119')
697 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
699 self.checkupState = 0
700 self.checkExtruderNr += 1
702 self.tempCheckTimeout -= 1
703 if self.tempCheckTimeout < 1:
704 self.checkupState = -1
705 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
706 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
707 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
708 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
709 elif self.checkupState >= 3 and self.checkupState < 10:
710 self.comm.sendCommand('M119')
711 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
713 def mcStateChange(self, state):
714 if self.comm is None:
716 if self.comm.isOperational():
717 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
718 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
719 elif self.comm.isError():
720 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
721 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
722 wx.CallAfter(self.endstopBitmap.Show, False)
723 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
724 wx.CallAfter(self.errorLogButton.Show, True)
725 wx.CallAfter(self.Layout)
727 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
729 def mcMessage(self, message):
730 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
731 for data in message.split(' '):
733 tag, value = data.split(':', 1)
735 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
737 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
739 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
741 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
743 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
745 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
747 tag, value = map(str.strip, message.split(':', 1))
749 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
751 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
753 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
755 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
757 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
759 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
760 if 'z_max' in message:
761 self.comm.sendCommand('M119')
763 if self.checkupState == 3:
764 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
765 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
766 self.checkupState = 5
767 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
768 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
770 self.checkupState = 4
771 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
772 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
773 elif self.checkupState == 4:
774 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
775 self.checkupState = 5
776 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
777 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
778 elif self.checkupState == 5:
779 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
780 self.checkupState = 6
781 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
782 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
783 elif self.checkupState == 6:
784 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
785 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
786 self.checkupState = 8
787 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
788 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
790 self.checkupState = 7
791 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
792 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
793 elif self.checkupState == 7:
794 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
795 self.checkupState = 8
796 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
797 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
798 elif self.checkupState == 8:
799 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
800 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
801 self.checkupState = 10
803 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
804 wx.CallAfter(self.infoBox.SetReadyIndicator)
805 wx.CallAfter(self.endstopBitmap.Show, False)
806 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
807 wx.CallAfter(self.OnSkipClick, None)
809 self.checkupState = 9
810 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
811 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
812 elif self.checkupState == 9:
813 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
814 self.checkupState = 10
816 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
817 wx.CallAfter(self.infoBox.SetReadyIndicator)
818 wx.CallAfter(self.endstopBitmap.Show, False)
819 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
820 wx.CallAfter(self.OnSkipClick, None)
822 def mcProgress(self, lineNr):
825 def mcZChange(self, newZ):
829 class UltimakerCalibrationPage(InfoPage):
830 def __init__(self, parent):
831 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")
833 self.AddText("Your Ultimaker requires some calibration.")
834 self.AddText("This calibration is needed for a proper extrusion amount.")
836 self.AddText("The following values are needed:")
837 self.AddText("* Diameter of filament")
838 self.AddText("* Number of steps per mm of filament extrusion")
840 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
842 self.AddText("First we need the diameter of your filament:")
843 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
845 "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.")
846 self.AddText("Note: This value can be changed later at any time.")
849 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
852 class UltimakerCalibrateStepsPerEPage(InfoPage):
853 def __init__(self, parent):
854 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")
856 #if profile.getMachineSetting('steps_per_e') == '0':
857 # profile.putMachineSetting('steps_per_e', '865.888')
859 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
860 self.AddText(_("First remove any filament from your machine."))
861 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
862 self.AddText(_("We'll push the filament 100mm"))
863 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
864 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
865 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
866 self.AddText(_("This results in the following steps per E:"))
867 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
868 self.AddText(_("You can repeat these steps to get better calibration."))
871 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
872 self.heatButton = self.AddButton(_("Heatup for filament removal"))
874 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
875 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
876 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
878 def OnSaveLengthClick(self, e):
879 currentEValue = float(self.stepsPerEInput.GetValue())
880 realExtrudeLength = float(self.lengthInput.GetValue())
881 newEValue = currentEValue * 100 / realExtrudeLength
882 self.stepsPerEInput.SetValue(str(newEValue))
883 self.lengthInput.SetValue("100")
885 def OnExtrudeClick(self, e):
886 t = threading.Thread(target=self.OnExtrudeRun)
890 def OnExtrudeRun(self):
891 self.heatButton.Enable(False)
892 self.extrudeButton.Enable(False)
893 currentEValue = float(self.stepsPerEInput.GetValue())
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()
908 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
911 self.sendGCommand('M302') #Disable cold extrusion protection
912 self.sendGCommand("M92 E%f" % (currentEValue))
913 self.sendGCommand("G92 E0")
914 self.sendGCommand("G1 E100 F600")
917 self.extrudeButton.Enable()
918 self.heatButton.Enable()
920 def OnHeatClick(self, e):
921 t = threading.Thread(target=self.OnHeatRun)
926 self.heatButton.Enable(False)
927 self.extrudeButton.Enable(False)
928 self.comm = machineCom.MachineCom()
929 if not self.comm.isOpen():
931 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
932 'Printer error', wx.OK | wx.ICON_INFORMATION)
933 self.heatButton.Enable(True)
934 self.extrudeButton.Enable(True)
937 line = self.comm.readline()
939 self.heatButton.Enable(True)
940 self.extrudeButton.Enable(True)
944 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
947 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
949 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
950 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
951 self.sendGCommand('M104 S0')
954 self.heatButton.Enable(True)
955 self.extrudeButton.Enable(True)
957 def sendGCommand(self, cmd):
958 self.comm.sendCommand(cmd) #Disable cold extrusion protection
960 line = self.comm.readline()
963 if line.startswith('ok'):
967 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
969 class Ultimaker2ReadyPage(InfoPage):
970 def __init__(self, parent):
971 super(Ultimaker2ReadyPage, self).__init__(parent, "Ultimaker2")
972 self.AddText('Congratulations on your the purchase of your brand new Ultimaker2.')
973 self.AddText('Cura is now ready to be used with your Ultimaker2.')
976 class LulzbotReadyPage(InfoPage):
977 def __init__(self, parent):
978 super(LulzbotReadyPage, self).__init__(parent, "Lulzbot TAZ/Mini")
979 self.AddText('Cura is now ready to be used with your Lulzbot.')
982 class configWizard(wx.wizard.Wizard):
983 def __init__(self, addNew = False):
984 super(configWizard, self).__init__(None, -1, "Configuration Wizard")
986 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
987 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
989 self.firstInfoPage = FirstInfoPage(self, addNew)
990 self.machineSelectPage = MachineSelectPage(self)
991 self.ultimakerSelectParts = SelectParts(self)
992 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
993 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
994 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
995 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
996 self.bedLevelPage = bedLevelWizardMain(self)
997 self.headOffsetCalibration = headOffsetCalibrationPage(self)
998 self.printrbotSelectType = PrintrbotPage(self)
999 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1000 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1001 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1003 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1004 self.lulzbotReadyPage = LulzbotReadyPage(self)
1006 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
1007 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
1008 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1009 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1010 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1011 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1012 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
1013 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1014 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1016 self.FitToPage(self.firstInfoPage)
1017 self.GetPageAreaSizer().Add(self.firstInfoPage)
1019 self.RunWizard(self.firstInfoPage)
1022 def OnPageChanging(self, e):
1023 e.GetPage().StoreData()
1025 def OnPageChanged(self, e):
1026 if e.GetPage().AllowNext():
1027 self.FindWindowById(wx.ID_FORWARD).Enable()
1029 self.FindWindowById(wx.ID_FORWARD).Disable()
1030 if e.GetPage().AllowBack():
1031 self.FindWindowById(wx.ID_BACKWARD).Enable()
1033 self.FindWindowById(wx.ID_BACKWARD).Disable()
1035 class bedLevelWizardMain(InfoPage):
1036 def __init__(self, parent):
1037 super(bedLevelWizardMain, self).__init__(parent, "Bed leveling wizard")
1039 self.AddText('This wizard will help you in leveling your printer bed')
1041 self.AddText('It will do the following steps')
1042 self.AddText('* Move the printer head to each corner')
1043 self.AddText(' and let you adjust the height of the bed to the nozzle')
1044 self.AddText('* Print a line around the bed to check if it is level')
1047 self.connectButton = self.AddButton('Connect to printer')
1050 self.infoBox = self.AddInfoBox()
1051 self.resumeButton = self.AddButton('Resume')
1052 self.upButton, self.downButton = self.AddDualButton('Up 0.2mm', 'Down 0.2mm')
1053 self.upButton2, self.downButton2 = self.AddDualButton('Up 10mm', 'Down 10mm')
1054 self.resumeButton.Enable(False)
1056 self.upButton.Enable(False)
1057 self.downButton.Enable(False)
1058 self.upButton2.Enable(False)
1059 self.downButton2.Enable(False)
1061 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1062 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1063 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1064 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1065 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1066 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1068 def OnConnect(self, e = None):
1069 if self.comm is not None:
1073 wx.CallAfter(self.OnConnect)
1075 self.connectButton.Enable(False)
1076 self.comm = machineCom.MachineCom(callbackObject=self)
1077 self.infoBox.SetBusy('Connecting to machine.')
1078 self._wizardState = 0
1080 def OnBedUp(self, e):
1081 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1082 self.comm.sendCommand('G92 Z10')
1083 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1084 self.comm.sendCommand('M400')
1086 def OnBedDown(self, e):
1087 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1088 self.comm.sendCommand('G92 Z10')
1089 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1090 self.comm.sendCommand('M400')
1092 def OnBedUp2(self, e):
1093 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1094 self.comm.sendCommand('G92 Z10')
1095 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1096 self.comm.sendCommand('M400')
1098 def OnBedDown2(self, e):
1099 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1100 self.comm.sendCommand('G92 Z10')
1101 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1102 self.comm.sendCommand('M400')
1104 def AllowNext(self):
1105 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1106 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1109 def OnResume(self, e):
1110 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1111 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1112 if self._wizardState == -1:
1113 wx.CallAfter(self.infoBox.SetInfo, 'Homing printer...')
1114 wx.CallAfter(self.upButton.Enable, False)
1115 wx.CallAfter(self.downButton.Enable, False)
1116 wx.CallAfter(self.upButton2.Enable, False)
1117 wx.CallAfter(self.downButton2.Enable, False)
1118 self.comm.sendCommand('M105')
1119 self.comm.sendCommand('G28')
1120 self._wizardState = 1
1121 elif self._wizardState == 2:
1122 if profile.getMachineSetting('has_heated_bed') == 'True':
1123 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back center...')
1124 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1125 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1126 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1127 self.comm.sendCommand('M400')
1128 self._wizardState = 3
1130 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back left corner...')
1131 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1132 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1133 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1134 self.comm.sendCommand('M400')
1135 self._wizardState = 3
1136 elif self._wizardState == 4:
1137 if profile.getMachineSetting('has_heated_bed') == 'True':
1138 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to front right corner...')
1139 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1140 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1141 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1142 self.comm.sendCommand('M400')
1143 self._wizardState = 7
1145 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back right corner...')
1146 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1147 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1148 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1149 self.comm.sendCommand('M400')
1150 self._wizardState = 5
1151 elif self._wizardState == 6:
1152 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to front right corner...')
1153 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1154 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1155 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1156 self.comm.sendCommand('M400')
1157 self._wizardState = 7
1158 elif self._wizardState == 8:
1159 wx.CallAfter(self.infoBox.SetBusy, 'Heating up printer...')
1160 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1161 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1162 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1163 self._wizardState = 9
1164 elif self._wizardState == 10:
1165 self._wizardState = 11
1166 wx.CallAfter(self.infoBox.SetInfo, 'Printing a square on the printer bed at 0.3mm height.')
1167 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1168 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1169 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1170 w = profile.getMachineSettingFloat('machine_width') - 10
1171 d = profile.getMachineSettingFloat('machine_depth')
1172 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1173 filamentArea = math.pi * filamentRadius * filamentRadius
1174 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1178 'G1 Z2 F%d' % (feedZ),
1180 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1181 'G1 Z0.3 F%d' % (feedZ)]
1183 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1185 for i in xrange(0, 3):
1186 dist = 5.0 + 0.4 * float(i)
1187 eValue += (d - 2.0*dist) * ePerMM
1188 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1189 eValue += (w - 2.0*dist) * ePerMM
1190 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1191 eValue += (d - 2.0*dist) * ePerMM
1192 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1193 eValue += (w - 2.0*dist) * ePerMM
1194 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1196 gcodeList.append('M400')
1197 self.comm.printGCode(gcodeList)
1198 self.resumeButton.Enable(False)
1200 def mcLog(self, message):
1201 print 'Log:', message
1203 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1204 if self._wizardState == 1:
1205 self._wizardState = 2
1206 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.')
1207 wx.CallAfter(self.resumeButton.Enable, True)
1208 elif self._wizardState == 3:
1209 self._wizardState = 4
1210 if profile.getMachineSetting('has_heated_bed') == 'True':
1211 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.')
1213 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.')
1214 wx.CallAfter(self.resumeButton.Enable, True)
1215 elif self._wizardState == 5:
1216 self._wizardState = 6
1217 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.')
1218 wx.CallAfter(self.resumeButton.Enable, True)
1219 elif self._wizardState == 7:
1220 self._wizardState = 8
1221 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.')
1222 wx.CallAfter(self.resumeButton.Enable, True)
1223 elif self._wizardState == 9:
1224 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1225 wx.CallAfter(self.infoBox.SetInfo, 'Heating up printer: %d/%d' % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1227 wx.CallAfter(self.infoBox.SetAttention, 'The printer is hot now. Please insert some PLA filament into the printer.')
1228 wx.CallAfter(self.resumeButton.Enable, True)
1229 self._wizardState = 10
1231 def mcStateChange(self, state):
1232 if self.comm is None:
1234 if self.comm.isOperational():
1235 if self._wizardState == 0:
1236 wx.CallAfter(self.infoBox.SetAttention, 'Use the up/down buttons to move the bed and adjust your Z endstop.')
1237 wx.CallAfter(self.upButton.Enable, True)
1238 wx.CallAfter(self.downButton.Enable, True)
1239 wx.CallAfter(self.upButton2.Enable, True)
1240 wx.CallAfter(self.downButton2.Enable, True)
1241 wx.CallAfter(self.resumeButton.Enable, True)
1242 self._wizardState = -1
1243 elif self._wizardState == 11 and not self.comm.isPrinting():
1244 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1245 self.comm.sendCommand('G92 E0')
1246 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1247 self.comm.sendCommand('M104 S0')
1248 wx.CallAfter(self.infoBox.SetInfo, 'Calibration finished.\nThe squares on the bed should slightly touch each other.')
1249 wx.CallAfter(self.infoBox.SetReadyIndicator)
1250 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1251 wx.CallAfter(self.connectButton.Enable, True)
1252 self._wizardState = 12
1253 elif self.comm.isError():
1254 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1256 def mcMessage(self, message):
1259 def mcProgress(self, lineNr):
1262 def mcZChange(self, newZ):
1265 class headOffsetCalibrationPage(InfoPage):
1266 def __init__(self, parent):
1267 super(headOffsetCalibrationPage, self).__init__(parent, "Printer head offset calibration")
1269 self.AddText('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine')
1272 self.connectButton = self.AddButton('Connect to printer')
1275 self.infoBox = self.AddInfoBox()
1276 self.textEntry = self.AddTextCtrl('')
1277 self.textEntry.Enable(False)
1278 self.resumeButton = self.AddButton('Resume')
1279 self.resumeButton.Enable(False)
1281 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1282 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1284 def AllowBack(self):
1287 def OnConnect(self, e = None):
1288 if self.comm is not None:
1292 wx.CallAfter(self.OnConnect)
1294 self.connectButton.Enable(False)
1295 self.comm = machineCom.MachineCom(callbackObject=self)
1296 self.infoBox.SetBusy('Connecting to machine.')
1297 self._wizardState = 0
1299 def OnResume(self, e):
1300 if self._wizardState == 2:
1301 self._wizardState = 3
1302 wx.CallAfter(self.infoBox.SetBusy, 'Printing initial calibration cross')
1304 w = profile.getMachineSettingFloat('machine_width')
1305 d = profile.getMachineSettingFloat('machine_depth')
1307 gcode = gcodeGenerator.gcodeGenerator()
1308 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1309 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1316 gcode.addMove(w/2, 5)
1317 gcode.addMove(z=0.2)
1319 gcode.addExtrude(w/2, d-5.0)
1321 gcode.addMove(5, d/2)
1323 gcode.addExtrude(w-5.0, d/2)
1324 gcode.addRetract(15)
1327 gcode.addMove(w/2, 5)
1329 gcode.addExtrude(w/2, d-5.0)
1331 gcode.addMove(5, d/2)
1333 gcode.addExtrude(w-5.0, d/2)
1334 gcode.addRetract(15)
1339 gcode.addCmd('M400')
1341 self.comm.printGCode(gcode.list())
1342 self.resumeButton.Enable(False)
1343 elif self._wizardState == 4:
1345 float(self.textEntry.GetValue())
1348 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1349 self._wizardState = 5
1350 self.infoBox.SetAttention('Please measure the distance between the horizontal lines in millimeters.')
1351 self.textEntry.SetValue('0.0')
1352 self.textEntry.Enable(True)
1353 elif self._wizardState == 5:
1355 float(self.textEntry.GetValue())
1358 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1359 self._wizardState = 6
1360 self.infoBox.SetBusy('Printing the fine calibration lines.')
1361 self.textEntry.SetValue('')
1362 self.textEntry.Enable(False)
1363 self.resumeButton.Enable(False)
1365 x = profile.getMachineSettingFloat('extruder_offset_x1')
1366 y = profile.getMachineSettingFloat('extruder_offset_y1')
1367 gcode = gcodeGenerator.gcodeGenerator()
1368 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1369 gcode.setPrintSpeed(25)
1372 gcode.addMove(50, 40, 0.2)
1374 for n in xrange(0, 10):
1375 gcode.addExtrude(50 + n * 10, 150)
1376 gcode.addExtrude(50 + n * 10 + 5, 150)
1377 gcode.addExtrude(50 + n * 10 + 5, 40)
1378 gcode.addExtrude(50 + n * 10 + 10, 40)
1379 gcode.addMove(40, 50)
1380 for n in xrange(0, 10):
1381 gcode.addExtrude(150, 50 + n * 10)
1382 gcode.addExtrude(150, 50 + n * 10 + 5)
1383 gcode.addExtrude(40, 50 + n * 10 + 5)
1384 gcode.addExtrude(40, 50 + n * 10 + 10)
1385 gcode.addRetract(15)
1388 gcode.addMove(50 - x, 30 - y, 0.2)
1390 for n in xrange(0, 10):
1391 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1392 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1393 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1394 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1395 gcode.addMove(30 - x, 50 - y, 0.2)
1396 for n in xrange(0, 10):
1397 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1398 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1399 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1400 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1401 gcode.addRetract(15)
1403 gcode.addCmd('M400')
1404 gcode.addCmd('M104 T0 S0')
1405 gcode.addCmd('M104 T1 S0')
1406 self.comm.printGCode(gcode.list())
1407 elif self._wizardState == 7:
1409 n = int(self.textEntry.GetValue()) - 1
1412 x = profile.getMachineSettingFloat('extruder_offset_x1')
1414 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1415 self.infoBox.SetAttention('Which horizontal line number lays perfect on top of each other? Front most line is zero.')
1416 self.textEntry.SetValue('10')
1417 self._wizardState = 8
1418 elif self._wizardState == 8:
1420 n = int(self.textEntry.GetValue()) - 1
1423 y = profile.getMachineSettingFloat('extruder_offset_y1')
1425 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1426 self.infoBox.SetInfo('Calibration finished. Offsets are: %s %s' % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1427 self.infoBox.SetReadyIndicator()
1428 self._wizardState = 8
1430 self.resumeButton.Enable(False)
1432 def mcLog(self, message):
1433 print 'Log:', message
1435 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1436 if self._wizardState == 1:
1437 if temp[0] >= 210 and temp[1] >= 210:
1438 self._wizardState = 2
1439 wx.CallAfter(self.infoBox.SetAttention, 'Please load both extruders with PLA.')
1440 wx.CallAfter(self.resumeButton.Enable, True)
1441 wx.CallAfter(self.resumeButton.SetFocus)
1443 def mcStateChange(self, state):
1444 if self.comm is None:
1446 if self.comm.isOperational():
1447 if self._wizardState == 0:
1448 wx.CallAfter(self.infoBox.SetInfo, 'Homing printer and heating up both extruders.')
1449 self.comm.sendCommand('M105')
1450 self.comm.sendCommand('M104 S220 T0')
1451 self.comm.sendCommand('M104 S220 T1')
1452 self.comm.sendCommand('G28')
1453 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1454 self._wizardState = 1
1455 if not self.comm.isPrinting():
1456 if self._wizardState == 3:
1457 self._wizardState = 4
1458 wx.CallAfter(self.infoBox.SetAttention, 'Please measure the distance between the vertical lines in millimeters.')
1459 wx.CallAfter(self.textEntry.SetValue, '0.0')
1460 wx.CallAfter(self.textEntry.Enable, True)
1461 wx.CallAfter(self.resumeButton.Enable, True)
1462 wx.CallAfter(self.resumeButton.SetFocus)
1463 elif self._wizardState == 6:
1464 self._wizardState = 7
1465 wx.CallAfter(self.infoBox.SetAttention, 'Which vertical line number lays perfect on top of each other? Leftmost line is zero.')
1466 wx.CallAfter(self.textEntry.SetValue, '10')
1467 wx.CallAfter(self.textEntry.Enable, True)
1468 wx.CallAfter(self.resumeButton.Enable, True)
1469 wx.CallAfter(self.resumeButton.SetFocus)
1471 elif self.comm.isError():
1472 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1474 def mcMessage(self, message):
1477 def mcProgress(self, lineNr):
1480 def mcZChange(self, newZ):
1483 class bedLevelWizard(wx.wizard.Wizard):
1485 super(bedLevelWizard, self).__init__(None, -1, "Bed leveling wizard")
1487 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1488 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1490 self.mainPage = bedLevelWizardMain(self)
1491 self.headOffsetCalibration = None
1493 self.FitToPage(self.mainPage)
1494 self.GetPageAreaSizer().Add(self.mainPage)
1496 self.RunWizard(self.mainPage)
1499 def OnPageChanging(self, e):
1500 e.GetPage().StoreData()
1502 def OnPageChanged(self, e):
1503 if e.GetPage().AllowNext():
1504 self.FindWindowById(wx.ID_FORWARD).Enable()
1506 self.FindWindowById(wx.ID_FORWARD).Disable()
1507 if e.GetPage().AllowBack():
1508 self.FindWindowById(wx.ID_BACKWARD).Enable()
1510 self.FindWindowById(wx.ID_BACKWARD).Disable()
1512 class headOffsetWizard(wx.wizard.Wizard):
1514 super(headOffsetWizard, self).__init__(None, -1, "Head offset wizard")
1516 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1517 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1519 self.mainPage = headOffsetCalibrationPage(self)
1521 self.FitToPage(self.mainPage)
1522 self.GetPageAreaSizer().Add(self.mainPage)
1524 self.RunWizard(self.mainPage)
1527 def OnPageChanging(self, e):
1528 e.GetPage().StoreData()
1530 def OnPageChanged(self, e):
1531 if e.GetPage().AllowNext():
1532 self.FindWindowById(wx.ID_FORWARD).Enable()
1534 self.FindWindowById(wx.ID_FORWARD).Disable()
1535 if e.GetPage().AllowBack():
1536 self.FindWindowById(wx.ID_BACKWARD).Enable()
1538 self.FindWindowById(wx.ID_BACKWARD).Disable()