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')
491 profile.putMachineSetting('serial_baud', '115200')
493 profile.putMachineSetting('machine_width', '158')
494 profile.putMachineSetting('machine_depth', '158')
495 profile.putMachineSetting('machine_height', '155')
496 profile.putProfileSetting('nozzle_size', '0.5')
497 profile.putMachineSetting('machine_name', 'Lulzbot Mini')
498 profile.putMachineSetting('machine_type', 'lulzbot_mini')
499 profile.putMachineSetting('serial_baud', '115200')
500 profile.putMachineSetting('machine_center_is_zero', 'False')
501 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
502 profile.putMachineSetting('has_heated_bed', 'True')
503 profile.putMachineSetting('extruder_head_size_min_x', '0.0')
504 profile.putMachineSetting('extruder_head_size_min_y', '0.0')
505 profile.putMachineSetting('extruder_head_size_max_x', '0.0')
506 profile.putMachineSetting('extruder_head_size_max_y', '0.0')
507 profile.putMachineSetting('extruder_head_size_height', '0.0')
509 profile.putMachineSetting('machine_width', '80')
510 profile.putMachineSetting('machine_depth', '80')
511 profile.putMachineSetting('machine_height', '60')
512 profile.putMachineSetting('machine_name', 'reprap')
513 profile.putMachineSetting('machine_type', 'reprap')
514 profile.putMachineSetting('gcode_flavor', 'RepRap (Marlin/Sprinter)')
515 profile.putPreference('startMode', 'Normal')
516 profile.putProfileSetting('nozzle_size', '0.5')
517 profile.checkAndUpdateMachineName()
518 profile.putProfileSetting('wall_thickness', float(profile.getProfileSetting('nozzle_size')) * 2)
519 #if self.SubmitUserStats.GetValue():
520 # profile.putPreference('submit_slice_information', 'True')
522 # profile.putPreference('submit_slice_information', 'False')
525 class SelectParts(InfoPage):
526 def __init__(self, parent):
527 super(SelectParts, self).__init__(parent, _("Select upgraded parts you have"))
528 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."))
530 self.springExtruder = self.AddCheckbox(_("Extruder drive upgrade"))
531 self.heatedBedKit = self.AddCheckbox(_("Heated printer bed (kit)"))
532 self.heatedBed = self.AddCheckbox(_("Heated printer bed (self built)"))
533 self.dualExtrusion = self.AddCheckbox(_("Dual extrusion (experimental)"))
535 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."))
536 self.AddText(_("This upgrade can be bought from the Ultimaker webshop\nor found on thingiverse as thing:26094"))
537 self.springExtruder.SetValue(True)
540 profile.putMachineSetting('ultimaker_extruder_upgrade', str(self.springExtruder.GetValue()))
541 if self.heatedBed.GetValue() or self.heatedBedKit.GetValue():
542 profile.putMachineSetting('has_heated_bed', 'True')
544 profile.putMachineSetting('has_heated_bed', 'False')
545 if self.dualExtrusion.GetValue():
546 profile.putMachineSetting('extruder_amount', '2')
547 profile.putMachineSetting('machine_depth', '195')
549 profile.putMachineSetting('extruder_amount', '1')
550 if profile.getMachineSetting('ultimaker_extruder_upgrade') == 'True':
551 profile.putProfileSetting('retraction_enable', 'True')
553 profile.putProfileSetting('retraction_enable', 'False')
556 class UltimakerFirmwareUpgradePage(InfoPage):
557 def __init__(self, parent):
558 super(UltimakerFirmwareUpgradePage, self).__init__(parent, _("Upgrade Ultimaker Firmware"))
559 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."))
560 self.AddHiddenSeperator()
561 self.AddText(_("The firmware shipping with new Ultimakers works, but upgrades\nhave been made to make better prints, and make calibration easier."))
562 self.AddHiddenSeperator()
563 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."))
564 upgradeButton, skipUpgradeButton = self.AddDualButton('Upgrade to Marlin firmware', 'Skip upgrade')
565 upgradeButton.Bind(wx.EVT_BUTTON, self.OnUpgradeClick)
566 skipUpgradeButton.Bind(wx.EVT_BUTTON, self.OnSkipClick)
567 self.AddHiddenSeperator()
568 if profile.getMachineSetting('machine_type') == 'ultimaker':
569 self.AddText(_("Do not upgrade to this firmware if:"))
570 self.AddText(_("* You have an older machine based on ATMega1280 (Rev 1 machine)"))
571 self.AddText(_("* Build your own heated bed"))
572 self.AddText(_("* Have other changes in the firmware"))
573 # button = self.AddButton('Goto this page for a custom firmware')
574 # button.Bind(wx.EVT_BUTTON, self.OnUrlClick)
579 def OnUpgradeClick(self, e):
580 if firmwareInstall.InstallFirmware():
581 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
583 def OnSkipClick(self, e):
584 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
585 self.GetParent().ShowPage(self.GetNext())
587 def OnUrlClick(self, e):
588 webbrowser.open('http://marlinbuilder.robotfuzz.com/')
590 class UltimakerCheckupPage(InfoPage):
591 def __init__(self, parent):
592 super(UltimakerCheckupPage, self).__init__(parent, "Ultimaker Checkup")
594 self.checkBitmap = wx.Bitmap(resources.getPathForImage('checkmark.png'))
595 self.crossBitmap = wx.Bitmap(resources.getPathForImage('cross.png'))
596 self.unknownBitmap = wx.Bitmap(resources.getPathForImage('question.png'))
597 self.endStopNoneBitmap = wx.Bitmap(resources.getPathForImage('endstop_none.png'))
598 self.endStopXMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmin.png'))
599 self.endStopXMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_xmax.png'))
600 self.endStopYMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymin.png'))
601 self.endStopYMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_ymax.png'))
602 self.endStopZMinBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmin.png'))
603 self.endStopZMaxBitmap = wx.Bitmap(resources.getPathForImage('endstop_zmax.png'))
606 _("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."))
607 b1, b2 = self.AddDualButton(_("Run checks"), _("Skip checks"))
608 b1.Bind(wx.EVT_BUTTON, self.OnCheckClick)
609 b2.Bind(wx.EVT_BUTTON, self.OnSkipClick)
611 self.commState = self.AddCheckmark(_("Communication:"), self.unknownBitmap)
612 self.tempState = self.AddCheckmark(_("Temperature:"), self.unknownBitmap)
613 self.stopState = self.AddCheckmark(_("Endstops:"), self.unknownBitmap)
615 self.infoBox = self.AddInfoBox()
616 self.machineState = self.AddText("")
617 self.temperatureLabel = self.AddText("")
618 self.errorLogButton = self.AddButton(_("Show error log"))
619 self.errorLogButton.Show(False)
621 self.endstopBitmap = self.AddBitmap(self.endStopNoneBitmap)
623 self.xMinStop = False
624 self.xMaxStop = False
625 self.yMinStop = False
626 self.yMaxStop = False
627 self.zMinStop = False
628 self.zMaxStop = False
630 self.Bind(wx.EVT_BUTTON, self.OnErrorLog, self.errorLogButton)
633 if self.comm is not None:
637 self.endstopBitmap.Show(False)
640 def OnSkipClick(self, e):
641 self.GetParent().FindWindowById(wx.ID_FORWARD).Enable()
642 self.GetParent().ShowPage(self.GetNext())
644 def OnCheckClick(self, e=None):
645 self.errorLogButton.Show(False)
646 if self.comm is not None:
650 wx.CallAfter(self.OnCheckClick)
652 self.infoBox.SetBusy(_("Connecting to machine."))
653 self.commState.SetBitmap(self.unknownBitmap)
654 self.tempState.SetBitmap(self.unknownBitmap)
655 self.stopState.SetBitmap(self.unknownBitmap)
656 self.checkupState = 0
657 self.checkExtruderNr = 0
658 self.comm = machineCom.MachineCom(callbackObject=self)
660 def OnErrorLog(self, e):
661 printWindow.LogWindow('\n'.join(self.comm.getLog()))
663 def mcLog(self, message):
666 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
667 if not self.comm.isOperational():
669 if self.checkupState == 0:
670 self.tempCheckTimeout = 20
671 if temp[self.checkExtruderNr] > 70:
672 self.checkupState = 1
673 wx.CallAfter(self.infoBox.SetInfo, _("Cooldown before temperature check."))
674 self.comm.sendCommand("M104 S0 T%d" % (self.checkExtruderNr))
675 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
677 self.startTemp = temp[self.checkExtruderNr]
678 self.checkupState = 2
679 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
680 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
681 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
682 elif self.checkupState == 1:
683 if temp[self.checkExtruderNr] < 60:
684 self.startTemp = temp[self.checkExtruderNr]
685 self.checkupState = 2
686 wx.CallAfter(self.infoBox.SetInfo, _("Checking the heater and temperature sensor."))
687 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
688 self.comm.sendCommand('M104 S200 T%d' % (self.checkExtruderNr))
689 elif self.checkupState == 2:
690 #print "WARNING, TEMPERATURE TEST DISABLED FOR TESTING!"
691 if temp[self.checkExtruderNr] > self.startTemp + 40:
692 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
693 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
694 if self.checkExtruderNr < int(profile.getMachineSetting('extruder_amount')):
695 self.checkExtruderNr = 0
696 self.checkupState = 3
697 wx.CallAfter(self.infoBox.SetAttention, _("Please make sure none of the endstops are pressed."))
698 wx.CallAfter(self.endstopBitmap.Show, True)
699 wx.CallAfter(self.Layout)
700 self.comm.sendCommand('M119')
701 wx.CallAfter(self.tempState.SetBitmap, self.checkBitmap)
703 self.checkupState = 0
704 self.checkExtruderNr += 1
706 self.tempCheckTimeout -= 1
707 if self.tempCheckTimeout < 1:
708 self.checkupState = -1
709 wx.CallAfter(self.tempState.SetBitmap, self.crossBitmap)
710 wx.CallAfter(self.infoBox.SetError, _("Temperature measurement FAILED!"), 'http://wiki.ultimaker.com/Cura:_Temperature_measurement_problems')
711 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
712 self.comm.sendCommand('M104 S0 T%d' % (self.checkExtruderNr))
713 elif self.checkupState >= 3 and self.checkupState < 10:
714 self.comm.sendCommand('M119')
715 wx.CallAfter(self.temperatureLabel.SetLabel, _("Head temperature: %d") % (temp[self.checkExtruderNr]))
717 def mcStateChange(self, state):
718 if self.comm is None:
720 if self.comm.isOperational():
721 wx.CallAfter(self.commState.SetBitmap, self.checkBitmap)
722 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
723 elif self.comm.isError():
724 wx.CallAfter(self.commState.SetBitmap, self.crossBitmap)
725 wx.CallAfter(self.infoBox.SetError, _("Failed to establish connection with the printer."), 'http://wiki.ultimaker.com/Cura:_Connection_problems')
726 wx.CallAfter(self.endstopBitmap.Show, False)
727 wx.CallAfter(self.machineState.SetLabel, '%s' % (self.comm.getErrorString()))
728 wx.CallAfter(self.errorLogButton.Show, True)
729 wx.CallAfter(self.Layout)
731 wx.CallAfter(self.machineState.SetLabel, _("Communication State: %s") % (self.comm.getStateString()))
733 def mcMessage(self, message):
734 if self.checkupState >= 3 and self.checkupState < 10 and ('_min' in message or '_max' in message):
735 for data in message.split(' '):
737 tag, value = data.split(':', 1)
739 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
741 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
743 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
745 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
747 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
749 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
751 tag, value = map(str.strip, message.split(':', 1))
753 self.xMinStop = (value == 'H' or value == 'TRIGGERED')
755 self.xMaxStop = (value == 'H' or value == 'TRIGGERED')
757 self.yMinStop = (value == 'H' or value == 'TRIGGERED')
759 self.yMaxStop = (value == 'H' or value == 'TRIGGERED')
761 self.zMinStop = (value == 'H' or value == 'TRIGGERED')
763 self.zMaxStop = (value == 'H' or value == 'TRIGGERED')
764 if 'z_max' in message:
765 self.comm.sendCommand('M119')
767 if self.checkupState == 3:
768 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
769 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
770 self.checkupState = 5
771 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
772 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
774 self.checkupState = 4
775 wx.CallAfter(self.infoBox.SetAttention, _("Please press the right X endstop."))
776 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMaxBitmap)
777 elif self.checkupState == 4:
778 if not self.xMinStop and self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
779 self.checkupState = 5
780 wx.CallAfter(self.infoBox.SetAttention, _("Please press the left X endstop."))
781 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopXMinBitmap)
782 elif self.checkupState == 5:
783 if self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
784 self.checkupState = 6
785 wx.CallAfter(self.infoBox.SetAttention, _("Please press the front Y endstop."))
786 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMinBitmap)
787 elif self.checkupState == 6:
788 if not self.xMinStop and not self.xMaxStop and self.yMinStop and not self.yMaxStop and not self.zMinStop and not self.zMaxStop:
789 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
790 self.checkupState = 8
791 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
792 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
794 self.checkupState = 7
795 wx.CallAfter(self.infoBox.SetAttention, _("Please press the back Y endstop."))
796 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopYMaxBitmap)
797 elif self.checkupState == 7:
798 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and self.yMaxStop and not self.zMinStop and not self.zMaxStop:
799 self.checkupState = 8
800 wx.CallAfter(self.infoBox.SetAttention, _("Please press the top Z endstop."))
801 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMinBitmap)
802 elif self.checkupState == 8:
803 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and self.zMinStop and not self.zMaxStop:
804 if profile.getMachineSetting('machine_type') == 'ultimaker_plus':
805 self.checkupState = 10
807 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
808 wx.CallAfter(self.infoBox.SetReadyIndicator)
809 wx.CallAfter(self.endstopBitmap.Show, False)
810 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
811 wx.CallAfter(self.OnSkipClick, None)
813 self.checkupState = 9
814 wx.CallAfter(self.infoBox.SetAttention, _("Please press the bottom Z endstop."))
815 wx.CallAfter(self.endstopBitmap.SetBitmap, self.endStopZMaxBitmap)
816 elif self.checkupState == 9:
817 if not self.xMinStop and not self.xMaxStop and not self.yMinStop and not self.yMaxStop and not self.zMinStop and self.zMaxStop:
818 self.checkupState = 10
820 wx.CallAfter(self.infoBox.SetInfo, _("Checkup finished"))
821 wx.CallAfter(self.infoBox.SetReadyIndicator)
822 wx.CallAfter(self.endstopBitmap.Show, False)
823 wx.CallAfter(self.stopState.SetBitmap, self.checkBitmap)
824 wx.CallAfter(self.OnSkipClick, None)
826 def mcProgress(self, lineNr):
829 def mcZChange(self, newZ):
833 class UltimakerCalibrationPage(InfoPage):
834 def __init__(self, parent):
835 super(UltimakerCalibrationPage, self).__init__(parent, "Ultimaker Calibration")
837 self.AddText("Your Ultimaker requires some calibration.")
838 self.AddText("This calibration is needed for a proper extrusion amount.")
840 self.AddText("The following values are needed:")
841 self.AddText("* Diameter of filament")
842 self.AddText("* Number of steps per mm of filament extrusion")
844 self.AddText("The better you have calibrated these values, the better your prints\nwill become.")
846 self.AddText("First we need the diameter of your filament:")
847 self.filamentDiameter = self.AddTextCtrl(profile.getProfileSetting('filament_diameter'))
849 "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.")
850 self.AddText("Note: This value can be changed later at any time.")
853 profile.putProfileSetting('filament_diameter', self.filamentDiameter.GetValue())
856 class UltimakerCalibrateStepsPerEPage(InfoPage):
857 def __init__(self, parent):
858 super(UltimakerCalibrateStepsPerEPage, self).__init__(parent, "Ultimaker Calibration")
860 #if profile.getMachineSetting('steps_per_e') == '0':
861 # profile.putMachineSetting('steps_per_e', '865.888')
863 self.AddText(_("Calibrating the Steps Per E requires some manual actions."))
864 self.AddText(_("First remove any filament from your machine."))
865 self.AddText(_("Next put in your filament so the tip is aligned with the\ntop of the extruder drive."))
866 self.AddText(_("We'll push the filament 100mm"))
867 self.extrudeButton = self.AddButton(_("Extrude 100mm filament"))
868 self.AddText(_("Now measure the amount of extruded filament:\n(this can be more or less then 100mm)"))
869 self.lengthInput, self.saveLengthButton = self.AddTextCtrlButton("100", _("Save"))
870 self.AddText(_("This results in the following steps per E:"))
871 self.stepsPerEInput = self.AddTextCtrl(profile.getMachineSetting('steps_per_e'))
872 self.AddText(_("You can repeat these steps to get better calibration."))
875 _("If you still have filament in your printer which needs\nheat to remove, press the heat up button below:"))
876 self.heatButton = self.AddButton(_("Heatup for filament removal"))
878 self.saveLengthButton.Bind(wx.EVT_BUTTON, self.OnSaveLengthClick)
879 self.extrudeButton.Bind(wx.EVT_BUTTON, self.OnExtrudeClick)
880 self.heatButton.Bind(wx.EVT_BUTTON, self.OnHeatClick)
882 def OnSaveLengthClick(self, e):
883 currentEValue = float(self.stepsPerEInput.GetValue())
884 realExtrudeLength = float(self.lengthInput.GetValue())
885 newEValue = currentEValue * 100 / realExtrudeLength
886 self.stepsPerEInput.SetValue(str(newEValue))
887 self.lengthInput.SetValue("100")
889 def OnExtrudeClick(self, e):
890 t = threading.Thread(target=self.OnExtrudeRun)
894 def OnExtrudeRun(self):
895 self.heatButton.Enable(False)
896 self.extrudeButton.Enable(False)
897 currentEValue = float(self.stepsPerEInput.GetValue())
898 self.comm = machineCom.MachineCom()
899 if not self.comm.isOpen():
901 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
902 'Printer error', wx.OK | wx.ICON_INFORMATION)
903 self.heatButton.Enable(True)
904 self.extrudeButton.Enable(True)
907 line = self.comm.readline()
912 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
915 self.sendGCommand('M302') #Disable cold extrusion protection
916 self.sendGCommand("M92 E%f" % (currentEValue))
917 self.sendGCommand("G92 E0")
918 self.sendGCommand("G1 E100 F600")
921 self.extrudeButton.Enable()
922 self.heatButton.Enable()
924 def OnHeatClick(self, e):
925 t = threading.Thread(target=self.OnHeatRun)
930 self.heatButton.Enable(False)
931 self.extrudeButton.Enable(False)
932 self.comm = machineCom.MachineCom()
933 if not self.comm.isOpen():
935 _("Error: Failed to open serial port to machine\nIf this keeps happening, try disconnecting and reconnecting the USB cable"),
936 'Printer error', wx.OK | wx.ICON_INFORMATION)
937 self.heatButton.Enable(True)
938 self.extrudeButton.Enable(True)
941 line = self.comm.readline()
943 self.heatButton.Enable(True)
944 self.extrudeButton.Enable(True)
948 #Wait 3 seconds for the SD card init to timeout if we have SD in our firmware but there is no SD card found.
951 self.sendGCommand('M104 S200') #Set the temperature to 200C, should be enough to get PLA and ABS out.
953 'Wait till you can remove the filament from the machine, and press OK.\n(Temperature is set to 200C)',
954 'Machine heatup', wx.OK | wx.ICON_INFORMATION)
955 self.sendGCommand('M104 S0')
958 self.heatButton.Enable(True)
959 self.extrudeButton.Enable(True)
961 def sendGCommand(self, cmd):
962 self.comm.sendCommand(cmd) #Disable cold extrusion protection
964 line = self.comm.readline()
967 if line.startswith('ok'):
971 profile.putPreference('steps_per_e', self.stepsPerEInput.GetValue())
973 class Ultimaker2ReadyPage(InfoPage):
974 def __init__(self, parent):
975 super(Ultimaker2ReadyPage, self).__init__(parent, "Ultimaker2")
976 self.AddText('Congratulations on your the purchase of your brand new Ultimaker2.')
977 self.AddText('Cura is now ready to be used with your Ultimaker2.')
980 class LulzbotReadyPage(InfoPage):
981 def __init__(self, parent):
982 super(LulzbotReadyPage, self).__init__(parent, "Lulzbot TAZ/Mini")
983 self.AddText('Cura is now ready to be used with your Lulzbot.')
986 class configWizard(wx.wizard.Wizard):
987 def __init__(self, addNew = False):
988 super(configWizard, self).__init__(None, -1, "Configuration Wizard")
990 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
991 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
993 self.firstInfoPage = FirstInfoPage(self, addNew)
994 self.machineSelectPage = MachineSelectPage(self)
995 self.ultimakerSelectParts = SelectParts(self)
996 self.ultimakerFirmwareUpgradePage = UltimakerFirmwareUpgradePage(self)
997 self.ultimakerCheckupPage = UltimakerCheckupPage(self)
998 self.ultimakerCalibrationPage = UltimakerCalibrationPage(self)
999 self.ultimakerCalibrateStepsPerEPage = UltimakerCalibrateStepsPerEPage(self)
1000 self.bedLevelPage = bedLevelWizardMain(self)
1001 self.headOffsetCalibration = headOffsetCalibrationPage(self)
1002 self.printrbotSelectType = PrintrbotPage(self)
1003 self.otherMachineSelectPage = OtherMachineSelectPage(self)
1004 self.customRepRapInfoPage = CustomRepRapInfoPage(self)
1005 self.otherMachineInfoPage = OtherMachineInfoPage(self)
1007 self.ultimaker2ReadyPage = Ultimaker2ReadyPage(self)
1008 self.lulzbotReadyPage = LulzbotReadyPage(self)
1010 wx.wizard.WizardPageSimple.Chain(self.firstInfoPage, self.machineSelectPage)
1011 #wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimaker2ReadyPage)
1012 wx.wizard.WizardPageSimple.Chain(self.machineSelectPage, self.ultimakerSelectParts)
1013 wx.wizard.WizardPageSimple.Chain(self.ultimakerSelectParts, self.ultimakerFirmwareUpgradePage)
1014 wx.wizard.WizardPageSimple.Chain(self.ultimakerFirmwareUpgradePage, self.ultimakerCheckupPage)
1015 wx.wizard.WizardPageSimple.Chain(self.ultimakerCheckupPage, self.bedLevelPage)
1016 #wx.wizard.WizardPageSimple.Chain(self.ultimakerCalibrationPage, self.ultimakerCalibrateStepsPerEPage)
1017 wx.wizard.WizardPageSimple.Chain(self.printrbotSelectType, self.otherMachineInfoPage)
1018 wx.wizard.WizardPageSimple.Chain(self.otherMachineSelectPage, self.customRepRapInfoPage)
1020 self.FitToPage(self.firstInfoPage)
1021 self.GetPageAreaSizer().Add(self.firstInfoPage)
1023 self.RunWizard(self.firstInfoPage)
1026 def OnPageChanging(self, e):
1027 e.GetPage().StoreData()
1029 def OnPageChanged(self, e):
1030 if e.GetPage().AllowNext():
1031 self.FindWindowById(wx.ID_FORWARD).Enable()
1033 self.FindWindowById(wx.ID_FORWARD).Disable()
1034 if e.GetPage().AllowBack():
1035 self.FindWindowById(wx.ID_BACKWARD).Enable()
1037 self.FindWindowById(wx.ID_BACKWARD).Disable()
1039 class bedLevelWizardMain(InfoPage):
1040 def __init__(self, parent):
1041 super(bedLevelWizardMain, self).__init__(parent, "Bed leveling wizard")
1043 self.AddText('This wizard will help you in leveling your printer bed')
1045 self.AddText('It will do the following steps')
1046 self.AddText('* Move the printer head to each corner')
1047 self.AddText(' and let you adjust the height of the bed to the nozzle')
1048 self.AddText('* Print a line around the bed to check if it is level')
1051 self.connectButton = self.AddButton('Connect to printer')
1054 self.infoBox = self.AddInfoBox()
1055 self.resumeButton = self.AddButton('Resume')
1056 self.upButton, self.downButton = self.AddDualButton('Up 0.2mm', 'Down 0.2mm')
1057 self.upButton2, self.downButton2 = self.AddDualButton('Up 10mm', 'Down 10mm')
1058 self.resumeButton.Enable(False)
1060 self.upButton.Enable(False)
1061 self.downButton.Enable(False)
1062 self.upButton2.Enable(False)
1063 self.downButton2.Enable(False)
1065 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1066 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1067 self.Bind(wx.EVT_BUTTON, self.OnBedUp, self.upButton)
1068 self.Bind(wx.EVT_BUTTON, self.OnBedDown, self.downButton)
1069 self.Bind(wx.EVT_BUTTON, self.OnBedUp2, self.upButton2)
1070 self.Bind(wx.EVT_BUTTON, self.OnBedDown2, self.downButton2)
1072 def OnConnect(self, e = None):
1073 if self.comm is not None:
1077 wx.CallAfter(self.OnConnect)
1079 self.connectButton.Enable(False)
1080 self.comm = machineCom.MachineCom(callbackObject=self)
1081 self.infoBox.SetBusy('Connecting to machine.')
1082 self._wizardState = 0
1084 def OnBedUp(self, e):
1085 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1086 self.comm.sendCommand('G92 Z10')
1087 self.comm.sendCommand('G1 Z9.8 F%d' % (feedZ))
1088 self.comm.sendCommand('M400')
1090 def OnBedDown(self, e):
1091 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1092 self.comm.sendCommand('G92 Z10')
1093 self.comm.sendCommand('G1 Z10.2 F%d' % (feedZ))
1094 self.comm.sendCommand('M400')
1096 def OnBedUp2(self, e):
1097 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1098 self.comm.sendCommand('G92 Z10')
1099 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1100 self.comm.sendCommand('M400')
1102 def OnBedDown2(self, e):
1103 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1104 self.comm.sendCommand('G92 Z10')
1105 self.comm.sendCommand('G1 Z20 F%d' % (feedZ))
1106 self.comm.sendCommand('M400')
1108 def AllowNext(self):
1109 if self.GetParent().headOffsetCalibration is not None and int(profile.getMachineSetting('extruder_amount')) > 1:
1110 wx.wizard.WizardPageSimple.Chain(self, self.GetParent().headOffsetCalibration)
1113 def OnResume(self, e):
1114 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1115 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1116 if self._wizardState == -1:
1117 wx.CallAfter(self.infoBox.SetInfo, 'Homing printer...')
1118 wx.CallAfter(self.upButton.Enable, False)
1119 wx.CallAfter(self.downButton.Enable, False)
1120 wx.CallAfter(self.upButton2.Enable, False)
1121 wx.CallAfter(self.downButton2.Enable, False)
1122 self.comm.sendCommand('M105')
1123 self.comm.sendCommand('G28')
1124 self._wizardState = 1
1125 elif self._wizardState == 2:
1126 if profile.getMachineSetting('has_heated_bed') == 'True':
1127 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back center...')
1128 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1129 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') / 2.0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1130 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1131 self.comm.sendCommand('M400')
1132 self._wizardState = 3
1134 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back left corner...')
1135 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1136 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, profile.getMachineSettingFloat('machine_depth'), feedTravel))
1137 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1138 self.comm.sendCommand('M400')
1139 self._wizardState = 3
1140 elif self._wizardState == 4:
1141 if profile.getMachineSetting('has_heated_bed') == 'True':
1142 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to front right corner...')
1143 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1144 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 5, feedTravel))
1145 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1146 self.comm.sendCommand('M400')
1147 self._wizardState = 7
1149 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to back right corner...')
1150 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1151 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, profile.getMachineSettingFloat('machine_depth') - 25, feedTravel))
1152 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1153 self.comm.sendCommand('M400')
1154 self._wizardState = 5
1155 elif self._wizardState == 6:
1156 wx.CallAfter(self.infoBox.SetBusy, 'Moving head to front right corner...')
1157 self.comm.sendCommand('G1 Z3 F%d' % (feedZ))
1158 self.comm.sendCommand('G1 X%d Y%d F%d' % (profile.getMachineSettingFloat('machine_width') - 5.0, 20, feedTravel))
1159 self.comm.sendCommand('G1 Z0 F%d' % (feedZ))
1160 self.comm.sendCommand('M400')
1161 self._wizardState = 7
1162 elif self._wizardState == 8:
1163 wx.CallAfter(self.infoBox.SetBusy, 'Heating up printer...')
1164 self.comm.sendCommand('G1 Z15 F%d' % (feedZ))
1165 self.comm.sendCommand('M104 S%d' % (profile.getProfileSettingFloat('print_temperature')))
1166 self.comm.sendCommand('G1 X%d Y%d F%d' % (0, 0, feedTravel))
1167 self._wizardState = 9
1168 elif self._wizardState == 10:
1169 self._wizardState = 11
1170 wx.CallAfter(self.infoBox.SetInfo, 'Printing a square on the printer bed at 0.3mm height.')
1171 feedZ = profile.getProfileSettingFloat('print_speed') * 60
1172 feedPrint = profile.getProfileSettingFloat('print_speed') * 60
1173 feedTravel = profile.getProfileSettingFloat('travel_speed') * 60
1174 w = profile.getMachineSettingFloat('machine_width') - 10
1175 d = profile.getMachineSettingFloat('machine_depth')
1176 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
1177 filamentArea = math.pi * filamentRadius * filamentRadius
1178 ePerMM = (profile.calculateEdgeWidth() * 0.3) / filamentArea
1182 'G1 Z2 F%d' % (feedZ),
1184 'G1 X%d Y%d F%d' % (5, 5, feedTravel),
1185 'G1 Z0.3 F%d' % (feedZ)]
1187 gcodeList.append('G1 E%f F%d' % (eValue, profile.getProfileSettingFloat('retraction_speed') * 60))
1189 for i in xrange(0, 3):
1190 dist = 5.0 + 0.4 * float(i)
1191 eValue += (d - 2.0*dist) * ePerMM
1192 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, d - dist, eValue, feedPrint))
1193 eValue += (w - 2.0*dist) * ePerMM
1194 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, d - dist, eValue, feedPrint))
1195 eValue += (d - 2.0*dist) * ePerMM
1196 gcodeList.append('G1 X%f Y%f E%f F%d' % (w - dist, dist, eValue, feedPrint))
1197 eValue += (w - 2.0*dist) * ePerMM
1198 gcodeList.append('G1 X%f Y%f E%f F%d' % (dist, dist, eValue, feedPrint))
1200 gcodeList.append('M400')
1201 self.comm.printGCode(gcodeList)
1202 self.resumeButton.Enable(False)
1204 def mcLog(self, message):
1205 print 'Log:', message
1207 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1208 if self._wizardState == 1:
1209 self._wizardState = 2
1210 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front left screw of your printer bed\nSo the nozzle just hits the bed.')
1211 wx.CallAfter(self.resumeButton.Enable, True)
1212 elif self._wizardState == 3:
1213 self._wizardState = 4
1214 if profile.getMachineSetting('has_heated_bed') == 'True':
1215 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back screw of your printer bed\nSo the nozzle just hits the bed.')
1217 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back left screw of your printer bed\nSo the nozzle just hits the bed.')
1218 wx.CallAfter(self.resumeButton.Enable, True)
1219 elif self._wizardState == 5:
1220 self._wizardState = 6
1221 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the back right screw of your printer bed\nSo the nozzle just hits the bed.')
1222 wx.CallAfter(self.resumeButton.Enable, True)
1223 elif self._wizardState == 7:
1224 self._wizardState = 8
1225 wx.CallAfter(self.infoBox.SetAttention, 'Adjust the front right screw of your printer bed\nSo the nozzle just hits the bed.')
1226 wx.CallAfter(self.resumeButton.Enable, True)
1227 elif self._wizardState == 9:
1228 if temp[0] < profile.getProfileSettingFloat('print_temperature') - 5:
1229 wx.CallAfter(self.infoBox.SetInfo, 'Heating up printer: %d/%d' % (temp[0], profile.getProfileSettingFloat('print_temperature')))
1231 wx.CallAfter(self.infoBox.SetAttention, 'The printer is hot now. Please insert some PLA filament into the printer.')
1232 wx.CallAfter(self.resumeButton.Enable, True)
1233 self._wizardState = 10
1235 def mcStateChange(self, state):
1236 if self.comm is None:
1238 if self.comm.isOperational():
1239 if self._wizardState == 0:
1240 wx.CallAfter(self.infoBox.SetAttention, 'Use the up/down buttons to move the bed and adjust your Z endstop.')
1241 wx.CallAfter(self.upButton.Enable, True)
1242 wx.CallAfter(self.downButton.Enable, True)
1243 wx.CallAfter(self.upButton2.Enable, True)
1244 wx.CallAfter(self.downButton2.Enable, True)
1245 wx.CallAfter(self.resumeButton.Enable, True)
1246 self._wizardState = -1
1247 elif self._wizardState == 11 and not self.comm.isPrinting():
1248 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1249 self.comm.sendCommand('G92 E0')
1250 self.comm.sendCommand('G1 E-10 F%d' % (profile.getProfileSettingFloat('retraction_speed') * 60))
1251 self.comm.sendCommand('M104 S0')
1252 wx.CallAfter(self.infoBox.SetInfo, 'Calibration finished.\nThe squares on the bed should slightly touch each other.')
1253 wx.CallAfter(self.infoBox.SetReadyIndicator)
1254 wx.CallAfter(self.GetParent().FindWindowById(wx.ID_FORWARD).Enable)
1255 wx.CallAfter(self.connectButton.Enable, True)
1256 self._wizardState = 12
1257 elif self.comm.isError():
1258 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1260 def mcMessage(self, message):
1263 def mcProgress(self, lineNr):
1266 def mcZChange(self, newZ):
1269 class headOffsetCalibrationPage(InfoPage):
1270 def __init__(self, parent):
1271 super(headOffsetCalibrationPage, self).__init__(parent, "Printer head offset calibration")
1273 self.AddText('This wizard will help you in calibrating the printer head offsets of your dual extrusion machine')
1276 self.connectButton = self.AddButton('Connect to printer')
1279 self.infoBox = self.AddInfoBox()
1280 self.textEntry = self.AddTextCtrl('')
1281 self.textEntry.Enable(False)
1282 self.resumeButton = self.AddButton('Resume')
1283 self.resumeButton.Enable(False)
1285 self.Bind(wx.EVT_BUTTON, self.OnConnect, self.connectButton)
1286 self.Bind(wx.EVT_BUTTON, self.OnResume, self.resumeButton)
1288 def AllowBack(self):
1291 def OnConnect(self, e = None):
1292 if self.comm is not None:
1296 wx.CallAfter(self.OnConnect)
1298 self.connectButton.Enable(False)
1299 self.comm = machineCom.MachineCom(callbackObject=self)
1300 self.infoBox.SetBusy('Connecting to machine.')
1301 self._wizardState = 0
1303 def OnResume(self, e):
1304 if self._wizardState == 2:
1305 self._wizardState = 3
1306 wx.CallAfter(self.infoBox.SetBusy, 'Printing initial calibration cross')
1308 w = profile.getMachineSettingFloat('machine_width')
1309 d = profile.getMachineSettingFloat('machine_depth')
1311 gcode = gcodeGenerator.gcodeGenerator()
1312 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1313 gcode.setPrintSpeed(profile.getProfileSettingFloat('bottom_layer_speed'))
1320 gcode.addMove(w/2, 5)
1321 gcode.addMove(z=0.2)
1323 gcode.addExtrude(w/2, d-5.0)
1325 gcode.addMove(5, d/2)
1327 gcode.addExtrude(w-5.0, d/2)
1328 gcode.addRetract(15)
1331 gcode.addMove(w/2, 5)
1333 gcode.addExtrude(w/2, d-5.0)
1335 gcode.addMove(5, d/2)
1337 gcode.addExtrude(w-5.0, d/2)
1338 gcode.addRetract(15)
1343 gcode.addCmd('M400')
1345 self.comm.printGCode(gcode.list())
1346 self.resumeButton.Enable(False)
1347 elif self._wizardState == 4:
1349 float(self.textEntry.GetValue())
1352 profile.putPreference('extruder_offset_x1', self.textEntry.GetValue())
1353 self._wizardState = 5
1354 self.infoBox.SetAttention('Please measure the distance between the horizontal lines in millimeters.')
1355 self.textEntry.SetValue('0.0')
1356 self.textEntry.Enable(True)
1357 elif self._wizardState == 5:
1359 float(self.textEntry.GetValue())
1362 profile.putPreference('extruder_offset_y1', self.textEntry.GetValue())
1363 self._wizardState = 6
1364 self.infoBox.SetBusy('Printing the fine calibration lines.')
1365 self.textEntry.SetValue('')
1366 self.textEntry.Enable(False)
1367 self.resumeButton.Enable(False)
1369 x = profile.getMachineSettingFloat('extruder_offset_x1')
1370 y = profile.getMachineSettingFloat('extruder_offset_y1')
1371 gcode = gcodeGenerator.gcodeGenerator()
1372 gcode.setExtrusionRate(profile.getProfileSettingFloat('nozzle_size') * 1.5, 0.2)
1373 gcode.setPrintSpeed(25)
1376 gcode.addMove(50, 40, 0.2)
1378 for n in xrange(0, 10):
1379 gcode.addExtrude(50 + n * 10, 150)
1380 gcode.addExtrude(50 + n * 10 + 5, 150)
1381 gcode.addExtrude(50 + n * 10 + 5, 40)
1382 gcode.addExtrude(50 + n * 10 + 10, 40)
1383 gcode.addMove(40, 50)
1384 for n in xrange(0, 10):
1385 gcode.addExtrude(150, 50 + n * 10)
1386 gcode.addExtrude(150, 50 + n * 10 + 5)
1387 gcode.addExtrude(40, 50 + n * 10 + 5)
1388 gcode.addExtrude(40, 50 + n * 10 + 10)
1389 gcode.addRetract(15)
1392 gcode.addMove(50 - x, 30 - y, 0.2)
1394 for n in xrange(0, 10):
1395 gcode.addExtrude(50 + n * 10.2 - 1.0 - x, 140 - y)
1396 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 140 - y)
1397 gcode.addExtrude(50 + n * 10.2 - 1.0 + 5.1 - x, 30 - y)
1398 gcode.addExtrude(50 + n * 10.2 - 1.0 + 10 - x, 30 - y)
1399 gcode.addMove(30 - x, 50 - y, 0.2)
1400 for n in xrange(0, 10):
1401 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 - y)
1402 gcode.addExtrude(160 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1403 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 5.1 - y)
1404 gcode.addExtrude(30 - x, 50 + n * 10.2 - 1.0 + 10 - y)
1405 gcode.addRetract(15)
1407 gcode.addCmd('M400')
1408 gcode.addCmd('M104 T0 S0')
1409 gcode.addCmd('M104 T1 S0')
1410 self.comm.printGCode(gcode.list())
1411 elif self._wizardState == 7:
1413 n = int(self.textEntry.GetValue()) - 1
1416 x = profile.getMachineSettingFloat('extruder_offset_x1')
1418 profile.putPreference('extruder_offset_x1', '%0.2f' % (x))
1419 self.infoBox.SetAttention('Which horizontal line number lays perfect on top of each other? Front most line is zero.')
1420 self.textEntry.SetValue('10')
1421 self._wizardState = 8
1422 elif self._wizardState == 8:
1424 n = int(self.textEntry.GetValue()) - 1
1427 y = profile.getMachineSettingFloat('extruder_offset_y1')
1429 profile.putPreference('extruder_offset_y1', '%0.2f' % (y))
1430 self.infoBox.SetInfo('Calibration finished. Offsets are: %s %s' % (profile.getMachineSettingFloat('extruder_offset_x1'), profile.getMachineSettingFloat('extruder_offset_y1')))
1431 self.infoBox.SetReadyIndicator()
1432 self._wizardState = 8
1434 self.resumeButton.Enable(False)
1436 def mcLog(self, message):
1437 print 'Log:', message
1439 def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp):
1440 if self._wizardState == 1:
1441 if temp[0] >= 210 and temp[1] >= 210:
1442 self._wizardState = 2
1443 wx.CallAfter(self.infoBox.SetAttention, 'Please load both extruders with PLA.')
1444 wx.CallAfter(self.resumeButton.Enable, True)
1445 wx.CallAfter(self.resumeButton.SetFocus)
1447 def mcStateChange(self, state):
1448 if self.comm is None:
1450 if self.comm.isOperational():
1451 if self._wizardState == 0:
1452 wx.CallAfter(self.infoBox.SetInfo, 'Homing printer and heating up both extruders.')
1453 self.comm.sendCommand('M105')
1454 self.comm.sendCommand('M104 S220 T0')
1455 self.comm.sendCommand('M104 S220 T1')
1456 self.comm.sendCommand('G28')
1457 self.comm.sendCommand('G1 Z15 F%d' % (profile.getProfileSettingFloat('print_speed') * 60))
1458 self._wizardState = 1
1459 if not self.comm.isPrinting():
1460 if self._wizardState == 3:
1461 self._wizardState = 4
1462 wx.CallAfter(self.infoBox.SetAttention, 'Please measure the distance between the vertical lines in millimeters.')
1463 wx.CallAfter(self.textEntry.SetValue, '0.0')
1464 wx.CallAfter(self.textEntry.Enable, True)
1465 wx.CallAfter(self.resumeButton.Enable, True)
1466 wx.CallAfter(self.resumeButton.SetFocus)
1467 elif self._wizardState == 6:
1468 self._wizardState = 7
1469 wx.CallAfter(self.infoBox.SetAttention, 'Which vertical line number lays perfect on top of each other? Leftmost line is zero.')
1470 wx.CallAfter(self.textEntry.SetValue, '10')
1471 wx.CallAfter(self.textEntry.Enable, True)
1472 wx.CallAfter(self.resumeButton.Enable, True)
1473 wx.CallAfter(self.resumeButton.SetFocus)
1475 elif self.comm.isError():
1476 wx.CallAfter(self.infoBox.SetError, 'Failed to establish connection with the printer.', 'http://wiki.ultimaker.com/Cura:_Connection_problems')
1478 def mcMessage(self, message):
1481 def mcProgress(self, lineNr):
1484 def mcZChange(self, newZ):
1487 class bedLevelWizard(wx.wizard.Wizard):
1489 super(bedLevelWizard, self).__init__(None, -1, "Bed leveling wizard")
1491 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1492 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1494 self.mainPage = bedLevelWizardMain(self)
1495 self.headOffsetCalibration = None
1497 self.FitToPage(self.mainPage)
1498 self.GetPageAreaSizer().Add(self.mainPage)
1500 self.RunWizard(self.mainPage)
1503 def OnPageChanging(self, e):
1504 e.GetPage().StoreData()
1506 def OnPageChanged(self, e):
1507 if e.GetPage().AllowNext():
1508 self.FindWindowById(wx.ID_FORWARD).Enable()
1510 self.FindWindowById(wx.ID_FORWARD).Disable()
1511 if e.GetPage().AllowBack():
1512 self.FindWindowById(wx.ID_BACKWARD).Enable()
1514 self.FindWindowById(wx.ID_BACKWARD).Disable()
1516 class headOffsetWizard(wx.wizard.Wizard):
1518 super(headOffsetWizard, self).__init__(None, -1, "Head offset wizard")
1520 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged)
1521 self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1523 self.mainPage = headOffsetCalibrationPage(self)
1525 self.FitToPage(self.mainPage)
1526 self.GetPageAreaSizer().Add(self.mainPage)
1528 self.RunWizard(self.mainPage)
1531 def OnPageChanging(self, e):
1532 e.GetPage().StoreData()
1534 def OnPageChanged(self, e):
1535 if e.GetPage().AllowNext():
1536 self.FindWindowById(wx.ID_FORWARD).Enable()
1538 self.FindWindowById(wx.ID_FORWARD).Disable()
1539 if e.GetPage().AllowBack():
1540 self.FindWindowById(wx.ID_BACKWARD).Enable()
1542 self.FindWindowById(wx.ID_BACKWARD).Disable()