Printrun/pronterface.py

1327 lines
53 KiB
Python
Raw Normal View History

2011-06-08 14:19:38 +00:00
#!/usr/bin/env python
2011-08-06 23:45:52 +00:00
# Set up Internationalization using gettext
import gettext
gettext.install('pronterface', '/usr/share/pronterface/locale', unicode=1)
2011-06-08 14:19:38 +00:00
try:
import wx
except:
2011-08-06 23:45:52 +00:00
print _("WX is not installed. This program requires WX to run.")
2011-06-08 14:19:38 +00:00
raise
import printcore, os, sys, glob, time, threading, traceback, StringIO, gviz, traceback, cStringIO
try:
os.chdir(os.path.split(__file__)[0])
except:
pass
2011-06-08 14:19:38 +00:00
thread=threading.Thread
2011-06-09 17:26:07 +00:00
winsize=(800,500)
2011-06-08 14:19:38 +00:00
if os.name=="nt":
2011-06-09 17:26:07 +00:00
winsize=(800,530)
2011-06-08 14:19:38 +00:00
try:
import _winreg
except:
pass
2011-06-08 14:19:38 +00:00
import pronsole
2011-06-08 22:02:00 +00:00
def dosify(name):
return os.path.split(name)[1].split(".")[0][:8]+".g"
class Tee(object):
def __init__(self, target):
self.stdout = sys.stdout
sys.stdout = self
self.target=target
def __del__(self):
sys.stdout = self.stdout
def write(self, data):
self.target(data)
self.stdout.write(data)
def flush(self):
self.stdout.flush()
2011-06-08 22:02:00 +00:00
class PronterWindow(wx.Frame,pronsole.pronsole):
2011-06-09 17:26:07 +00:00
def __init__(self, filename=None,size=winsize):
pronsole.pronsole.__init__(self)
2011-06-29 21:32:24 +00:00
self.settings.last_file_path = ""
self.settings.last_temperature = 0.0
self.settings.last_bed_temperature = 0.0
2011-08-07 20:00:13 +00:00
self.settings.bed_size_x = 200.
self.settings.bed_size_y = 200.
self.settings.preview_grid_step1 = 10.
self.settings.preview_grid_step2 = 50.
2011-08-07 20:11:35 +00:00
self.settings.preview_extrusion_width = 0.5
2011-06-08 14:19:38 +00:00
self.filename=filename
os.putenv("UBUNTU_MENUPROXY","0")
2011-08-06 23:45:52 +00:00
wx.Frame.__init__(self,None,title=_("Printer Interface"),size=size);
self.SetIcon(wx.Icon("P-face.ico",wx.BITMAP_TYPE_ICO))
2011-06-08 14:19:38 +00:00
self.panel=wx.Panel(self,-1,size=size)
self.statuscheck=False
self.tempreport=""
self.monitor=0
self.monitor_interval=3
2011-06-08 14:19:38 +00:00
self.paused=False
2011-06-09 19:43:42 +00:00
xcol=(245,245,108)
ycol=(180,180,255)
zcol=(180,255,180)
self.cpbuttons=[
2011-08-06 23:45:52 +00:00
[_("X+100"),("move X 100"),(2,0),xcol,(1,3)],
[_("X+10"),("move X 10"),(3,0),xcol,(1,3)],
[_("X+1"),("move X 1"),(4,0),xcol,(1,3)],
[_("X+0.1"),("move X 0.1"),(5,0),xcol,(1,3)],
[_("HomeX"),("home X"),(6,0),(205,205,78),(1,3)],
[_("X-0.1"),("move X -0.1"),(7,0),xcol,(1,3)],
[_("X-1"),("move X -1"),(8,0),xcol,(1,3)],
[_("X-10"),("move X -10"),(9,0),xcol,(1,3)],
[_("X-100"),("move X -100"),(10,0),xcol,(1,3)],
[_("Y+100"),("move Y 100"),(2,3),ycol,(1,3)],
[_("Y+10"),("move Y 10"),(3,3),ycol,(1,3)],
[_("Y+1"),("move Y 1"),(4,3),ycol,(1,3)],
[_("Y+0.1"),("move Y 0.1"),(5,3),ycol,(1,3)],
[_("HomeY"),("home Y"),(6,3),(150,150,205),(1,3)],
[_("Y-0.1"),("move Y -0.1"),(7,3),ycol,(1,3)],
[_("Y-1"),("move Y -1"),(8,3),ycol,(1,3)],
[_("Y-10"),("move Y -10"),(9,3),ycol,(1,3)],
[_("Y-100"),("move Y -100"),(10,3),ycol,(1,3)],
[_("Motors off"),("M84"),(2,6),(250,250,250),(1,3)],
[_("Z+10"),("move Z 10"),(3,6),zcol,(1,3)],
[_("Z+1"),("move Z 1"),(4,6),zcol,(1,3)],
[_("Z+0.1"),("move Z 0.1"),(5,6),zcol,(1,3)],
[_("HomeZ"),("home Z"),(6,6),(150,205,150),(1,3)],
[_("Z-0.1"),("move Z -0.1"),(7,6),zcol,(1,3)],
[_("Z-1"),("move Z -1"),(8,6),zcol,(1,3)],
[_("Z-10"),("move Z -10"),(9,6),zcol,(1,3)],
[_("Home"),("home"),(10,6),(250,250,250),(1,3)],
[_("Check temp"),("M105"),(11,6),(225,200,200),(1,3)],
[_("Extrude"),("extrude"),(13,0),(225,200,200),(1,2)],
[_("Reverse"),("reverse"),(14,0),(225,200,200),(1,2)],
]
self.custombuttons=[]
self.btndict={}
self.parse_cmdline(sys.argv[1:])
customdict={}
try:
execfile("custombtn.txt",customdict)
if len(customdict["btns"]):
if not len(self.custombuttons):
try:
self.custombuttons = customdict["btns"]
for n in xrange(len(self.custombuttons)):
self.cbutton_save(n,self.custombuttons[n])
os.rename("custombtn.txt","custombtn.old")
rco=open("custombtn.txt","w")
2011-08-06 23:45:52 +00:00
rco.write(_("# I moved all your custom buttons into .pronsolerc.\n# Please don't add them here any more.\n# Backup of your old buttons is in custombtn.old\n"))
rco.close()
except IOError,x:
print str(x)
else:
2011-08-06 23:45:52 +00:00
print _("Note!!! You have specified custom buttons in both custombtn.txt and .pronsolerc")
print _("Ignoring custombtn.txt. Remove all current buttons to revert to custombtn.txt")
except:
pass
2011-06-08 14:19:38 +00:00
self.popmenu()
self.popwindow()
self.t=Tee(self.catchprint)
self.stdout=sys.stdout
self.mini=False
self.p.sendcb=self.sentcb
self.p.startcb=self.startcb
self.p.endcb=self.endcb
self.starttime=0
2011-06-22 11:40:27 +00:00
self.curlayer=0
self.cur_button=None
def startcb(self):
self.starttime=time.time()
def endcb(self):
if(self.p.queueindex==0):
print "Print took "+str(int(time.time()-self.starttime)/60)+" minutes "+str(int(time.time()-self.starttime)%60)+" seconds"
wx.CallAfter(self.pausebtn.Disable)
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.printbtn.SetLabel,_("Print"))
def online(self):
2011-08-06 23:45:52 +00:00
print _("Printer is now online")
wx.CallAfter(self.connectbtn.Disable)
for i in self.printerControls:
wx.CallAfter(i.Enable)
if self.filename:
wx.CallAfter(self.printbtn.Enable)
def sentcb(self,line):
2011-06-22 11:40:27 +00:00
if("G1" in line):
if("Z" in line):
try:
layer=float(line.split("Z")[1].split()[0])
if(layer!=self.curlayer):
self.curlayer=layer
self.gviz.hilight=[]
2011-08-23 12:33:28 +00:00
threading.Thread(target=wx.CallAfter,args=(self.gviz.setlayer,layer)).start()
2011-06-22 11:40:27 +00:00
except:
pass
2011-08-23 12:33:28 +00:00
threading.Thread(target=self.gviz.addgcode,args=(line,1)).start()
#self.gwindow.p.addgcode(line,hilight=1)
def do_extrude(self,l=""):
try:
if not (l.__class__=="".__class__ or l.__class__==u"".__class__) or (not len(l)):
l=str(self.edist.GetValue())
pronsole.pronsole.do_extrude(self,l)
except:
raise
def do_reverse(self,l=""):
try:
if not (l.__class__=="".__class__ or l.__class__==u"".__class__) or (not len(l)):
l=str(float(self.edist.GetValue())*-1.0)
pronsole.pronsole.do_extrude(self,l)
except:
pass
2011-06-09 10:54:03 +00:00
def do_settemp(self,l=""):
try:
if not (l.__class__=="".__class__ or l.__class__==u"".__class__) or (not len(l)):
2011-06-11 21:03:01 +00:00
l=str(self.htemp.GetValue().split()[0])
2011-06-09 10:54:03 +00:00
l=l.lower().replace(",",".")
for i in self.temps.keys():
l=l.replace(i,self.temps[i])
f=float(l)
if f>=0:
if self.p.online:
self.p.send_now("M104 S"+l)
2011-08-06 23:45:52 +00:00
print _("Setting hotend temperature to "),f,_(" degrees Celsius.")
2011-06-09 10:54:03 +00:00
self.htemp.SetValue(l)
self.set("last_temperature",str(f))
2011-06-09 10:54:03 +00:00
else:
2011-08-06 23:45:52 +00:00
print _("Printer is not online.")
2011-06-09 10:54:03 +00:00
else:
2011-08-06 23:45:52 +00:00
print _("You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0.")
2011-06-09 10:54:03 +00:00
except:
2011-08-06 23:45:52 +00:00
print _("You must enter a temperature.")
2011-06-09 10:54:03 +00:00
def do_bedtemp(self,l=""):
try:
if not (l.__class__=="".__class__ or l.__class__==u"".__class__) or (not len(l)):
2011-06-11 21:03:01 +00:00
l=str(self.btemp.GetValue().split()[0])
2011-06-09 10:54:03 +00:00
l=l.lower().replace(",",".")
for i in self.bedtemps.keys():
l=l.replace(i,self.bedtemps[i])
f=float(l)
if f>=0:
if self.p.online:
self.p.send_now("M140 S"+l)
2011-08-06 23:45:52 +00:00
print _("Setting bed temperature to "),f,_(" degrees Celsius.")
2011-06-09 10:54:03 +00:00
self.btemp.SetValue(l)
self.set("last_bed_temperature",str(f))
2011-06-09 10:54:03 +00:00
else:
2011-08-06 23:45:52 +00:00
print _("Printer is not online.")
2011-06-09 10:54:03 +00:00
else:
2011-08-06 23:45:52 +00:00
print _("You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0.")
2011-06-09 10:54:03 +00:00
except:
2011-08-06 23:45:52 +00:00
print _("You must enter a temperature.")
2011-06-09 10:54:03 +00:00
2011-07-26 14:34:55 +00:00
def end_macro(self):
pronsole.pronsole.end_macro(self)
self.update_macros_menu()
def delete_macro(self,macro_name):
pronsole.pronsole.delete_macro(self,macro_name)
self.update_macros_menu()
def start_macro(self,macro_name,old_macro_definition=""):
if not self.processing_rc:
def cb(definition):
2011-07-26 14:34:55 +00:00
if len(definition.strip())==0:
if old_macro_definition!="":
2011-08-06 23:45:52 +00:00
dialog = wx.MessageDialog(self,_("Do you want to erase the macro?"),style=wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
2011-07-26 14:34:55 +00:00
if dialog.ShowModal()==wx.ID_YES:
self.delete_macro(macro_name)
return
2011-08-06 23:45:52 +00:00
print _("Cancelled.")
2011-07-26 14:34:55 +00:00
return
self.cur_macro_name = macro_name
self.cur_macro_def = definition
self.end_macro()
2011-07-15 08:12:21 +00:00
macroed(macro_name,old_macro_definition,cb)
else:
pronsole.pronsole.start_macro(self,macro_name,old_macro_definition)
2011-06-09 10:54:03 +00:00
def catchprint(self,l):
wx.CallAfter(self.logbox.AppendText,l)
2011-06-08 14:19:38 +00:00
def scanserial(self):
"""scan for available ports. return a list of device names."""
baselist=[]
if os.name=="nt":
try:
key=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM")
i=0
while(1):
baselist+=[_winreg.EnumValue(key,i)[1]]
i+=1
except:
pass
return baselist+glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') +glob.glob("/dev/tty.*")+glob.glob("/dev/cu.*")+glob.glob("/dev/rfcomm*")
def popmenu(self):
self.menustrip = wx.MenuBar()
m = wx.Menu()
2011-08-06 23:45:52 +00:00
self.Bind(wx.EVT_MENU, self.loadfile, m.Append(-1,_("&Open..."),_(" Opens file")))
self.Bind(wx.EVT_MENU, self.do_editgcode, m.Append(-1,_("&Edit..."),_(" Edit open file")))
2011-07-20 08:23:07 +00:00
if sys.platform != 'darwin':
2011-08-06 23:45:52 +00:00
self.Bind(wx.EVT_MENU, lambda x:threading.Thread(target=lambda :self.do_skein("set")).start(), m.Append(-1,_("SFACT Settings"),_(" Adjust SFACT settings")))
2011-08-06 13:28:25 +00:00
try:
from SkeinforgeQuickEditDialog import SkeinforgeQuickEditDialog
2011-08-06 23:45:52 +00:00
self.Bind(wx.EVT_MENU, lambda *e:SkeinforgeQuickEditDialog(self), m.Append(-1,_("SFACT Quick Settings"),_(" Quickly adjust SFACT settings for active profile")))
2011-08-06 13:28:25 +00:00
except:
pass
2011-08-06 23:45:52 +00:00
self.Bind(wx.EVT_MENU, self.OnExit, m.Append(wx.ID_EXIT,_("E&xit"),_(" Closes the Window")))
self.menustrip.Append(m,_("&Print"))
2011-07-26 14:34:55 +00:00
m = wx.Menu()
self.macros_menu = wx.Menu()
2011-08-06 23:45:52 +00:00
m.AppendSubMenu(self.macros_menu, _("&Macros"))
self.Bind(wx.EVT_MENU, self.new_macro, self.macros_menu.Append(-1, _("<&New...>")))
self.Bind(wx.EVT_MENU, lambda *e:options(self), m.Append(-1,_("&Options"),_(" Options dialog")))
self.menustrip.Append(m,_("&Settings"))
2011-07-26 14:34:55 +00:00
self.update_macros_menu()
2011-06-08 14:19:38 +00:00
self.SetMenuBar(self.menustrip)
2011-08-06 13:28:25 +00:00
def doneediting(self,gcode):
f=open(self.filename,"w")
f.write("\n".join(gcode))
f.close()
wx.CallAfter(self.loadfile,None,self.filename)
def do_editgcode(self,e=None):
if(self.filename is not None):
macroed(self.filename,self.f,self.doneediting,1)
def new_macro(self,e=None):
2011-08-06 23:45:52 +00:00
dialog = wx.Dialog(self,-1,_("Enter macro name"),size=(200,100))
2011-07-26 14:34:55 +00:00
panel = wx.Panel(dialog,-1)
vbox = wx.BoxSizer(wx.VERTICAL)
2011-08-06 23:45:52 +00:00
wx.StaticText(panel,-1,_("Macro name:"),(8,14))
2011-07-26 14:34:55 +00:00
dialog.namectrl = wx.TextCtrl(panel,-1,'',(80,8),size=(100,24),style=wx.TE_PROCESS_ENTER)
hbox = wx.BoxSizer(wx.HORIZONTAL)
2011-08-06 23:45:52 +00:00
okb = wx.Button(dialog,wx.ID_OK,_("Ok"),size=(50,24))
dialog.Bind(wx.EVT_TEXT_ENTER,lambda e:dialog.EndModal(wx.ID_OK),dialog.namectrl)
#dialog.Bind(wx.EVT_BUTTON,lambda e:self.new_macro_named(dialog,e),okb)
2011-07-26 14:34:55 +00:00
hbox.Add(okb)
2011-08-06 23:45:52 +00:00
hbox.Add(wx.Button(dialog,wx.ID_CANCEL,_("Cancel"),size=(50,24)))
2011-07-26 14:34:55 +00:00
vbox.Add(panel)
vbox.Add(hbox,1,wx.ALIGN_CENTER|wx.TOP|wx.BOTTOM,10)
dialog.SetSizer(vbox)
dialog.Centre()
macro = ""
if dialog.ShowModal()==wx.ID_OK:
macro = dialog.namectrl.GetValue()
if macro != "":
wx.CallAfter(self.edit_macro,macro)
dialog.Destroy()
return macro
def edit_macro(self,macro):
if macro == "": return self.new_macro()
if self.macros.has_key(macro):
old_def = self.macros[macro]
elif hasattr(self.__class__,"do_"+macro):
2011-08-06 23:45:52 +00:00
print _("Name '")+macro+_("' is being used by built-in command")
return
elif len([c for c in macro if not c.isalnum() and c != "_"]):
print "Macro name may contain only alphanumeric symbols and underscores"
return
else:
old_def = ""
self.start_macro(macro,old_def)
return macro
2011-07-26 14:34:55 +00:00
def update_macros_menu(self):
if not hasattr(self,"macros_menu"):
return # too early, menu not yet built
try:
while True:
item = self.macros_menu.FindItemByPosition(1)
if item is None: return
self.macros_menu.DeleteItem(item)
except:
pass
for macro in self.macros.keys():
self.Bind(wx.EVT_MENU, lambda x,m=macro:self.start_macro(m,self.macros[m]), self.macros_menu.Append(-1, macro))
2011-06-08 14:19:38 +00:00
def OnExit(self, event):
self.Close()
def popwindow(self):
# this list will contain all controls that should be only enabled
# when we're connected to a printer
self.printerControls = []
2011-06-16 04:28:46 +00:00
#sizer layout: topsizer is a column sizer containing two sections
#upper section contains the mini view buttons
#lower section contains the rest of the window - manual controls, console, visualizations
#TOP ROW:
uts=self.uppertopsizer=wx.BoxSizer(wx.HORIZONTAL)
2011-08-06 23:45:52 +00:00
uts.Add(wx.StaticText(self.panel,-1,_("Port:"),pos=(0,5)),wx.TOP|wx.LEFT,5)
scan=self.scanserial()
2011-06-08 14:19:38 +00:00
self.serialport = wx.ComboBox(self.panel, -1,
choices=scan,
2011-06-09 17:21:13 +00:00
style=wx.CB_DROPDOWN|wx.CB_SORT, pos=(50,0))
try:
self.serialport.SetValue(scan[0])
if self.settings.port:
self.serialport.SetValue(self.settings.port)
except:
pass
2011-06-16 04:28:46 +00:00
uts.Add(self.serialport)
uts.Add(wx.StaticText(self.panel,-1,"@",pos=(250,5)),wx.RIGHT,5)
2011-06-08 14:19:38 +00:00
self.baud = wx.ComboBox(self.panel, -1,
choices=["2400", "9600", "19200", "38400", "57600", "115200"],
2011-06-16 04:28:46 +00:00
style=wx.CB_DROPDOWN|wx.CB_SORT, size=(110,30),pos=(275,0))
try:
self.baud.SetValue("115200")
self.baud.SetValue(str(self.settings.baudrate))
except:
pass
2011-06-16 04:28:46 +00:00
uts.Add(self.baud)
2011-08-06 23:45:52 +00:00
self.connectbtn=wx.Button(self.panel,-1,_("Connect"),pos=(380,0))
2011-06-16 04:28:46 +00:00
uts.Add(self.connectbtn)
2011-08-06 23:45:52 +00:00
self.connectbtn.SetToolTipString(_("Connect to the printer"))
2011-06-08 14:19:38 +00:00
self.connectbtn.Bind(wx.EVT_BUTTON,self.connect)
2011-08-06 23:45:52 +00:00
self.disconnectbtn=wx.Button(self.panel,-1,_("Disconnect"),pos=(470,0))
2011-06-08 14:19:38 +00:00
self.disconnectbtn.Bind(wx.EVT_BUTTON,self.disconnect)
self.printerControls.append(self.disconnectbtn)
2011-06-16 04:28:46 +00:00
uts.Add(self.disconnectbtn)
2011-08-06 23:45:52 +00:00
self.resetbtn=wx.Button(self.panel,-1,_("Reset"),pos=(560,0))
2011-06-08 14:19:38 +00:00
self.resetbtn.Bind(wx.EVT_BUTTON,self.reset)
2011-06-16 04:28:46 +00:00
uts.Add(self.resetbtn)
2011-08-06 23:45:52 +00:00
self.minibtn=wx.Button(self.panel,-1,_("Mini mode"),pos=(690,0))
2011-06-16 04:28:46 +00:00
self.minibtn.Bind(wx.EVT_BUTTON,self.toggleview)
uts.Add((10,-1))
self.monitorbox=wx.CheckBox(self.panel,-1,"",pos=(450,37))
uts.Add((15,-1))
uts.Add(self.monitorbox)
2011-08-06 23:45:52 +00:00
uts.Add(wx.StaticText(self.panel,-1,_("Monitor\nprinter"),pos=(470,37)))
self.monitorbox.Bind(wx.EVT_CHECKBOX,self.setmonitor)
uts.Add((15,-1),flag=wx.EXPAND)
2011-06-16 04:28:46 +00:00
uts.Add(self.minibtn)
#SECOND ROW
ubs=self.upperbottomsizer=wx.BoxSizer(wx.HORIZONTAL)
2011-08-06 23:45:52 +00:00
self.loadbtn=wx.Button(self.panel,-1,_("Load file"),pos=(0,40))
2011-06-08 14:19:38 +00:00
self.loadbtn.Bind(wx.EVT_BUTTON,self.loadfile)
2011-06-16 04:28:46 +00:00
ubs.Add(self.loadbtn)
2011-08-06 23:45:52 +00:00
self.uploadbtn=wx.Button(self.panel,-1,_("SD Upload"),pos=(90,40))
2011-06-08 14:19:38 +00:00
self.uploadbtn.Bind(wx.EVT_BUTTON,self.upload)
self.printerControls.append(self.uploadbtn)
2011-06-16 04:28:46 +00:00
ubs.Add(self.uploadbtn)
2011-08-06 23:45:52 +00:00
self.sdprintbtn=wx.Button(self.panel,-1,_("SD Print"),pos=(180,40))
2011-06-08 14:19:38 +00:00
self.sdprintbtn.Bind(wx.EVT_BUTTON,self.sdprintfile)
self.printerControls.append(self.sdprintbtn)
2011-06-16 04:28:46 +00:00
ubs.Add(self.sdprintbtn)
2011-08-06 23:45:52 +00:00
self.printbtn=wx.Button(self.panel,-1,_("Print"),pos=(270,40))
2011-06-16 04:28:46 +00:00
self.printbtn.Bind(wx.EVT_BUTTON,self.printfile)
self.printbtn.Disable()
2011-06-16 04:28:46 +00:00
ubs.Add(self.printbtn)
2011-08-06 23:45:52 +00:00
self.pausebtn=wx.Button(self.panel,-1,_("Pause"),pos=(360,40))
2011-06-16 04:28:46 +00:00
self.pausebtn.Bind(wx.EVT_BUTTON,self.pause)
ubs.Add(self.pausebtn)
ubs.Add((50,-1),flag=wx.EXPAND)
2011-06-16 04:28:46 +00:00
#Right full view
lrs=self.lowerrsizer=wx.BoxSizer(wx.VERTICAL)
self.logbox=wx.TextCtrl(self.panel,size=(350,340),pos=(440,75),style = wx.TE_MULTILINE)
self.logbox.SetEditable(0)
2011-06-16 04:28:46 +00:00
lrs.Add(self.logbox)
lbrs=wx.BoxSizer(wx.HORIZONTAL)
self.commandbox=wx.TextCtrl(self.panel,size=(250,30),pos=(440,420),style = wx.TE_PROCESS_ENTER)
self.commandbox.Bind(wx.EVT_TEXT_ENTER,self.sendline)
#self.printerControls.append(self.commandbox)
2011-06-16 04:28:46 +00:00
lbrs.Add(self.commandbox)
2011-08-06 23:45:52 +00:00
self.sendbtn=wx.Button(self.panel,-1,_("Send"),pos=(700,420))
2011-06-08 14:19:38 +00:00
self.sendbtn.Bind(wx.EVT_BUTTON,self.sendline)
#self.printerControls.append(self.sendbtn)
2011-06-16 04:28:46 +00:00
lbrs.Add(self.sendbtn)
lrs.Add(lbrs)
#left pane
lls=self.lowerlsizer=wx.GridBagSizer()
2011-08-06 23:45:52 +00:00
lls.Add(wx.StaticText(self.panel,-1,_("mm/min"),pos=(60,69)),pos=(0,4),span=(1,4))
self.xyfeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.xy_feedrate),min=0,max=50000,size=(70,25),pos=(25,83))
2011-08-06 23:45:52 +00:00
lls.Add(wx.StaticText(self.panel,-1,_("XY:"),pos=(2,90-2)),pos=(1,0),span=(1,2))
2011-06-16 04:28:46 +00:00
lls.Add(self.xyfeedc,pos=(1,2),span=(1,4))
2011-08-06 23:45:52 +00:00
lls.Add(wx.StaticText(self.panel,-1,_("Z:"),pos=(90,90-2)),pos=(1,6),span=(1,2))
self.zfeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.z_feedrate),min=0,max=50000,size=(70,25),pos=(105,83))
2011-06-16 04:28:46 +00:00
lls.Add(self.zfeedc,pos=(1,8),span=(1,4))
#lls.Add((200,375))
for i in self.cpbuttons:
2011-06-16 04:28:46 +00:00
btn=wx.Button(self.panel,-1,i[0])#,size=(60,-1))
btn.SetBackgroundColour(i[3])
btn.SetForegroundColour("black")
btn.properties=i
btn.Bind(wx.EVT_BUTTON,self.procbutton)
self.btndict[i[1]]=btn
self.printerControls.append(btn)
2011-06-16 04:28:46 +00:00
lls.Add(btn,pos=i[2],span=i[4])
2011-08-06 23:45:52 +00:00
lls.Add(wx.StaticText(self.panel,-1,_("Heater:"),pos=(0,343)),pos=(11,0),span=(1,1))
htemp_choices=[self.temps[i]+" ("+i+")" for i in sorted(self.temps.keys(),key=lambda x:self.temps[x])]
if self.settings.last_temperature not in map(float,self.temps.values()):
htemp_choices = [str(self.settings.last_temperature)] + htemp_choices
2011-06-09 10:54:03 +00:00
self.htemp=wx.ComboBox(self.panel, -1,
choices=htemp_choices,style=wx.CB_DROPDOWN, size=(90,25),pos=(45,337))
2011-06-09 10:54:03 +00:00
self.htemp.SetValue("0")
2011-06-16 04:28:46 +00:00
lls.Add(self.htemp,pos=(11,1),span=(1,3))
2011-08-06 23:45:52 +00:00
self.settbtn=wx.Button(self.panel,-1,_("Set"),size=(38,-1),pos=(135,335))
2011-06-09 10:54:03 +00:00
self.settbtn.Bind(wx.EVT_BUTTON,self.do_settemp)
self.printerControls.append(self.settbtn)
2011-06-16 04:28:46 +00:00
lls.Add(self.settbtn,pos=(11,4),span=(1,2))
2011-08-06 23:45:52 +00:00
lls.Add(wx.StaticText(self.panel,-1,_("Bed:"),pos=(0,343)),pos=(12,0),span=(1,1))
btemp_choices=[self.bedtemps[i]+" ("+i+")" for i in sorted(self.bedtemps.keys(),key=lambda x:self.bedtemps[x])]
if self.settings.last_bed_temperature not in map(float,self.bedtemps.values()):
btemp_choices = [str(self.settings.last_bed_temperature)] + btemp_choices
2011-06-09 10:54:03 +00:00
self.btemp=wx.ComboBox(self.panel, -1,
choices=btemp_choices,style=wx.CB_DROPDOWN, size=(90,25),pos=(45,367))
2011-06-09 10:54:03 +00:00
self.btemp.SetValue("0")
2011-06-16 04:28:46 +00:00
lls.Add(self.btemp,pos=(12,1),span=(1,3))
2011-08-06 23:45:52 +00:00
self.setbbtn=wx.Button(self.panel,-1,_("Set"),size=(38,-1),pos=(135,365))
2011-06-09 10:54:03 +00:00
self.setbbtn.Bind(wx.EVT_BUTTON,self.do_bedtemp)
self.printerControls.append(self.setbbtn)
2011-06-16 04:28:46 +00:00
lls.Add(self.setbbtn,pos=(12,4),span=(1,2))
self.tempdisp=wx.StaticText(self.panel,-1,"")
lls.Add(self.tempdisp,pos=(12,6),span=(1,3))
2011-06-09 10:54:03 +00:00
2011-06-09 16:44:57 +00:00
self.edist=wx.SpinCtrl(self.panel,-1,"5",min=0,max=1000,size=(60,25),pos=(70,398))
self.edist.SetBackgroundColour((225,200,200))
self.edist.SetForegroundColour("black")
2011-06-16 04:28:46 +00:00
lls.Add(self.edist,pos=(13,3),span=(1,2))
2011-08-06 23:45:52 +00:00
lls.Add(wx.StaticText(self.panel,-1,_("mm"),pos=(130,407)),pos=(13,5),span=(1,2))
self.efeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.e_feedrate),min=0,max=50000,size=(60,25),pos=(70,397+28))
2011-06-09 16:44:57 +00:00
self.efeedc.SetBackgroundColour((225,200,200))
self.efeedc.SetForegroundColour("black")
self.efeedc.Bind(wx.EVT_SPINCTRL,self.setfeeds)
2011-06-16 04:28:46 +00:00
lls.Add(self.efeedc,pos=(14,3),span=(1,2))
2011-08-06 23:45:52 +00:00
lls.Add(wx.StaticText(self.panel,-1,_("mm/min"),pos=(130,407+27)),pos=(14,5),span=(1,2))
2011-06-09 16:44:57 +00:00
self.xyfeedc.Bind(wx.EVT_SPINCTRL,self.setfeeds)
self.zfeedc.Bind(wx.EVT_SPINCTRL,self.setfeeds)
self.zfeedc.SetBackgroundColour((180,255,180))
self.zfeedc.SetForegroundColour("black")
2011-06-21 16:52:11 +00:00
lls.Add((10,0),pos=(0,11),span=(1,1))
2011-08-07 20:00:13 +00:00
self.gviz=gviz.gviz(self.panel,(300,300),
bedsize=(self.settings.bed_size_x,self.settings.bed_size_y),
2011-08-07 20:11:35 +00:00
grid=(self.settings.preview_grid_step1,self.settings.preview_grid_step2),
extrusion_width=self.settings.preview_extrusion_width)
self.gviz.showall=1
2011-08-07 20:00:13 +00:00
self.gwindow=gviz.window([],
bedsize=(self.settings.bed_size_x,self.settings.bed_size_y),
2011-08-07 20:11:35 +00:00
grid=(self.settings.preview_grid_step1,self.settings.preview_grid_step2),
extrusion_width=self.settings.preview_extrusion_width)
self.gviz.Bind(wx.EVT_LEFT_DOWN,self.showwin)
self.gwindow.Bind(wx.EVT_CLOSE,lambda x:self.gwindow.Hide())
2011-08-03 11:26:16 +00:00
cs=self.centersizer=wx.GridBagSizer()
cs.Add(self.gviz,pos=(0,0),span=(1,3))
lls.Add(cs,pos=(0,10),span=(15,1))
2011-06-16 04:28:46 +00:00
self.uppersizer=wx.BoxSizer(wx.VERTICAL)
self.uppersizer.Add(self.uppertopsizer)
self.uppersizer.Add(self.upperbottomsizer)
self.lowersizer=wx.BoxSizer(wx.HORIZONTAL)
self.lowersizer.Add(lls)
self.lowersizer.Add(lrs)
self.topsizer=wx.BoxSizer(wx.VERTICAL)
self.topsizer.Add(self.uppersizer)
self.topsizer.Add(self.lowersizer)
self.panel.SetSizer(self.topsizer)
self.status=self.CreateStatusBar()
2011-08-06 23:45:52 +00:00
self.status.SetStatusText(_("Not connected to printer."))
2011-08-03 11:26:16 +00:00
self.panel.Bind(wx.EVT_MOUSE_EVENTS,self.editbutton)
2011-06-16 04:28:46 +00:00
self.Bind(wx.EVT_CLOSE, self.kill)
self.topsizer.Layout()
self.topsizer.Fit(self)
# disable all printer controls until we connect to a printer
self.pausebtn.Disable()
for i in self.printerControls:
i.Disable()
2011-06-16 04:28:46 +00:00
#self.panel.Fit()
#uts.Layout()
2011-08-03 11:26:16 +00:00
self.cbuttons_reload()
2011-06-16 04:28:46 +00:00
def showwin(self,event):
if(self.f is not None):
self.gwindow.Show()
2011-06-08 14:19:38 +00:00
2011-06-09 16:44:57 +00:00
def setfeeds(self,e):
2011-06-29 21:31:57 +00:00
self.feedrates_changed = True
2011-06-09 16:44:57 +00:00
try:
self.settings._set("e_feedrate",self.efeedc.GetValue())
2011-06-09 16:44:57 +00:00
except:
pass
try:
self.settings._set("z_feedrate",self.zfeedc.GetValue())
2011-06-09 16:44:57 +00:00
except:
pass
try:
self.settings._set("xy_feedrate",self.xyfeedc.GetValue())
2011-06-09 16:44:57 +00:00
except:
pass
def toggleview(self,e):
if(self.mini):
self.mini=False
2011-06-16 04:28:46 +00:00
self.topsizer.Fit(self)
#self.SetSize(winsize)
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.minibtn.SetLabel, _("Mini mode"))
else:
self.mini=True
2011-06-16 04:28:46 +00:00
self.uppersizer.Fit(self)
#self.SetSize(winssize)
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.minibtn.SetLabel, _("Full mode"))
2011-08-03 11:26:16 +00:00
def cbuttons_reload(self):
allcbs = []
ubs=self.upperbottomsizer
cs=self.centersizer
for item in ubs.GetChildren():
if hasattr(item.GetWindow(),"custombutton"):
allcbs += [(ubs,item.GetWindow())]
for item in cs.GetChildren():
if hasattr(item.GetWindow(),"custombutton"):
allcbs += [(cs,item.GetWindow())]
for sizer,button in allcbs:
#sizer.Remove(button)
button.Destroy()
for i in xrange(len(self.custombuttons)):
btndef = self.custombuttons[i]
try:
b=wx.Button(self.panel,-1,btndef[0])
if len(btndef)>2:
b.SetBackgroundColour(btndef[2])
rr,gg,bb=b.GetBackgroundColour().Get()
if 0.3*rr+0.59*gg+0.11*bb < 60:
b.SetForegroundColour("#ffffff")
except:
b=wx.Button(self.panel,-1,"")
b.Freeze()
b.custombutton=i
b.properties=btndef
b.Bind(wx.EVT_BUTTON,self.procbutton)
b.Bind(wx.EVT_MOUSE_EVENTS,self.editbutton)
if i<4:
ubs.Add(b)
else:
cs.Add(b,pos=(1+(i-4)/3,(i-4)%3),span=(1,1))
self.topsizer.Layout()
def help_button(self):
2011-08-06 23:45:52 +00:00
print _('Defines custom button. Usage: button <num> "title" [/c "colour"] command')
2011-08-03 11:26:16 +00:00
def do_button(self,argstr):
def nextarg(rest):
rest=rest.lstrip()
if rest.startswith('"'):
return rest[1:].split('"',1)
else:
return rest.split(None,1)
#try:
num,argstr=nextarg(argstr)
num=int(num)
title,argstr=nextarg(argstr)
colour=None
try:
c1,c2=nextarg(argstr)
if c1=="/c":
colour,argstr=nextarg(c2)
except:
pass
command=argstr.strip()
if num<0 or num>=64:
2011-08-06 23:45:52 +00:00
print _("Custom button number should be between 0 and 63")
2011-08-03 11:26:16 +00:00
return
while num >= len(self.custombuttons):
self.custombuttons+=[None]
self.custombuttons[num]=[title,command]
if colour is not None:
self.custombuttons[num]+=[colour]
if not self.processing_rc:
self.cbuttons_reload()
#except Exception,x:
# print "Bad syntax for button definition, see 'help button'"
# print x
2011-08-03 11:26:16 +00:00
def cbutton_save(self,n,bdef,new_n=None):
if new_n is None: new_n=n
if bdef is None or bdef == "":
self.save_in_rc(("button %d" % n),'')
elif len(bdef)>2:
colour=bdef[2]
if type(colour) not in (str,unicode):
#print type(colour),map(type,colour)
if type(colour)==tuple and tuple(map(type,colour))==(int,int,int):
colour = map(lambda x:x%256,colour)
colour = wx.Colour(*colour).GetAsString(wx.C2S_NAME|wx.C2S_HTML_SYNTAX)
else:
colour = wx.Colour(colour).GetAsString(wx.C2S_NAME|wx.C2S_HTML_SYNTAX)
2011-08-03 11:26:16 +00:00
self.save_in_rc(("button %d" % n),'button %d "%s" /c "%s" %s' % (new_n,bdef[0],colour,bdef[1]))
else:
self.save_in_rc(("button %d" % n),'button %d "%s" %s' % (new_n,bdef[0],bdef[1]))
def cbutton_edit(self,e,button=None):
bedit=ButtonEdit(self)
if button is not None:
n = button.custombutton
bedit.name.SetValue(button.properties[0])
bedit.command.SetValue(button.properties[1])
if len(button.properties)>2:
colour=button.properties[2]
if type(colour) not in (str,unicode):
#print type(colour)
if type(colour)==tuple and tuple(map(type,colour))==(int,int,int):
colour = map(lambda x:x%256,colour)
colour = wx.Colour(*colour).GetAsString(wx.C2S_NAME|wx.C2S_HTML_SYNTAX)
else:
colour = wx.Colour(colour).GetAsString(wx.C2S_NAME|wx.C2S_HTML_SYNTAX)
2011-08-03 11:26:16 +00:00
bedit.color.SetValue(colour)
else:
n = len(self.custombuttons)
if bedit.ShowModal()==wx.ID_OK:
if n==len(self.custombuttons):
self.custombuttons+=[None]
self.custombuttons[n]=[bedit.name.GetValue().strip(),bedit.command.GetValue().strip()]
if bedit.color.GetValue().strip()!="":
self.custombuttons[n]+=[bedit.color.GetValue()]
self.cbutton_save(n,self.custombuttons[n])
bedit.Destroy()
self.cbuttons_reload()
def cbutton_remove(self,e,button):
n = button.custombutton
self.custombuttons[n]=None
self.cbutton_save(n,None)
while self.custombuttons[-1] is None:
del self.custombuttons[-1]
self.cbuttons_reload()
def cbutton_order(self,e,button,dir):
n = button.custombutton
if dir<0:
n=n-1
if n+1 >= len(self.custombuttons):
self.custombuttons+=[None] # pad
# swap
self.custombuttons[n],self.custombuttons[n+1] = self.custombuttons[n+1],self.custombuttons[n]
self.cbutton_save(n,self.custombuttons[n])
self.cbutton_save(n+1,self.custombuttons[n+1])
if self.custombuttons[-1] is None:
del self.custombuttons[-1]
self.cbuttons_reload()
def editbutton(self,e):
if e.IsCommandEvent() or e.ButtonUp(wx.MOUSE_BTN_RIGHT):
if e.IsCommandEvent():
pos = (0,0)
else:
pos = e.GetPosition()
2011-08-03 11:26:16 +00:00
popupmenu = wx.Menu()
obj = e.GetEventObject()
if hasattr(obj,"custombutton"):
2011-08-06 23:45:52 +00:00
item = popupmenu.Append(-1,_("Edit custom button '%s'") % e.GetEventObject().GetLabelText())
2011-08-03 11:26:16 +00:00
self.Bind(wx.EVT_MENU,lambda e,button=e.GetEventObject():self.cbutton_edit(e,button),item)
2011-08-06 23:45:52 +00:00
item = popupmenu.Append(-1,_("Move left <<"))
2011-08-03 11:26:16 +00:00
self.Bind(wx.EVT_MENU,lambda e,button=e.GetEventObject():self.cbutton_order(e,button,-1),item)
if obj.custombutton == 0: item.Enable(False)
2011-08-06 23:45:52 +00:00
item = popupmenu.Append(-1,_("Move right >>"))
2011-08-03 11:26:16 +00:00
self.Bind(wx.EVT_MENU,lambda e,button=e.GetEventObject():self.cbutton_order(e,button,1),item)
if obj.custombutton == 63: item.Enable(False)
pos = self.panel.ScreenToClient(e.GetEventObject().ClientToScreen(pos))
2011-08-06 23:45:52 +00:00
item = popupmenu.Append(-1,_("Remove custom button '%s'") % e.GetEventObject().GetLabelText())
2011-08-03 11:26:16 +00:00
self.Bind(wx.EVT_MENU,lambda e,button=e.GetEventObject():self.cbutton_remove(e,button),item)
else:
2011-08-06 23:45:52 +00:00
item = popupmenu.Append(-1,_("Add custom button"))
2011-08-03 11:26:16 +00:00
self.Bind(wx.EVT_MENU,self.cbutton_edit,item)
self.panel.PopupMenu(popupmenu, pos)
else:
e.Skip()
def procbutton(self,e):
try:
if hasattr(e.GetEventObject(),"custombutton"):
2011-08-04 19:28:34 +00:00
if wx.GetKeyState(wx.WXK_CONTROL) or wx.GetKeyState(wx.WXK_ALT):
return self.editbutton(e)
self.cur_button=e.GetEventObject().custombutton
self.onecmd(e.GetEventObject().properties[1])
self.cur_button=None
except:
2011-08-06 23:45:52 +00:00
print _("event object missing")
self.cur_button=None
raise
2011-06-08 14:19:38 +00:00
def kill(self,e):
self.statuscheck=0
self.p.recvcb=None
self.p.disconnect()
2011-06-29 21:31:57 +00:00
if hasattr(self,"feedrates_changed"):
self.save_in_rc("set xy_feedrate","set xy_feedrate %d" % self.settings.xy_feedrate)
self.save_in_rc("set z_feedrate","set z_feedrate %d" % self.settings.z_feedrate)
self.save_in_rc("set e_feedrate","set e_feedrate %d" % self.settings.e_feedrate)
try:
self.gwindow.Destroy()
except:
pass
2011-06-08 14:19:38 +00:00
self.Destroy()
def do_monitor(self,l=""):
if l.strip()=="":
self.monitorbox.SetValue(not self.monitorbox.GetValue())
elif l.strip()=="off":
self.monitorbox.SetValue(False)
else:
try:
self.monitor_interval=float(l)
self.monitorbox.SetValue(self.monitor_interval>0)
except:
2011-08-06 23:45:52 +00:00
print _("Invalid period given.")
self.setmonitor(None)
if self.monitor:
2011-08-06 23:45:52 +00:00
print _("Monitoring printer.")
else:
2011-08-06 23:45:52 +00:00
print _("Done monitoring.")
2011-06-08 14:19:38 +00:00
def setmonitor(self,e):
self.monitor=self.monitorbox.GetValue()
def sendline(self,e):
command=self.commandbox.GetValue()
if not len(command):
return
wx.CallAfter(self.logbox.AppendText,">>>"+command+"\n")
2011-06-11 21:03:01 +00:00
self.onecmd(str(command))
self.commandbox.SetSelection(0,len(command))
2011-06-08 14:19:38 +00:00
def statuschecker(self):
try:
while(self.statuscheck):
string=""
if(self.p.online):
2011-08-06 23:45:52 +00:00
string+=_("Printer is online. ")
try:
2011-08-06 23:45:52 +00:00
string+=_("Loaded ")+os.path.split(self.filename)[1]+" "
except:
pass
2011-08-06 23:45:52 +00:00
string+=(self.tempreport.replace("\r","").replace("T",_("Hotend")).replace("B",_("Bed")).replace("\n","").replace("ok ",""))+" "
wx.CallAfter(self.tempdisp.SetLabel,self.tempreport.strip().replace("ok ",""))
2011-06-08 14:19:38 +00:00
if self.sdprinting:
2011-08-06 23:45:52 +00:00
string+= _(" SD printing:%04.2f %%") % (self.percentdone,)
2011-06-08 14:19:38 +00:00
if self.p.printing:
2011-08-06 23:45:52 +00:00
string+= _(" Printing:%04.2f %%") % (100*float(self.p.queueindex)/len(self.p.mainqueue),)
2011-06-08 14:19:38 +00:00
wx.CallAfter(self.status.SetStatusText,string)
2011-06-21 16:52:11 +00:00
wx.CallAfter(self.gviz.Refresh)
2011-06-08 14:19:38 +00:00
if(self.monitor and self.p.online):
if self.sdprinting:
self.p.send_now("M27")
self.p.send_now("M105")
time.sleep(self.monitor_interval)
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.status.SetStatusText,_("Not connected to printer."))
2011-06-08 14:19:38 +00:00
except:
pass #if window has been closed
def capture(self, func, *args, **kwargs):
stdout=sys.stdout
cout=None
try:
cout=self.cout
except:
pass
if cout is None:
cout=cStringIO.StringIO()
sys.stdout=cout
retval=None
try:
retval=func(*args,**kwargs)
except:
traceback.print_exc()
sys.stdout=stdout
return retval
def recvcb(self,l):
if "T:" in l:
self.tempreport=l
wx.CallAfter(self.tempdisp.SetLabel,self.tempreport.strip().replace("ok ",""))
tstring=l.rstrip()
#print tstring
if(tstring!="ok"):
print tstring
#wx.CallAfter(self.logbox.AppendText,tstring+"\n")
2011-06-08 14:19:38 +00:00
for i in self.recvlisteners:
i(l)
def listfiles(self,line):
if "Begin file list" in line:
self.listing=1
elif "End file list" in line:
self.listing=0
self.recvlisteners.remove(self.listfiles)
wx.CallAfter(self.filesloaded)
elif self.listing:
self.sdfiles+=[line.replace("\n","").replace("\r","").lower()]
def waitforsdresponse(self,l):
if "file.open failed" in l:
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.status.SetStatusText,_("Opening file failed."))
2011-06-08 14:19:38 +00:00
self.recvlisteners.remove(self.waitforsdresponse)
return
if "File opened" in l:
wx.CallAfter(self.status.SetStatusText,l)
if "File selected" in l:
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.status.SetStatusText,_("Starting print"))
2011-06-08 14:19:38 +00:00
self.sdprinting=1
self.p.send_now("M24")
self.startcb()
2011-06-08 14:19:38 +00:00
return
if "Done printing file" in l:
wx.CallAfter(self.status.SetStatusText,l)
self.sdprinting=0
self.recvlisteners.remove(self.waitforsdresponse)
self.endcb()
2011-06-08 14:19:38 +00:00
return
if "SD printing byte" in l:
#M27 handler
try:
resp=l.split()
vals=resp[-1].split("/")
self.percentdone=100.0*int(vals[0])/int(vals[1])
except:
pass
def filesloaded(self):
2011-08-06 23:45:52 +00:00
dlg=wx.SingleChoiceDialog(self, _("Select the file to print"), _("Pick SD file"), self.sdfiles)
if(dlg.ShowModal()==wx.ID_OK):
2011-06-08 14:19:38 +00:00
target=dlg.GetStringSelection()
if len(target):
self.recvlisteners+=[self.waitforsdresponse]
self.p.send_now("M23 "+target.lower())
#print self.sdfiles
pass
def getfiles(self):
if not self.p.online:
self.sdfiles=[]
return
self.listing=0
self.sdfiles=[]
self.recvlisteners+=[self.listfiles]
self.p.send_now("M20")
def skein_func(self):
try:
from skeinforge.skeinforge_application.skeinforge_utilities import skeinforge_craft
from skeinforge.skeinforge_application import skeinforge
from skeinforge.fabmetheus_utilities import settings
skeinforge_craft.writeOutput(self.filename,False)
2011-06-08 14:19:38 +00:00
#print len(self.cout.getvalue().split())
self.stopsf=1
except:
2011-08-06 23:45:52 +00:00
print _("Skeinforge execution failed.")
2011-06-08 14:19:38 +00:00
self.stopsf=1
traceback.print_exc(file=sys.stdout)
2011-06-08 14:19:38 +00:00
def skein_monitor(self):
while(not self.stopsf):
try:
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.status.SetStatusText,_("Skeining..."))#+self.cout.getvalue().split("\n")[-1])
2011-06-08 14:19:38 +00:00
except:
pass
time.sleep(0.1)
fn=self.filename
try:
self.filename=self.filename.replace(".stl","_export.gcode").replace(".STL","_export.gcode")
of=open(self.filename)
self.f=[i.replace("\n","").replace("\r","") for i in of]
of.close
if self.p.online:
wx.CallAfter(self.printbtn.Enable)
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.status.SetStatusText,_("Loaded ")+self.filename+_(", %d lines") % (len(self.f),))
wx.CallAfter(self.pausebtn.Disable)
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.printbtn.SetLabel,_("Print"))
2011-06-21 16:52:11 +00:00
threading.Thread(target=self.loadviz).start()
2011-06-08 14:19:38 +00:00
except:
self.filename=fn
def skein(self,filename):
2011-08-06 23:45:52 +00:00
print _("Skeining ") + filename
2011-06-08 14:19:38 +00:00
if not os.path.exists("skeinforge"):
2011-08-06 23:45:52 +00:00
print _("Skeinforge not found. \nPlease copy Skeinforge into a directory named \"skeinforge\" in the same directory as this file.")
2011-06-08 14:19:38 +00:00
return
if not os.path.exists("skeinforge/__init__.py"):
f=open("skeinforge/__init__.py","w")
f.close()
2011-06-08 14:19:38 +00:00
self.cout=StringIO.StringIO()
self.filename=filename
self.stopsf=0
thread(target=self.skein_func).start()
thread(target=self.skein_monitor).start()
2011-08-06 13:28:25 +00:00
def loadfile(self,event,filename=None):
2011-06-29 21:32:24 +00:00
basedir=self.settings.last_file_path
if not os.path.exists(basedir):
basedir = "."
try:
basedir=os.path.split(self.filename)[0]
except:
pass
2011-08-06 23:45:52 +00:00
dlg=wx.FileDialog(self,_("Open file to print"),basedir,style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
dlg.SetWildcard(_("STL and GCODE files (;*.gcode;*.g;*.stl;*.STL;)"))
2011-08-06 13:28:25 +00:00
if(filename is not None or dlg.ShowModal() == wx.ID_OK):
if filename is not None:
name=filename
else:
name=dlg.GetPath()
2011-06-08 14:19:38 +00:00
if not(os.path.exists(name)):
2011-08-06 23:45:52 +00:00
self.status.SetStatusText(_("File not found!"))
2011-06-08 14:19:38 +00:00
return
2011-06-29 21:32:24 +00:00
path = os.path.split(name)[0]
if path != self.settings.last_file_path:
self.set("last_file_path",path)
if name.lower().endswith(".stl"):
2011-06-08 14:19:38 +00:00
self.skein(name)
else:
self.filename=name
of=open(self.filename)
self.f=[i.replace("\n","").replace("\r","") for i in of]
of.close
2011-08-06 23:45:52 +00:00
self.status.SetStatusText(_("Loaded ") + name + _(", %d lines") % (len(self.f),))
wx.CallAfter(self.printbtn.SetLabel, _("Print"))
wx.CallAfter(self.pausebtn.SetLabel, _("Pause"))
wx.CallAfter(self.pausebtn.Disable)
if self.p.online:
wx.CallAfter(self.printbtn.Enable)
2011-06-21 16:52:11 +00:00
threading.Thread(target=self.loadviz).start()
def loadviz(self):
2011-08-27 07:15:22 +00:00
Xtot,Ytot,Ztot,Xmin,Xmax,Ymin,Ymax,Zmin,Zmax = pronsole.measurements(self.f)
2011-08-27 06:45:35 +00:00
print pronsole.totalelength(self.f), _("mm of filament used in this print\n")
Xtot,Ytot,Ztot= pronsole.measurements(self.f)
2011-08-27 07:26:07 +00:00
print ("the print goes from"),Xmin,("mm to"),Xmax,("mm in X\nand is"),Xtot,("mm wide\n")
print ("the print goes from"),Ymin,("mm to"),Ymax,("mm in Y\nand is"),Ytot,("mm wide\n")
print ("the print goes from"),Zmin,("mm to"),Zmax,("mm in Z\nand is"),Ztot,("mm high\n")
2011-06-21 16:52:11 +00:00
self.gviz.clear()
self.gwindow.p.clear()
2011-06-21 16:52:11 +00:00
for i in self.f:
self.gviz.addgcode(i)
self.gwindow.p.addgcode(i)
2011-06-21 16:52:11 +00:00
self.gviz.showall=1
wx.CallAfter(self.gviz.Refresh)
2011-06-08 14:19:38 +00:00
def printfile(self,event):
2011-06-10 18:34:04 +00:00
if self.paused:
self.p.paused=0
self.paused=0
self.on_startprint()
2011-06-10 18:34:04 +00:00
if self.sdprinting:
self.p.send_now("M26 S0")
self.p.send_now("M24")
return
2011-06-08 14:19:38 +00:00
if self.f is None or not len(self.f):
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.status.SetStatusText, _("No file loaded. Please use load first."))
2011-06-08 14:19:38 +00:00
return
if not self.p.online:
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.status.SetStatusText,_("Not connected to printer."))
2011-06-08 14:19:38 +00:00
return
2011-07-09 14:07:17 +00:00
self.on_startprint()
2011-06-08 14:19:38 +00:00
self.p.startprint(self.f)
def on_startprint(self):
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.pausebtn.SetLabel, _("Pause"))
wx.CallAfter(self.pausebtn.Enable)
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.printbtn.SetLabel, _("Restart"))
2011-06-08 22:02:00 +00:00
def endupload(self):
self.p.send_now("M29 ")
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.status.SetStatusText, _("File upload complete"))
2011-06-08 22:02:00 +00:00
time.sleep(0.5)
self.p.clear=True
self.uploading=False
def uploadtrigger(self,l):
if "Writing to file" in l:
self.uploading=True
self.p.startprint(self.f)
self.p.endcb=self.endupload
self.recvlisteners.remove(self.uploadtrigger)
elif "open failed, File" in l:
self.recvlisteners.remove(self.uploadtrigger)
2011-06-08 14:19:38 +00:00
def upload(self,event):
2011-06-08 22:02:00 +00:00
if not len(self.f):
return
if not self.p.online:
return
2011-08-06 23:45:52 +00:00
dlg=wx.TextEntryDialog(self, ("Enter a target filename in 8.3 format:"), _("Pick SD filename") ,dosify(self.filename))
2011-06-08 22:02:00 +00:00
if dlg.ShowModal()==wx.ID_OK:
2011-06-11 21:03:01 +00:00
self.p.send_now("M28 "+str(dlg.GetValue()))
2011-06-08 22:02:00 +00:00
self.recvlisteners+=[self.uploadtrigger]
2011-06-08 14:19:38 +00:00
pass
def pause(self,event):
if not self.paused:
if self.sdprinting:
self.p.send_now("M25")
else:
if(not self.p.printing):
#print "Not printing, cannot pause."
return
self.p.pause()
self.paused=True
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.pausebtn.SetLabel, _("Resume"))
2011-06-08 14:19:38 +00:00
else:
self.paused=False
if self.sdprinting:
self.p.send_now("M24")
else:
self.p.resume()
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.pausebtn.SetLabel, _("Pause"))
2011-06-08 14:19:38 +00:00
def sdprintfile(self,event):
self.on_startprint()
2011-06-08 14:19:38 +00:00
threading.Thread(target=self.getfiles).start()
pass
def connect(self,event):
port=None
try:
port=self.scanserial()[0]
except:
pass
if self.serialport.GetValue()!="":
2011-06-11 21:03:01 +00:00
port=str(self.serialport.GetValue())
2011-06-08 14:19:38 +00:00
baud=115200
try:
baud=int(self.baud.GetValue())
except:
pass
2011-06-10 18:34:04 +00:00
if self.paused:
self.p.paused=0
self.p.printing=0
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.pausebtn.SetLabel, _("Pause"))
wx.CallAfter(self.printbtn.SetLabel, _("Print"))
2011-06-10 18:34:04 +00:00
self.paused=0
if self.sdprinting:
self.p.send_now("M26 S0")
2011-06-08 14:19:38 +00:00
self.p.connect(port,baud)
self.statuscheck=True
if port != self.settings.port:
self.set("port",port)
if baud != self.settings.baudrate:
self.set("baudrate",str(baud))
2011-06-08 14:19:38 +00:00
threading.Thread(target=self.statuschecker).start()
2011-06-10 18:34:04 +00:00
2011-06-08 14:19:38 +00:00
def disconnect(self,event):
self.p.disconnect()
self.statuscheck=False
wx.CallAfter(self.connectbtn.Enable);
wx.CallAfter(self.printbtn.Disable);
wx.CallAfter(self.pausebtn.Disable);
for i in self.printerControls:
wx.CallAfter(i.Disable)
2011-06-10 18:34:04 +00:00
if self.paused:
self.p.paused=0
self.p.printing=0
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.pausebtn.SetLabel, _("Pause"))
wx.CallAfter(self.printbtn.SetLabel, _("Print"))
2011-06-10 18:34:04 +00:00
self.paused=0
if self.sdprinting:
self.p.send_now("M26 S0")
2011-06-08 14:19:38 +00:00
def reset(self,event):
2011-08-06 23:45:52 +00:00
dlg=wx.MessageDialog(self, _("Are you sure you want to reset the printer?"), _("Reset?"), wx.YES|wx.NO)
2011-06-08 14:19:38 +00:00
if dlg.ShowModal()==wx.ID_YES:
self.p.reset()
2011-06-10 18:34:04 +00:00
if self.paused:
self.p.paused=0
self.p.printing=0
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.pausebtn.SetLabel, _("Pause"))
wx.CallAfter(self.printbtn.SetLabel, _("Print"))
2011-06-10 18:34:04 +00:00
self.paused=0
class macroed(wx.Dialog):
"""Really simple editor to edit macro definitions"""
2011-08-06 13:28:25 +00:00
def __init__(self,macro_name,definition,callback,gcode=False):
self.indent_chars = " "
2011-08-06 13:28:25 +00:00
title=" macro %s"
if gcode:
title=" %s"
self.gcode=gcode
wx.Dialog.__init__(self,None,title=title % macro_name,style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
self.callback = callback
self.panel=wx.Panel(self,-1)
titlesizer=wx.BoxSizer(wx.HORIZONTAL)
2011-08-06 13:28:25 +00:00
title = wx.StaticText(self.panel,-1,title%macro_name)
title.SetFont(wx.Font(11,wx.NORMAL,wx.NORMAL,wx.BOLD))
titlesizer.Add(title,1)
2011-08-06 23:45:52 +00:00
self.okb = wx.Button(self.panel, -1, ("Save"))
self.okb.Bind(wx.EVT_BUTTON, self.save)
titlesizer.Add(self.okb)
2011-08-06 23:45:52 +00:00
self.cancelb = wx.Button(self.panel, -1, ("Cancel"))
self.cancelb.Bind(wx.EVT_BUTTON, self.close)
titlesizer.Add(self.cancelb)
topsizer=wx.BoxSizer(wx.VERTICAL)
topsizer.Add(titlesizer,0,wx.EXPAND)
self.e=wx.TextCtrl(self.panel,style=wx.TE_MULTILINE+wx.HSCROLL,size=(200,200))
2011-08-06 13:28:25 +00:00
if not self.gcode:
self.e.SetValue(self.unindent(definition))
else:
self.e.SetValue("\n".join(definition))
topsizer.Add(self.e,1,wx.ALL+wx.EXPAND)
self.panel.SetSizer(topsizer)
topsizer.Layout()
topsizer.Fit(self)
self.Show()
2011-07-26 14:34:55 +00:00
self.e.SetFocus()
def save(self,ev):
self.Destroy()
2011-08-06 13:28:25 +00:00
if not self.gcode:
self.callback(self.reindent(self.e.GetValue()))
else:
self.callback(self.e.GetValue().split("\n"))
def close(self,ev):
self.Destroy()
def unindent(self,text):
import re
self.indent_chars = text[:len(text)-len(text.lstrip())]
unindented = ""
2011-07-15 08:12:21 +00:00
lines = re.split(r"(?:\r\n?|\n)",text)
#print lines
if len(lines) <= 1:
return text
for line in lines:
if line.startswith(self.indent_chars):
unindented += line[len(self.indent_chars):] + "\n"
else:
unindented += line + "\n"
return unindented
def reindent(self,text):
2011-07-15 08:12:21 +00:00
import re
lines = re.split(r"(?:\r\n?|\n)",text)
if len(lines) <= 1:
return text
reindented = ""
for line in lines:
reindented += self.indent_chars + line + "\n"
return reindented
2011-06-08 14:19:38 +00:00
2011-07-26 16:19:45 +00:00
class options(wx.Dialog):
"""Options editor"""
def __init__(self,pronterface):
2011-08-06 23:45:52 +00:00
wx.Dialog.__init__(self, None, title=_("Edit settings"))
2011-07-26 16:19:45 +00:00
topsizer=wx.BoxSizer(wx.VERTICAL)
2011-08-06 23:45:52 +00:00
vbox=wx.StaticBoxSizer(wx.StaticBox(self, label=_("Defaults")) ,wx.VERTICAL)
2011-07-26 16:19:45 +00:00
topsizer.Add(vbox,1,wx.ALL+wx.EXPAND)
grid=wx.GridSizer(rows=0,cols=2,hgap=8,vgap=2)
vbox.Add(grid,0,wx.EXPAND)
ctrls = {}
for k,v in pronterface.settings._all_settings().items():
grid.Add(wx.StaticText(self,-1,k),0,wx.BOTTOM+wx.RIGHT)
ctrls[k] = wx.TextCtrl(self,-1,str(v))
grid.Add(ctrls[k],1,wx.EXPAND)
topsizer.Add(self.CreateSeparatedButtonSizer(wx.OK+wx.CANCEL),0,wx.EXPAND)
self.SetSizer(topsizer)
topsizer.Layout()
topsizer.Fit(self)
if self.ShowModal()==wx.ID_OK:
for k,v in pronterface.settings._all_settings().items():
if ctrls[k].GetValue() != str(v):
pronterface.set(k,str(ctrls[k].GetValue()))
self.Destroy()
2011-06-08 14:19:38 +00:00
2011-08-03 11:26:16 +00:00
class ButtonEdit(wx.Dialog):
"""Custom button edit dialog"""
def __init__(self,pronterface):
2011-08-06 23:45:52 +00:00
wx.Dialog.__init__(self, None, title=_("Custom button"),style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
self.pronterface=pronterface
2011-08-03 11:26:16 +00:00
topsizer=wx.BoxSizer(wx.VERTICAL)
vbox=wx.StaticBoxSizer(wx.StaticBox(self,label=""),wx.VERTICAL)
topsizer.Add(vbox,1,wx.ALL+wx.EXPAND)
grid=wx.FlexGridSizer(rows=0,cols=2,hgap=4,vgap=2)
grid.AddGrowableCol(1,1)
vbox.Add(grid,0,wx.EXPAND)
2011-08-06 23:45:52 +00:00
grid.Add(wx.StaticText(self,-1, _("Button title")), 0, wx.BOTTOM+wx.RIGHT)
2011-08-03 11:26:16 +00:00
self.name=wx.TextCtrl(self,-1,"")
grid.Add(self.name,1,wx.EXPAND)
2011-08-06 23:45:52 +00:00
grid.Add(wx.StaticText(self, -1, _("Command")), 0, wx.BOTTOM+wx.RIGHT)
2011-08-03 11:26:16 +00:00
self.command=wx.TextCtrl(self,-1,"")
xbox=wx.BoxSizer(wx.HORIZONTAL)
xbox.Add(self.command,1,wx.EXPAND)
self.command.Bind(wx.EVT_TEXT,self.macrob_enabler)
self.macrob=wx.Button(self,-1,"..",style=wx.BU_EXACTFIT)
self.macrob.Bind(wx.EVT_BUTTON,self.macrob_handler)
xbox.Add(self.macrob,0)
grid.Add(xbox)
2011-08-06 23:45:52 +00:00
grid.Add(wx.StaticText(self,-1, _("Color")),0,wx.BOTTOM+wx.RIGHT)
2011-08-03 11:26:16 +00:00
self.color=wx.TextCtrl(self,-1,"")
grid.Add(self.color,1,wx.EXPAND)
2011-08-03 11:26:16 +00:00
topsizer.Add(self.CreateSeparatedButtonSizer(wx.OK+wx.CANCEL),0,wx.EXPAND)
self.SetSizer(topsizer)
topsizer.Layout()
topsizer.Fit(self)
def macrob_enabler(self,e):
macro = self.command.GetValue()
valid = False
if macro == "":
valid = True
elif self.pronterface.macros.has_key(macro):
valid = True
elif hasattr(self.pronterface.__class__,"do_"+macro):
valid = False
elif len([c for c in macro if not c.isalnum() and c != "_"]):
valid = False
else:
valid = True
self.macrob.Enable(valid)
def macrob_handler(self,e):
macro = self.command.GetValue()
macro = self.pronterface.edit_macro(macro)
self.command.SetValue(macro)
if self.name.GetValue()=="":
self.name.SetValue(macro)
2011-08-03 11:26:16 +00:00
2011-06-08 14:19:38 +00:00
if __name__ == '__main__':
app = wx.App(False)
main = PronterWindow()
main.Show()
2011-06-16 04:28:46 +00:00
try:
app.MainLoop()
except:
pass