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.LulzbotMiniRadio = self.AddRadioButton("Lulzbot Mini", style=wx.RB_GROUP)
389 self.LulzbotMiniRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
390 self.LulzbotMiniRadio.SetValue(True)
391 self.LulzbotTazRadio = self.AddRadioButton("Lulzbot TAZ")
392 self.LulzbotTazRadio.Bind(wx.EVT_RADIOBUTTON, self.OnLulzbotSelect)
393 self.Ultimaker2Radio = self.AddRadioButton("Ultimaker2")
394 self.Ultimaker2Radio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimaker2Select)
395 self.UltimakerRadio = self.AddRadioButton("Ultimaker Original")
396 self.UltimakerRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerSelect)
397 self.UltimakerOPRadio = self.AddRadioButton("Ultimaker Original+")
398 self.UltimakerOPRadio.Bind(wx.EVT_RADIOBUTTON, self.OnUltimakerOPSelect)
399 self.PrintrbotRadio = self.AddRadioButton("Printrbot")
400 self.PrintrbotRadio.Bind(wx.EVT_RADIOBUTTON, self.OnPrintrbotSelect)
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(False)
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')
490 profile.putMachineSetting('machine_type', 'lulzbot_TAZ')
492 profile.putMachineSetting('machine_width', '158')
493 profile.putMachineSetting('machine_depth', '158')
494 profile.putMachineSetting('machine_height', '155')
495 profile.putProfileSetting('nozzle_size', '0.5')
496 profile.putMachineSetting('machine_name', 'Lulzbot Mini')
497 profile.putMachineSetting('machine_type', 'lulzbot_mini')
498 profile.putMachineSetting('machine_center_is_zero', 'False')
499 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
500 profile.putMachineSetting('has_heated_bed', 'True')
501 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
502 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
503 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
504 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
505 profile.putMachineSetting('extruder_head_size_height', '0.0')
507 profile.putMachineSetting('machine_width', '80')
508 profile.putMachineSetting('machine_depth', '80')
509 profile.putMachineSetting('machine_height', '60')
510 profile.putMachineSetting('machine_name', 'reprap')
511 profile.putMachineSetting('machine_type', 'reprap')
512 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
513 profile.putPreference('startMode', 'Normal')
514 profile.putProfileSetting('nozzle_size', '0.5')
515 profile.checkAndUpdateMachineName()
516 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
517 if self.SubmitUserStats.GetValue():
518 profile.putPreference('submit_slice_information', 'True')
520 profile.putPreference('submit_slice_information', 'False')
523 class SelectParts(InfoPage):
524 def __init__(self, parent):
525 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
526 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."))
528 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
529 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
530 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
531 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
533 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."))
534 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
535 self.springExtruder.SetValue(True)
538 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
539 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
540 profile.putMachineSetting('has_heated_bed', 'True')
542 profile.putMachineSetting('has_heated_bed', 'False')
543 if self.dualExtrusion.GetValue():
544 profile.putMachineSetting('extruder_amount', '2')
545 profile.putMachineSetting('machine_depth', '195')
547 profile.putMachineSetting('extruder_amount', '1')
548 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
549 profile.putProfileSetting('retraction_enable', 'True')
551 profile.putProfileSetting('retraction_enable', 'False')
554 class UltimakerFirmwareUpgradePage(InfoPage):
555 def __init__(self, parent):
556 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
557 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."))
558 self.AddHiddenSeperator()
559 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
560 self.AddHiddenSeperator()
561 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."))
562 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
563 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
564 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
565 self.AddHiddenSeperator()
566 if profile.getMachineSetting('machine_type') == 'ultimaker':
567 self.AddText(_("Do not upgrade to this firmware if:"))
568 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
569 self.AddText(_("* Build your own heated bed"))
570 self.AddText(_("* Have other changes in the firmware"))
571 # button = self.AddButton('Goto this page for a custom firmware')
572 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
577 def OnUpgradeClick(self, e):
578 if firmwareInstall.InstallFirmware():
579 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
581 def OnSkipClick(self, e):
582 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
583 self.GetParent().ShowPage(self.GetNext())
585 def OnUrlClick(self, e):
586 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
588 class UltimakerCheckupPage(InfoPage):
589 def __init__(self, parent):
590 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")
592 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
593 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
594 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
595 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
596 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
597 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
598 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
599 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
600 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
601 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
604 _("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."))
605 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
606 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
607 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
609 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
610 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
611 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
613 self.infoBox = self.AddInfoBox()
614 self.machineState = self.AddText("")
615 self.temperatureLabel = self.AddText("")
616 self.errorLogButton = self.AddButton(_("Show error log"))
617 self.errorLogButton.Show(False)
619 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
621 self.xMinStop = False
622 self.xMaxStop = False
623 self.yMinStop = False
624 self.yMaxStop = False
625 self.zMinStop = False
626 self.zMaxStop = False
628 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
631 if self.comm is not None:
635 self.endstopBitmap.Show(False)
638 def OnSkipClick(self, e):
639 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
640 self.GetParent().ShowPage(self.GetNext())
642 def OnCheckClick(self, e=None):
643 self.errorLogButton.Show(False)
644 if self.comm is not None:
648 wx.CallAfter(self.OnCheckClick)
650 self.infoBox.SetBusy(_("Connecting to machine."))
651 self.commState.SetBitmap(self.unknownBitmap)
652 self.tempState.SetBitmap(self.unknownBitmap)
653 self.stopState.SetBitmap(self.unknownBitmap)
654 self.checkupState = 0
655 self.checkExtruderNr = 0
656 self.comm = machineCom.MachineCom(callbackObject=self)
658 def OnErrorLog(self, e):
659 printWindow.LogWindow('\n'.join(self.comm.getLog()))
661 def mcLog(self, message):
664 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
665 if not self.comm.isOperational():
667 if self.checkupState == 0:
668 self.tempCheckTimeout = 20
669 if temp[self.checkExtruderNr] > 70:
670 self.checkupState = 1
671 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
672 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
673 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
675 self.startTemp = temp[self.checkExtruderNr]
676 self.checkupState = 2
677 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
678 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
679 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
680 elif self.checkupState == 1:
681 if temp[self.checkExtruderNr] < 60:
682 self.startTemp = temp[self.checkExtruderNr]
683 self.checkupState = 2
684 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
685 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
686 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
687 elif self.checkupState == 2:
688 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
689 if temp[self.checkExtruderNr] > self.startTemp + 40:
690 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
691 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
692 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
693 self.checkExtruderNr = 0
694 self.checkupState = 3
695 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
696 wx.CallAfter(self.endstopBitmap.Show, True)
697 wx.CallAfter(self.Layout)
698 self.comm.sendCommand('M119')
699 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
701 self.checkupState = 0
702 self.checkExtruderNr += 1
704 self.tempCheckTimeout -= 1
705 if self.tempCheckTimeout < 1:
706 self.checkupState = -1
707 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
708 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
709 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
710 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
711 elif self.checkupState >= 3 and self.checkupState < 10:
712 self.comm.sendCommand('M119')
713 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
715 def mcStateChange(self, state):
716 if self.comm is None:
718 if self.comm.isOperational():
719 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
720 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
721 elif self.comm.isError():
722 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
723 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
724 wx.CallAfter(self.endstopBitmap.Show, False)
725 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
726 wx.CallAfter(self.errorLogButton.Show, True)
727 wx.CallAfter(self.Layout)
729 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
731 def mcMessage(self, message):
732 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
733 for data in message.split(' '):
735 tag, value = data.split(':', 1)
737 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
739 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
741 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
743 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
745 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
747 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
749 tag, value = map(str.strip, message.split(':', 1))
751 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
753 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
755 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
757 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
759 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
761 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
762 if 'z_max' in message:
763 self.comm.sendCommand('M119')
765 if self.checkupState == 3:
766 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
767 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
768 self.checkupState = 5
769 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
770 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
772 self.checkupState = 4
773 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
774 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
775 elif self.checkupState == 4:
776 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
777 self.checkupState = 5
778 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
779 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
780 elif self.checkupState == 5:
781 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
782 self.checkupState = 6
783 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
784 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
785 elif self.checkupState == 6:
786 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
787 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
788 self.checkupState = 8
789 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
790 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
792 self.checkupState = 7
793 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
794 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
795 elif self.checkupState == 7:
796 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
797 self.checkupState = 8
798 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
799 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
800 elif self.checkupState == 8:
801 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
802 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
803 self.checkupState = 10
805 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
806 wx.CallAfter(self.infoBox.SetReadyIndicator)
807 wx.CallAfter(self.endstopBitmap.Show, False)
808 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
809 wx.CallAfter(self.OnSkipClick, None)
811 self.checkupState = 9
812 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
813 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
814 elif self.checkupState == 9:
815 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
816 self.checkupState = 10
818 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
819 wx.CallAfter(self.infoBox.SetReadyIndicator)
820 wx.CallAfter(self.endstopBitmap.Show, False)
821 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
822 wx.CallAfter(self.OnSkipClick, None)
824 def mcProgress(self, lineNr):
827 def mcZChange(self, newZ):
831 class UltimakerCalibrationPage(InfoPage):
832 def __init__(self, parent):
833 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")
835 self.AddText("Your Ultimaker requires some calibration.")
836 self.AddText("This calibration is needed for a proper extrusion amount.")
838 self.AddText("The following values are needed:")
839 self.AddText("* Diameter of filament")
840 self.AddText("* Number of steps per mm of filament extrusion")
842 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
844 self.AddText("First we need the diameter of your filament:")
845 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
847 "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.")
848 self.AddText("Note: This value can be changed later at any time.")
851 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
854 class UltimakerCalibrateStepsPerEPage(InfoPage):
855 def __init__(self, parent):
856 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")
858 #if profile.getMachineSetting('steps_per_e') == '0':
859 # profile.putMachineSetting('steps_per_e', '865.888')
861 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
862 self.AddText(_("First remove any filament from your machine."))
863 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
864 self.AddText(_("We'll push the filament 100mm"))
865 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
866 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
867 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
868 self.AddText(_("This results in the following steps per E:"))
869 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
870 self.AddText(_("You can repeat these steps to get better calibration."))
873 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
874 self.heatButton = self.AddButton(_("Heatup for filament removal"))
876 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
877 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
878 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
880 def OnSaveLengthClick(self, e):
881 currentEValue = float(self.stepsPerEInput.GetValue())
882 realExtrudeLength = float(self.lengthInput.GetValue())
883 newEValue = currentEValue * 100 / realExtrudeLength
884 self.stepsPerEInput.SetValue(str(newEValue))
885 self.lengthInput.SetValue("100")
887 def OnExtrudeClick(self, e):
888 t = threading.Thread(target=self.OnExtrudeRun)
892 def OnExtrudeRun(self):
893 self.heatButton.Enable(False)
894 self.extrudeButton.Enable(False)
895 currentEValue = float(self.stepsPerEInput.GetValue())
896 self.comm = machineCom.MachineCom()
897 if not self.comm.isOpen():
899 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
900 'Printer error', wx.OK | wx.ICON_INFORMATION)
901 self.heatButton.Enable(True)
902 self.extrudeButton.Enable(True)
905 line = self.comm.readline()
910 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
913 self.sendGCommand('M302') #Disable cold extrusion protection
914 self.sendGCommand("M92 E%f" % (currentEValue))
915 self.sendGCommand("G92 E0")
916 self.sendGCommand("G1 E100 F600")
919 self.extrudeButton.Enable()
920 self.heatButton.Enable()
922 def OnHeatClick(self, e):
923 t = threading.Thread(target=self.OnHeatRun)
928 self.heatButton.Enable(False)
929 self.extrudeButton.Enable(False)
930 self.comm = machineCom.MachineCom()
931 if not self.comm.isOpen():
933 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
934 'Printer error', wx.OK | wx.ICON_INFORMATION)
935 self.heatButton.Enable(True)
936 self.extrudeButton.Enable(True)
939 line = self.comm.readline()
941 self.heatButton.Enable(True)
942 self.extrudeButton.Enable(True)
946 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
949 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
951 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
952 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
953 self.sendGCommand('M104 S0')
956 self.heatButton.Enable(True)
957 self.extrudeButton.Enable(True)
959 def sendGCommand(self, cmd):
960 self.comm.sendCommand(cmd) #Disable cold extrusion protection
962 line = self.comm.readline()
965 if line.startswith('ok'):
969 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
971 class Ultimaker2ReadyPage(InfoPage):
972 def __init__(self, parent):
973 super(Ultimaker2ReadyPage, self).__init__(parent, "Ultimaker2")
974 self.AddText('Congratulations on your the purchase of your brand new Ultimaker2.')
975 self.AddText('Cura is now ready to be used with your Ultimaker2.')
978 class LulzbotReadyPage(InfoPage):
979 def __init__(self, parent):
980 super(LulzbotReadyPage, self).__init__(parent, "Lulzbot TAZ/Mini")
981 self.AddText('Cura is now ready to be used with your Lulzbot.')
984 class configWizard(wx.wizard.Wizard):
985 def __init__(self, addNew = False):
986 super(configWizard, self).__init__(None, -1, "Configuration Wizard")
988 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
989 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
991 self.firstInfoPage = FirstInfoPage(self, addNew)
992 self.machineSelectPage = MachineSelectPage(self)
993 self.ultimakerSelectParts = SelectParts(self)
994 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
995 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
996 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
997 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
998 self.bedLevelPage = bedLevelWizardMain(self)
999 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1000 self.printrbotSelectType = PrintrbotPage(self)
1001 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1002 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1003 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1005 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1006 self.lulzbotReadyPage = LulzbotReadyPage(self)
1008 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
1009 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
1010 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1011 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1012 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1013 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1014 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
1015 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1016 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1018 self.FitToPage(self.firstInfoPage)
1019 self.GetPageAreaSizer().Add(self.firstInfoPage)
1021 self.RunWizard(self.firstInfoPage)
1024 def OnPageChanging(self, e):
1025 e.GetPage().StoreData()
1027 def OnPageChanged(self, e):
1028 if e.GetPage().AllowNext():
1029 self.FindWindowById(wx.ID_FORWARD).Enable()
1031 self.FindWindowById(wx.ID_FORWARD).Disable()
1032 if e.GetPage().AllowBack():
1033 self.FindWindowById(wx.ID_BACKWARD).Enable()
1035 self.FindWindowById(wx.ID_BACKWARD).Disable()
1037 class bedLevelWizardMain(InfoPage):
1038 def __init__(self, parent):
1039 super(bedLevelWizardMain, self).__init__(parent, "Bed leveling wizard")
1041 self.AddText('This wizard will help you in leveling your printer bed')
1043 self.AddText('It will do the following steps')
1044 self.AddText('* Move the printer head to each corner')
1045 self.AddText(' and let you adjust the height of the bed to the nozzle')
1046 self.AddText('* Print a line around the bed to check if it is level')
1049 self.connectButton = self.AddButton('Connect to printer')
1052 self.infoBox = self.AddInfoBox()
1053 self.resumeButton = self.AddButton('Resume')
1054 self.upButton, self.downButton = self.AddDualButton('Up 0.2mm', 'Down 0.2mm')
1055 self.upButton2, self.downButton2 = self.AddDualButton('Up 10mm', 'Down 10mm')
1056 self.resumeButton.Enable(False)
1058 self.upButton.Enable(False)
1059 self.downButton.Enable(False)
1060 self.upButton2.Enable(False)
1061 self.downButton2.Enable(False)
1063 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1064 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1065 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1066 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1067 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1068 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1070 def OnConnect(self, e = None):
1071 if self.comm is not None:
1075 wx.CallAfter(self.OnConnect)
1077 self.connectButton.Enable(False)
1078 self.comm = machineCom.MachineCom(callbackObject=self)
1079 self.infoBox.SetBusy('Connecting to machine.')
1080 self._wizardState = 0
1082 def OnBedUp(self, e):
1083 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1084 self.comm.sendCommand('G92 Z10')
1085 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1086 self.comm.sendCommand('M400')
1088 def OnBedDown(self, e):
1089 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1090 self.comm.sendCommand('G92 Z10')
1091 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1092 self.comm.sendCommand('M400')
1094 def OnBedUp2(self, e):
1095 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1096 self.comm.sendCommand('G92 Z10')
1097 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1098 self.comm.sendCommand('M400')
1100 def OnBedDown2(self, e):
1101 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1102 self.comm.sendCommand('G92 Z10')
1103 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1104 self.comm.sendCommand('M400')
1106 def AllowNext(self):
1107 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1108 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1111 def OnResume(self, e):
1112 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1113 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1114 if self._wizardState == -1:
1115 wx.CallAfter(self.infoBox.SetInfo, 'Homing printer...')
1116 wx.CallAfter(self.upButton.Enable, False)
1117 wx.CallAfter(self.downButton.Enable, False)
1118 wx.CallAfter(self.upButton2.Enable, False)
1119 wx.CallAfter(self.downButton2.Enable, False)
1120 self.comm.sendCommand('M105')
1121 self.comm.sendCommand('G28')
1122 self._wizardState = 1
1123 elif self._wizardState == 2:
1124 if profile.getMachineSetting('has_heated_bed') == 'True':
1125 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back center...')
1126 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1127 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1128 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1129 self.comm.sendCommand('M400')
1130 self._wizardState = 3
1132 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back left corner...')
1133 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1134 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1135 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1136 self.comm.sendCommand('M400')
1137 self._wizardState = 3
1138 elif self._wizardState == 4:
1139 if profile.getMachineSetting('has_heated_bed') == 'True':
1140 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to front right corner...')
1141 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1142 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1143 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1144 self.comm.sendCommand('M400')
1145 self._wizardState = 7
1147 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back right corner...')
1148 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1149 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1150 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1151 self.comm.sendCommand('M400')
1152 self._wizardState = 5
1153 elif self._wizardState == 6:
1154 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to front right corner...')
1155 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1156 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1157 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1158 self.comm.sendCommand('M400')
1159 self._wizardState = 7
1160 elif self._wizardState == 8:
1161 wx.CallAfter(self.infoBox.SetBusy, 'Heating up printer...')
1162 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1163 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1164 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1165 self._wizardState = 9
1166 elif self._wizardState == 10:
1167 self._wizardState = 11
1168 wx.CallAfter(self.infoBox.SetInfo, 'Printing a square on the printer bed at 0.3mm height.')
1169 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1170 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1171 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1172 w = profile.getMachineSettingFloat('machine_width') - 10
1173 d = profile.getMachineSettingFloat('machine_depth')
1174 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1175 filamentArea = math.pi * filamentRadius * filamentRadius
1176 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1180 'G1 Z2 F%d' % (feedZ),
1182 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1183 'G1 Z0.3 F%d' % (feedZ)]
1185 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1187 for i in xrange(0, 3):
1188 dist = 5.0 + 0.4 * float(i)
1189 eValue += (d - 2.0*dist) * ePerMM
1190 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1191 eValue += (w - 2.0*dist) * ePerMM
1192 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1193 eValue += (d - 2.0*dist) * ePerMM
1194 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1195 eValue += (w - 2.0*dist) * ePerMM
1196 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1198 gcodeList.append('M400')
1199 self.comm.printGCode(gcodeList)
1200 self.resumeButton.Enable(False)
1202 def mcLog(self, message):
1203 print 'Log:', message
1205 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1206 if self._wizardState == 1:
1207 self._wizardState = 2
1208 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.')
1209 wx.CallAfter(self.resumeButton.Enable, True)
1210 elif self._wizardState == 3:
1211 self._wizardState = 4
1212 if profile.getMachineSetting('has_heated_bed') == 'True':
1213 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.')
1215 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.')
1216 wx.CallAfter(self.resumeButton.Enable, True)
1217 elif self._wizardState == 5:
1218 self._wizardState = 6
1219 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.')
1220 wx.CallAfter(self.resumeButton.Enable, True)
1221 elif self._wizardState == 7:
1222 self._wizardState = 8
1223 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.')
1224 wx.CallAfter(self.resumeButton.Enable, True)
1225 elif self._wizardState == 9:
1226 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1227 wx.CallAfter(self.infoBox.SetInfo, 'Heating up printer: %d/%d' % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1229 wx.CallAfter(self.infoBox.SetAttention, 'The printer is hot now. Please insert some PLA filament into the printer.')
1230 wx.CallAfter(self.resumeButton.Enable, True)
1231 self._wizardState = 10
1233 def mcStateChange(self, state):
1234 if self.comm is None:
1236 if self.comm.isOperational():
1237 if self._wizardState == 0:
1238 wx.CallAfter(self.infoBox.SetAttention, 'Use the up/down buttons to move the bed and adjust your Z endstop.')
1239 wx.CallAfter(self.upButton.Enable, True)
1240 wx.CallAfter(self.downButton.Enable, True)
1241 wx.CallAfter(self.upButton2.Enable, True)
1242 wx.CallAfter(self.downButton2.Enable, True)
1243 wx.CallAfter(self.resumeButton.Enable, True)
1244 self._wizardState = -1
1245 elif self._wizardState == 11 and not self.comm.isPrinting():
1246 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1247 self.comm.sendCommand('G92 E0')
1248 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1249 self.comm.sendCommand('M104 S0')
1250 wx.CallAfter(self.infoBox.SetInfo, 'Calibration finished.\nThe squares on the bed should slightly touch each other.')
1251 wx.CallAfter(self.infoBox.SetReadyIndicator)
1252 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1253 wx.CallAfter(self.connectButton.Enable, True)
1254 self._wizardState = 12
1255 elif self.comm.isError():
1256 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1258 def mcMessage(self, message):
1261 def mcProgress(self, lineNr):
1264 def mcZChange(self, newZ):
1267 class headOffsetCalibrationPage(InfoPage):
1268 def __init__(self, parent):
1269 super(headOffsetCalibrationPage, self).__init__(parent, "Printer head offset calibration")
1271 self.AddText('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine')
1274 self.connectButton = self.AddButton('Connect to printer')
1277 self.infoBox = self.AddInfoBox()
1278 self.textEntry = self.AddTextCtrl('')
1279 self.textEntry.Enable(False)
1280 self.resumeButton = self.AddButton('Resume')
1281 self.resumeButton.Enable(False)
1283 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1284 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1286 def AllowBack(self):
1289 def OnConnect(self, e = None):
1290 if self.comm is not None:
1294 wx.CallAfter(self.OnConnect)
1296 self.connectButton.Enable(False)
1297 self.comm = machineCom.MachineCom(callbackObject=self)
1298 self.infoBox.SetBusy('Connecting to machine.')
1299 self._wizardState = 0
1301 def OnResume(self, e):
1302 if self._wizardState == 2:
1303 self._wizardState = 3
1304 wx.CallAfter(self.infoBox.SetBusy, 'Printing initial calibration cross')
1306 w = profile.getMachineSettingFloat('machine_width')
1307 d = profile.getMachineSettingFloat('machine_depth')
1309 gcode = gcodeGenerator.gcodeGenerator()
1310 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1311 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1318 gcode.addMove(w/2, 5)
1319 gcode.addMove(z=0.2)
1321 gcode.addExtrude(w/2, d-5.0)
1323 gcode.addMove(5, d/2)
1325 gcode.addExtrude(w-5.0, d/2)
1326 gcode.addRetract(15)
1329 gcode.addMove(w/2, 5)
1331 gcode.addExtrude(w/2, d-5.0)
1333 gcode.addMove(5, d/2)
1335 gcode.addExtrude(w-5.0, d/2)
1336 gcode.addRetract(15)
1341 gcode.addCmd('M400')
1343 self.comm.printGCode(gcode.list())
1344 self.resumeButton.Enable(False)
1345 elif self._wizardState == 4:
1347 float(self.textEntry.GetValue())
1350 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1351 self._wizardState = 5
1352 self.infoBox.SetAttention('Please measure the distance between the horizontal lines in millimeters.')
1353 self.textEntry.SetValue('0.0')
1354 self.textEntry.Enable(True)
1355 elif self._wizardState == 5:
1357 float(self.textEntry.GetValue())
1360 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1361 self._wizardState = 6
1362 self.infoBox.SetBusy('Printing the fine calibration lines.')
1363 self.textEntry.SetValue('')
1364 self.textEntry.Enable(False)
1365 self.resumeButton.Enable(False)
1367 x = profile.getMachineSettingFloat('extruder_offset_x1')
1368 y = profile.getMachineSettingFloat('extruder_offset_y1')
1369 gcode = gcodeGenerator.gcodeGenerator()
1370 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1371 gcode.setPrintSpeed(25)
1374 gcode.addMove(50, 40, 0.2)
1376 for n in xrange(0, 10):
1377 gcode.addExtrude(50 + n * 10, 150)
1378 gcode.addExtrude(50 + n * 10 + 5, 150)
1379 gcode.addExtrude(50 + n * 10 + 5, 40)
1380 gcode.addExtrude(50 + n * 10 + 10, 40)
1381 gcode.addMove(40, 50)
1382 for n in xrange(0, 10):
1383 gcode.addExtrude(150, 50 + n * 10)
1384 gcode.addExtrude(150, 50 + n * 10 + 5)
1385 gcode.addExtrude(40, 50 + n * 10 + 5)
1386 gcode.addExtrude(40, 50 + n * 10 + 10)
1387 gcode.addRetract(15)
1390 gcode.addMove(50 - x, 30 - y, 0.2)
1392 for n in xrange(0, 10):
1393 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1394 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1395 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1396 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1397 gcode.addMove(30 - x, 50 - y, 0.2)
1398 for n in xrange(0, 10):
1399 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1400 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1401 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1402 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1403 gcode.addRetract(15)
1405 gcode.addCmd('M400')
1406 gcode.addCmd('M104 T0 S0')
1407 gcode.addCmd('M104 T1 S0')
1408 self.comm.printGCode(gcode.list())
1409 elif self._wizardState == 7:
1411 n = int(self.textEntry.GetValue()) - 1
1414 x = profile.getMachineSettingFloat('extruder_offset_x1')
1416 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1417 self.infoBox.SetAttention('Which horizontal line number lays perfect on top of each other? Front most line is zero.')
1418 self.textEntry.SetValue('10')
1419 self._wizardState = 8
1420 elif self._wizardState == 8:
1422 n = int(self.textEntry.GetValue()) - 1
1425 y = profile.getMachineSettingFloat('extruder_offset_y1')
1427 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1428 self.infoBox.SetInfo('Calibration finished. Offsets are: %s %s' % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1429 self.infoBox.SetReadyIndicator()
1430 self._wizardState = 8
1432 self.resumeButton.Enable(False)
1434 def mcLog(self, message):
1435 print 'Log:', message
1437 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1438 if self._wizardState == 1:
1439 if temp[0] >= 210 and temp[1] >= 210:
1440 self._wizardState = 2
1441 wx.CallAfter(self.infoBox.SetAttention, 'Please load both extruders with PLA.')
1442 wx.CallAfter(self.resumeButton.Enable, True)
1443 wx.CallAfter(self.resumeButton.SetFocus)
1445 def mcStateChange(self, state):
1446 if self.comm is None:
1448 if self.comm.isOperational():
1449 if self._wizardState == 0:
1450 wx.CallAfter(self.infoBox.SetInfo, 'Homing printer and heating up both extruders.')
1451 self.comm.sendCommand('M105')
1452 self.comm.sendCommand('M104 S220 T0')
1453 self.comm.sendCommand('M104 S220 T1')
1454 self.comm.sendCommand('G28')
1455 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1456 self._wizardState = 1
1457 if not self.comm.isPrinting():
1458 if self._wizardState == 3:
1459 self._wizardState = 4
1460 wx.CallAfter(self.infoBox.SetAttention, 'Please measure the distance between the vertical lines in millimeters.')
1461 wx.CallAfter(self.textEntry.SetValue, '0.0')
1462 wx.CallAfter(self.textEntry.Enable, True)
1463 wx.CallAfter(self.resumeButton.Enable, True)
1464 wx.CallAfter(self.resumeButton.SetFocus)
1465 elif self._wizardState == 6:
1466 self._wizardState = 7
1467 wx.CallAfter(self.infoBox.SetAttention, 'Which vertical line number lays perfect on top of each other? Leftmost line is zero.')
1468 wx.CallAfter(self.textEntry.SetValue, '10')
1469 wx.CallAfter(self.textEntry.Enable, True)
1470 wx.CallAfter(self.resumeButton.Enable, True)
1471 wx.CallAfter(self.resumeButton.SetFocus)
1473 elif self.comm.isError():
1474 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1476 def mcMessage(self, message):
1479 def mcProgress(self, lineNr):
1482 def mcZChange(self, newZ):
1485 class bedLevelWizard(wx.wizard.Wizard):
1487 super(bedLevelWizard, self).__init__(None, -1, "Bed leveling wizard")
1489 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1490 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1492 self.mainPage = bedLevelWizardMain(self)
1493 self.headOffsetCalibration = None
1495 self.FitToPage(self.mainPage)
1496 self.GetPageAreaSizer().Add(self.mainPage)
1498 self.RunWizard(self.mainPage)
1501 def OnPageChanging(self, e):
1502 e.GetPage().StoreData()
1504 def OnPageChanged(self, e):
1505 if e.GetPage().AllowNext():
1506 self.FindWindowById(wx.ID_FORWARD).Enable()
1508 self.FindWindowById(wx.ID_FORWARD).Disable()
1509 if e.GetPage().AllowBack():
1510 self.FindWindowById(wx.ID_BACKWARD).Enable()
1512 self.FindWindowById(wx.ID_BACKWARD).Disable()
1514 class headOffsetWizard(wx.wizard.Wizard):
1516 super(headOffsetWizard, self).__init__(None, -1, "Head offset wizard")
1518 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1519 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1521 self.mainPage = headOffsetCalibrationPage(self)
1523 self.FitToPage(self.mainPage)
1524 self.GetPageAreaSizer().Add(self.mainPage)
1526 self.RunWizard(self.mainPage)
1529 def OnPageChanging(self, e):
1530 e.GetPage().StoreData()
1532 def OnPageChanged(self, e):
1533 if e.GetPage().AllowNext():
1534 self.FindWindowById(wx.ID_FORWARD).Enable()
1536 self.FindWindowById(wx.ID_FORWARD).Disable()
1537 if e.GetPage().AllowBack():
1538 self.FindWindowById(wx.ID_BACKWARD).Enable()
1540 self.FindWindowById(wx.ID_BACKWARD).Disable()