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.putProfileSetting('nozzle_size', '0.35')
489 profile.putMachineSetting('machine_name', 'Lulzbot TAZ')
491 profile.putMachineSetting('machine_width', '160')
492 profile.putMachineSetting('machine_depth', '160')
493 profile.putMachineSetting('machine_height', '160')
494 profile.putProfileSetting('nozzle_size', '0.5')
495 profile.putMachineSetting('machine_name', 'Lulzbot Mini')
496 profile.putMachineSetting('machine_type', 'Aleph Objects')
497 profile.putMachineSetting('machine_center_is_zero', 'False')
498 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
499 profile.putMachineSetting('has_heated_bed', 'True')
500 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
501 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
502 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
503 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
504 profile.putMachineSetting('extruder_head_size_height', '0.0')
506 profile.putMachineSetting('machine_width', '80')
507 profile.putMachineSetting('machine_depth', '80')
508 profile.putMachineSetting('machine_height', '60')
509 profile.putMachineSetting('machine_name', 'reprap')
510 profile.putMachineSetting('machine_type', 'reprap')
511 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
512 profile.putPreference('startMode', 'Normal')
513 profile.putProfileSetting('nozzle_size', '0.5')
514 profile.checkAndUpdateMachineName()
515 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
516 if self.SubmitUserStats.GetValue():
517 profile.putPreference('submit_slice_information', 'True')
519 profile.putPreference('submit_slice_information', 'False')
522 class SelectParts(InfoPage):
523 def __init__(self, parent):
524 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
525 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."))
527 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
528 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
529 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
530 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
532 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."))
533 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
534 self.springExtruder.SetValue(True)
537 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
538 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
539 profile.putMachineSetting('has_heated_bed', 'True')
541 profile.putMachineSetting('has_heated_bed', 'False')
542 if self.dualExtrusion.GetValue():
543 profile.putMachineSetting('extruder_amount', '2')
544 profile.putMachineSetting('machine_depth', '195')
546 profile.putMachineSetting('extruder_amount', '1')
547 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
548 profile.putProfileSetting('retraction_enable', 'True')
550 profile.putProfileSetting('retraction_enable', 'False')
553 class UltimakerFirmwareUpgradePage(InfoPage):
554 def __init__(self, parent):
555 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
556 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."))
557 self.AddHiddenSeperator()
558 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
559 self.AddHiddenSeperator()
560 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."))
561 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
562 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
563 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
564 self.AddHiddenSeperator()
565 if profile.getMachineSetting('machine_type') == 'ultimaker':
566 self.AddText(_("Do not upgrade to this firmware if:"))
567 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
568 self.AddText(_("* Build your own heated bed"))
569 self.AddText(_("* Have other changes in the firmware"))
570 # button = self.AddButton('Goto this page for a custom firmware')
571 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
576 def OnUpgradeClick(self, e):
577 if firmwareInstall.InstallFirmware():
578 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
580 def OnSkipClick(self, e):
581 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
582 self.GetParent().ShowPage(self.GetNext())
584 def OnUrlClick(self, e):
585 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
587 class UltimakerCheckupPage(InfoPage):
588 def __init__(self, parent):
589 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")
591 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
592 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
593 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
594 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
595 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
596 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
597 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
598 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
599 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
600 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
603 _("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."))
604 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
605 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
606 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
608 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
609 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
610 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
612 self.infoBox = self.AddInfoBox()
613 self.machineState = self.AddText("")
614 self.temperatureLabel = self.AddText("")
615 self.errorLogButton = self.AddButton(_("Show error log"))
616 self.errorLogButton.Show(False)
618 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
620 self.xMinStop = False
621 self.xMaxStop = False
622 self.yMinStop = False
623 self.yMaxStop = False
624 self.zMinStop = False
625 self.zMaxStop = False
627 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
630 if self.comm is not None:
634 self.endstopBitmap.Show(False)
637 def OnSkipClick(self, e):
638 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
639 self.GetParent().ShowPage(self.GetNext())
641 def OnCheckClick(self, e=None):
642 self.errorLogButton.Show(False)
643 if self.comm is not None:
647 wx.CallAfter(self.OnCheckClick)
649 self.infoBox.SetBusy(_("Connecting to machine."))
650 self.commState.SetBitmap(self.unknownBitmap)
651 self.tempState.SetBitmap(self.unknownBitmap)
652 self.stopState.SetBitmap(self.unknownBitmap)
653 self.checkupState = 0
654 self.checkExtruderNr = 0
655 self.comm = machineCom.MachineCom(callbackObject=self)
657 def OnErrorLog(self, e):
658 printWindow.LogWindow('\n'.join(self.comm.getLog()))
660 def mcLog(self, message):
663 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
664 if not self.comm.isOperational():
666 if self.checkupState == 0:
667 self.tempCheckTimeout = 20
668 if temp[self.checkExtruderNr] > 70:
669 self.checkupState = 1
670 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
671 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
672 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
674 self.startTemp = temp[self.checkExtruderNr]
675 self.checkupState = 2
676 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
677 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
678 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
679 elif self.checkupState == 1:
680 if temp[self.checkExtruderNr] < 60:
681 self.startTemp = temp[self.checkExtruderNr]
682 self.checkupState = 2
683 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
684 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
685 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
686 elif self.checkupState == 2:
687 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
688 if temp[self.checkExtruderNr] > self.startTemp + 40:
689 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
690 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
691 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
692 self.checkExtruderNr = 0
693 self.checkupState = 3
694 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
695 wx.CallAfter(self.endstopBitmap.Show, True)
696 wx.CallAfter(self.Layout)
697 self.comm.sendCommand('M119')
698 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
700 self.checkupState = 0
701 self.checkExtruderNr += 1
703 self.tempCheckTimeout -= 1
704 if self.tempCheckTimeout < 1:
705 self.checkupState = -1
706 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
707 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
708 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
709 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
710 elif self.checkupState >= 3 and self.checkupState < 10:
711 self.comm.sendCommand('M119')
712 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
714 def mcStateChange(self, state):
715 if self.comm is None:
717 if self.comm.isOperational():
718 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
719 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
720 elif self.comm.isError():
721 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
722 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
723 wx.CallAfter(self.endstopBitmap.Show, False)
724 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
725 wx.CallAfter(self.errorLogButton.Show, True)
726 wx.CallAfter(self.Layout)
728 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
730 def mcMessage(self, message):
731 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
732 for data in message.split(' '):
734 tag, value = data.split(':', 1)
736 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
738 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
740 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
742 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
744 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
746 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
748 tag, value = map(str.strip, message.split(':', 1))
750 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
752 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
754 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
756 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
758 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
760 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
761 if 'z_max' in message:
762 self.comm.sendCommand('M119')
764 if self.checkupState == 3:
765 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
766 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
767 self.checkupState = 5
768 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
769 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
771 self.checkupState = 4
772 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
773 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
774 elif self.checkupState == 4:
775 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
776 self.checkupState = 5
777 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
778 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
779 elif self.checkupState == 5:
780 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
781 self.checkupState = 6
782 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
783 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
784 elif self.checkupState == 6:
785 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
786 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
787 self.checkupState = 8
788 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
789 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
791 self.checkupState = 7
792 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
793 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
794 elif self.checkupState == 7:
795 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
796 self.checkupState = 8
797 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
798 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
799 elif self.checkupState == 8:
800 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
801 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
802 self.checkupState = 10
804 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
805 wx.CallAfter(self.infoBox.SetReadyIndicator)
806 wx.CallAfter(self.endstopBitmap.Show, False)
807 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
808 wx.CallAfter(self.OnSkipClick, None)
810 self.checkupState = 9
811 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
812 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
813 elif self.checkupState == 9:
814 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
815 self.checkupState = 10
817 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
818 wx.CallAfter(self.infoBox.SetReadyIndicator)
819 wx.CallAfter(self.endstopBitmap.Show, False)
820 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
821 wx.CallAfter(self.OnSkipClick, None)
823 def mcProgress(self, lineNr):
826 def mcZChange(self, newZ):
830 class UltimakerCalibrationPage(InfoPage):
831 def __init__(self, parent):
832 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")
834 self.AddText("Your Ultimaker requires some calibration.")
835 self.AddText("This calibration is needed for a proper extrusion amount.")
837 self.AddText("The following values are needed:")
838 self.AddText("* Diameter of filament")
839 self.AddText("* Number of steps per mm of filament extrusion")
841 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
843 self.AddText("First we need the diameter of your filament:")
844 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
846 "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.")
847 self.AddText("Note: This value can be changed later at any time.")
850 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
853 class UltimakerCalibrateStepsPerEPage(InfoPage):
854 def __init__(self, parent):
855 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")
857 #if profile.getMachineSetting('steps_per_e') == '0':
858 # profile.putMachineSetting('steps_per_e', '865.888')
860 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
861 self.AddText(_("First remove any filament from your machine."))
862 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
863 self.AddText(_("We'll push the filament 100mm"))
864 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
865 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
866 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
867 self.AddText(_("This results in the following steps per E:"))
868 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
869 self.AddText(_("You can repeat these steps to get better calibration."))
872 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
873 self.heatButton = self.AddButton(_("Heatup for filament removal"))
875 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
876 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
877 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
879 def OnSaveLengthClick(self, e):
880 currentEValue = float(self.stepsPerEInput.GetValue())
881 realExtrudeLength = float(self.lengthInput.GetValue())
882 newEValue = currentEValue * 100 / realExtrudeLength
883 self.stepsPerEInput.SetValue(str(newEValue))
884 self.lengthInput.SetValue("100")
886 def OnExtrudeClick(self, e):
887 t = threading.Thread(target=self.OnExtrudeRun)
891 def OnExtrudeRun(self):
892 self.heatButton.Enable(False)
893 self.extrudeButton.Enable(False)
894 currentEValue = float(self.stepsPerEInput.GetValue())
895 self.comm = machineCom.MachineCom()
896 if not self.comm.isOpen():
898 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
899 'Printer error', wx.OK | wx.ICON_INFORMATION)
900 self.heatButton.Enable(True)
901 self.extrudeButton.Enable(True)
904 line = self.comm.readline()
909 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
912 self.sendGCommand('M302') #Disable cold extrusion protection
913 self.sendGCommand("M92 E%f" % (currentEValue))
914 self.sendGCommand("G92 E0")
915 self.sendGCommand("G1 E100 F600")
918 self.extrudeButton.Enable()
919 self.heatButton.Enable()
921 def OnHeatClick(self, e):
922 t = threading.Thread(target=self.OnHeatRun)
927 self.heatButton.Enable(False)
928 self.extrudeButton.Enable(False)
929 self.comm = machineCom.MachineCom()
930 if not self.comm.isOpen():
932 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
933 'Printer error', wx.OK | wx.ICON_INFORMATION)
934 self.heatButton.Enable(True)
935 self.extrudeButton.Enable(True)
938 line = self.comm.readline()
940 self.heatButton.Enable(True)
941 self.extrudeButton.Enable(True)
945 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
948 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
950 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
951 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
952 self.sendGCommand('M104 S0')
955 self.heatButton.Enable(True)
956 self.extrudeButton.Enable(True)
958 def sendGCommand(self, cmd):
959 self.comm.sendCommand(cmd) #Disable cold extrusion protection
961 line = self.comm.readline()
964 if line.startswith('ok'):
968 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
970 class Ultimaker2ReadyPage(InfoPage):
971 def __init__(self, parent):
972 super(Ultimaker2ReadyPage, self).__init__(parent, "Ultimaker2")
973 self.AddText('Congratulations on your the purchase of your brand new Ultimaker2.')
974 self.AddText('Cura is now ready to be used with your Ultimaker2.')
977 class LulzbotReadyPage(InfoPage):
978 def __init__(self, parent):
979 super(LulzbotReadyPage, self).__init__(parent, "Lulzbot TAZ/Mini")
980 self.AddText('Cura is now ready to be used with your Lulzbot.')
983 class configWizard(wx.wizard.Wizard):
984 def __init__(self, addNew = False):
985 super(configWizard, self).__init__(None, -1, "Configuration Wizard")
987 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
988 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
990 self.firstInfoPage = FirstInfoPage(self, addNew)
991 self.machineSelectPage = MachineSelectPage(self)
992 self.ultimakerSelectParts = SelectParts(self)
993 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
994 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
995 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
996 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
997 self.bedLevelPage = bedLevelWizardMain(self)
998 self.headOffsetCalibration = headOffsetCalibrationPage(self)
999 self.printrbotSelectType = PrintrbotPage(self)
1000 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1001 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1002 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1004 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1005 self.lulzbotReadyPage = LulzbotReadyPage(self)
1007 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
1008 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
1009 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1010 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1011 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1012 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1013 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
1014 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1015 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1017 self.FitToPage(self.firstInfoPage)
1018 self.GetPageAreaSizer().Add(self.firstInfoPage)
1020 self.RunWizard(self.firstInfoPage)
1023 def OnPageChanging(self, e):
1024 e.GetPage().StoreData()
1026 def OnPageChanged(self, e):
1027 if e.GetPage().AllowNext():
1028 self.FindWindowById(wx.ID_FORWARD).Enable()
1030 self.FindWindowById(wx.ID_FORWARD).Disable()
1031 if e.GetPage().AllowBack():
1032 self.FindWindowById(wx.ID_BACKWARD).Enable()
1034 self.FindWindowById(wx.ID_BACKWARD).Disable()
1036 class bedLevelWizardMain(InfoPage):
1037 def __init__(self, parent):
1038 super(bedLevelWizardMain, self).__init__(parent, "Bed leveling wizard")
1040 self.AddText('This wizard will help you in leveling your printer bed')
1042 self.AddText('It will do the following steps')
1043 self.AddText('* Move the printer head to each corner')
1044 self.AddText(' and let you adjust the height of the bed to the nozzle')
1045 self.AddText('* Print a line around the bed to check if it is level')
1048 self.connectButton = self.AddButton('Connect to printer')
1051 self.infoBox = self.AddInfoBox()
1052 self.resumeButton = self.AddButton('Resume')
1053 self.upButton, self.downButton = self.AddDualButton('Up 0.2mm', 'Down 0.2mm')
1054 self.upButton2, self.downButton2 = self.AddDualButton('Up 10mm', 'Down 10mm')
1055 self.resumeButton.Enable(False)
1057 self.upButton.Enable(False)
1058 self.downButton.Enable(False)
1059 self.upButton2.Enable(False)
1060 self.downButton2.Enable(False)
1062 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1063 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1064 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1065 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1066 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1067 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1069 def OnConnect(self, e = None):
1070 if self.comm is not None:
1074 wx.CallAfter(self.OnConnect)
1076 self.connectButton.Enable(False)
1077 self.comm = machineCom.MachineCom(callbackObject=self)
1078 self.infoBox.SetBusy('Connecting to machine.')
1079 self._wizardState = 0
1081 def OnBedUp(self, e):
1082 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1083 self.comm.sendCommand('G92 Z10')
1084 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1085 self.comm.sendCommand('M400')
1087 def OnBedDown(self, e):
1088 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1089 self.comm.sendCommand('G92 Z10')
1090 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1091 self.comm.sendCommand('M400')
1093 def OnBedUp2(self, e):
1094 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1095 self.comm.sendCommand('G92 Z10')
1096 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1097 self.comm.sendCommand('M400')
1099 def OnBedDown2(self, e):
1100 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1101 self.comm.sendCommand('G92 Z10')
1102 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1103 self.comm.sendCommand('M400')
1105 def AllowNext(self):
1106 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1107 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1110 def OnResume(self, e):
1111 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1112 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1113 if self._wizardState == -1:
1114 wx.CallAfter(self.infoBox.SetInfo, 'Homing printer...')
1115 wx.CallAfter(self.upButton.Enable, False)
1116 wx.CallAfter(self.downButton.Enable, False)
1117 wx.CallAfter(self.upButton2.Enable, False)
1118 wx.CallAfter(self.downButton2.Enable, False)
1119 self.comm.sendCommand('M105')
1120 self.comm.sendCommand('G28')
1121 self._wizardState = 1
1122 elif self._wizardState == 2:
1123 if profile.getMachineSetting('has_heated_bed') == 'True':
1124 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back center...')
1125 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1126 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1127 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1128 self.comm.sendCommand('M400')
1129 self._wizardState = 3
1131 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back left corner...')
1132 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1133 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1134 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1135 self.comm.sendCommand('M400')
1136 self._wizardState = 3
1137 elif self._wizardState == 4:
1138 if profile.getMachineSetting('has_heated_bed') == 'True':
1139 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to front right corner...')
1140 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1141 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1142 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1143 self.comm.sendCommand('M400')
1144 self._wizardState = 7
1146 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back right corner...')
1147 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1148 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1149 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1150 self.comm.sendCommand('M400')
1151 self._wizardState = 5
1152 elif self._wizardState == 6:
1153 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to front right corner...')
1154 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1155 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1156 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1157 self.comm.sendCommand('M400')
1158 self._wizardState = 7
1159 elif self._wizardState == 8:
1160 wx.CallAfter(self.infoBox.SetBusy, 'Heating up printer...')
1161 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1162 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1163 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1164 self._wizardState = 9
1165 elif self._wizardState == 10:
1166 self._wizardState = 11
1167 wx.CallAfter(self.infoBox.SetInfo, 'Printing a square on the printer bed at 0.3mm height.')
1168 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1169 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1170 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1171 w = profile.getMachineSettingFloat('machine_width') - 10
1172 d = profile.getMachineSettingFloat('machine_depth')
1173 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1174 filamentArea = math.pi * filamentRadius * filamentRadius
1175 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1179 'G1 Z2 F%d' % (feedZ),
1181 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1182 'G1 Z0.3 F%d' % (feedZ)]
1184 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1186 for i in xrange(0, 3):
1187 dist = 5.0 + 0.4 * float(i)
1188 eValue += (d - 2.0*dist) * ePerMM
1189 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1190 eValue += (w - 2.0*dist) * ePerMM
1191 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1192 eValue += (d - 2.0*dist) * ePerMM
1193 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1194 eValue += (w - 2.0*dist) * ePerMM
1195 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1197 gcodeList.append('M400')
1198 self.comm.printGCode(gcodeList)
1199 self.resumeButton.Enable(False)
1201 def mcLog(self, message):
1202 print 'Log:', message
1204 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1205 if self._wizardState == 1:
1206 self._wizardState = 2
1207 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.')
1208 wx.CallAfter(self.resumeButton.Enable, True)
1209 elif self._wizardState == 3:
1210 self._wizardState = 4
1211 if profile.getMachineSetting('has_heated_bed') == 'True':
1212 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.')
1214 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.')
1215 wx.CallAfter(self.resumeButton.Enable, True)
1216 elif self._wizardState == 5:
1217 self._wizardState = 6
1218 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.')
1219 wx.CallAfter(self.resumeButton.Enable, True)
1220 elif self._wizardState == 7:
1221 self._wizardState = 8
1222 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.')
1223 wx.CallAfter(self.resumeButton.Enable, True)
1224 elif self._wizardState == 9:
1225 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1226 wx.CallAfter(self.infoBox.SetInfo, 'Heating up printer: %d/%d' % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1228 wx.CallAfter(self.infoBox.SetAttention, 'The printer is hot now. Please insert some PLA filament into the printer.')
1229 wx.CallAfter(self.resumeButton.Enable, True)
1230 self._wizardState = 10
1232 def mcStateChange(self, state):
1233 if self.comm is None:
1235 if self.comm.isOperational():
1236 if self._wizardState == 0:
1237 wx.CallAfter(self.infoBox.SetAttention, 'Use the up/down buttons to move the bed and adjust your Z endstop.')
1238 wx.CallAfter(self.upButton.Enable, True)
1239 wx.CallAfter(self.downButton.Enable, True)
1240 wx.CallAfter(self.upButton2.Enable, True)
1241 wx.CallAfter(self.downButton2.Enable, True)
1242 wx.CallAfter(self.resumeButton.Enable, True)
1243 self._wizardState = -1
1244 elif self._wizardState == 11 and not self.comm.isPrinting():
1245 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1246 self.comm.sendCommand('G92 E0')
1247 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1248 self.comm.sendCommand('M104 S0')
1249 wx.CallAfter(self.infoBox.SetInfo, 'Calibration finished.\nThe squares on the bed should slightly touch each other.')
1250 wx.CallAfter(self.infoBox.SetReadyIndicator)
1251 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1252 wx.CallAfter(self.connectButton.Enable, True)
1253 self._wizardState = 12
1254 elif self.comm.isError():
1255 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1257 def mcMessage(self, message):
1260 def mcProgress(self, lineNr):
1263 def mcZChange(self, newZ):
1266 class headOffsetCalibrationPage(InfoPage):
1267 def __init__(self, parent):
1268 super(headOffsetCalibrationPage, self).__init__(parent, "Printer head offset calibration")
1270 self.AddText('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine')
1273 self.connectButton = self.AddButton('Connect to printer')
1276 self.infoBox = self.AddInfoBox()
1277 self.textEntry = self.AddTextCtrl('')
1278 self.textEntry.Enable(False)
1279 self.resumeButton = self.AddButton('Resume')
1280 self.resumeButton.Enable(False)
1282 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1283 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1285 def AllowBack(self):
1288 def OnConnect(self, e = None):
1289 if self.comm is not None:
1293 wx.CallAfter(self.OnConnect)
1295 self.connectButton.Enable(False)
1296 self.comm = machineCom.MachineCom(callbackObject=self)
1297 self.infoBox.SetBusy('Connecting to machine.')
1298 self._wizardState = 0
1300 def OnResume(self, e):
1301 if self._wizardState == 2:
1302 self._wizardState = 3
1303 wx.CallAfter(self.infoBox.SetBusy, 'Printing initial calibration cross')
1305 w = profile.getMachineSettingFloat('machine_width')
1306 d = profile.getMachineSettingFloat('machine_depth')
1308 gcode = gcodeGenerator.gcodeGenerator()
1309 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1310 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1317 gcode.addMove(w/2, 5)
1318 gcode.addMove(z=0.2)
1320 gcode.addExtrude(w/2, d-5.0)
1322 gcode.addMove(5, d/2)
1324 gcode.addExtrude(w-5.0, d/2)
1325 gcode.addRetract(15)
1328 gcode.addMove(w/2, 5)
1330 gcode.addExtrude(w/2, d-5.0)
1332 gcode.addMove(5, d/2)
1334 gcode.addExtrude(w-5.0, d/2)
1335 gcode.addRetract(15)
1340 gcode.addCmd('M400')
1342 self.comm.printGCode(gcode.list())
1343 self.resumeButton.Enable(False)
1344 elif self._wizardState == 4:
1346 float(self.textEntry.GetValue())
1349 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1350 self._wizardState = 5
1351 self.infoBox.SetAttention('Please measure the distance between the horizontal lines in millimeters.')
1352 self.textEntry.SetValue('0.0')
1353 self.textEntry.Enable(True)
1354 elif self._wizardState == 5:
1356 float(self.textEntry.GetValue())
1359 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1360 self._wizardState = 6
1361 self.infoBox.SetBusy('Printing the fine calibration lines.')
1362 self.textEntry.SetValue('')
1363 self.textEntry.Enable(False)
1364 self.resumeButton.Enable(False)
1366 x = profile.getMachineSettingFloat('extruder_offset_x1')
1367 y = profile.getMachineSettingFloat('extruder_offset_y1')
1368 gcode = gcodeGenerator.gcodeGenerator()
1369 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1370 gcode.setPrintSpeed(25)
1373 gcode.addMove(50, 40, 0.2)
1375 for n in xrange(0, 10):
1376 gcode.addExtrude(50 + n * 10, 150)
1377 gcode.addExtrude(50 + n * 10 + 5, 150)
1378 gcode.addExtrude(50 + n * 10 + 5, 40)
1379 gcode.addExtrude(50 + n * 10 + 10, 40)
1380 gcode.addMove(40, 50)
1381 for n in xrange(0, 10):
1382 gcode.addExtrude(150, 50 + n * 10)
1383 gcode.addExtrude(150, 50 + n * 10 + 5)
1384 gcode.addExtrude(40, 50 + n * 10 + 5)
1385 gcode.addExtrude(40, 50 + n * 10 + 10)
1386 gcode.addRetract(15)
1389 gcode.addMove(50 - x, 30 - y, 0.2)
1391 for n in xrange(0, 10):
1392 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1393 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1394 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1395 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1396 gcode.addMove(30 - x, 50 - y, 0.2)
1397 for n in xrange(0, 10):
1398 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1399 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1400 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1401 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1402 gcode.addRetract(15)
1404 gcode.addCmd('M400')
1405 gcode.addCmd('M104 T0 S0')
1406 gcode.addCmd('M104 T1 S0')
1407 self.comm.printGCode(gcode.list())
1408 elif self._wizardState == 7:
1410 n = int(self.textEntry.GetValue()) - 1
1413 x = profile.getMachineSettingFloat('extruder_offset_x1')
1415 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1416 self.infoBox.SetAttention('Which horizontal line number lays perfect on top of each other? Front most line is zero.')
1417 self.textEntry.SetValue('10')
1418 self._wizardState = 8
1419 elif self._wizardState == 8:
1421 n = int(self.textEntry.GetValue()) - 1
1424 y = profile.getMachineSettingFloat('extruder_offset_y1')
1426 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1427 self.infoBox.SetInfo('Calibration finished. Offsets are: %s %s' % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1428 self.infoBox.SetReadyIndicator()
1429 self._wizardState = 8
1431 self.resumeButton.Enable(False)
1433 def mcLog(self, message):
1434 print 'Log:', message
1436 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1437 if self._wizardState == 1:
1438 if temp[0] >= 210 and temp[1] >= 210:
1439 self._wizardState = 2
1440 wx.CallAfter(self.infoBox.SetAttention, 'Please load both extruders with PLA.')
1441 wx.CallAfter(self.resumeButton.Enable, True)
1442 wx.CallAfter(self.resumeButton.SetFocus)
1444 def mcStateChange(self, state):
1445 if self.comm is None:
1447 if self.comm.isOperational():
1448 if self._wizardState == 0:
1449 wx.CallAfter(self.infoBox.SetInfo, 'Homing printer and heating up both extruders.')
1450 self.comm.sendCommand('M105')
1451 self.comm.sendCommand('M104 S220 T0')
1452 self.comm.sendCommand('M104 S220 T1')
1453 self.comm.sendCommand('G28')
1454 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1455 self._wizardState = 1
1456 if not self.comm.isPrinting():
1457 if self._wizardState == 3:
1458 self._wizardState = 4
1459 wx.CallAfter(self.infoBox.SetAttention, 'Please measure the distance between the vertical lines in millimeters.')
1460 wx.CallAfter(self.textEntry.SetValue, '0.0')
1461 wx.CallAfter(self.textEntry.Enable, True)
1462 wx.CallAfter(self.resumeButton.Enable, True)
1463 wx.CallAfter(self.resumeButton.SetFocus)
1464 elif self._wizardState == 6:
1465 self._wizardState = 7
1466 wx.CallAfter(self.infoBox.SetAttention, 'Which vertical line number lays perfect on top of each other? Leftmost line is zero.')
1467 wx.CallAfter(self.textEntry.SetValue, '10')
1468 wx.CallAfter(self.textEntry.Enable, True)
1469 wx.CallAfter(self.resumeButton.Enable, True)
1470 wx.CallAfter(self.resumeButton.SetFocus)
1472 elif self.comm.isError():
1473 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1475 def mcMessage(self, message):
1478 def mcProgress(self, lineNr):
1481 def mcZChange(self, newZ):
1484 class bedLevelWizard(wx.wizard.Wizard):
1486 super(bedLevelWizard, self).__init__(None, -1, "Bed leveling wizard")
1488 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1489 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1491 self.mainPage = bedLevelWizardMain(self)
1492 self.headOffsetCalibration = None
1494 self.FitToPage(self.mainPage)
1495 self.GetPageAreaSizer().Add(self.mainPage)
1497 self.RunWizard(self.mainPage)
1500 def OnPageChanging(self, e):
1501 e.GetPage().StoreData()
1503 def OnPageChanged(self, e):
1504 if e.GetPage().AllowNext():
1505 self.FindWindowById(wx.ID_FORWARD).Enable()
1507 self.FindWindowById(wx.ID_FORWARD).Disable()
1508 if e.GetPage().AllowBack():
1509 self.FindWindowById(wx.ID_BACKWARD).Enable()
1511 self.FindWindowById(wx.ID_BACKWARD).Disable()
1513 class headOffsetWizard(wx.wizard.Wizard):
1515 super(headOffsetWizard, self).__init__(None, -1, "Head offset wizard")
1517 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1518 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1520 self.mainPage = headOffsetCalibrationPage(self)
1522 self.FitToPage(self.mainPage)
1523 self.GetPageAreaSizer().Add(self.mainPage)
1525 self.RunWizard(self.mainPage)
1528 def OnPageChanging(self, e):
1529 e.GetPage().StoreData()
1531 def OnPageChanged(self, e):
1532 if e.GetPage().AllowNext():
1533 self.FindWindowById(wx.ID_FORWARD).Enable()
1535 self.FindWindowById(wx.ID_FORWARD).Disable()
1536 if e.GetPage().AllowBack():
1537 self.FindWindowById(wx.ID_BACKWARD).Enable()
1539 self.FindWindowById(wx.ID_BACKWARD).Disable()