Printrun/pronterface.py

2071 lines
89 KiB
Python
Raw Normal View History

2011-06-08 14:19:38 +00:00
#!/usr/bin/env python
2012-01-23 11:36:49 +00:00
# This file is part of the Printrun suite.
#
2012-01-23 11:36:49 +00:00
# Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
2012-01-23 11:36:49 +00:00
# Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
2012-01-23 11:36:49 +00:00
# You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
2011-08-06 23:45:52 +00:00
import os, Queue, re
from printrun.printrun_utils import install_locale
install_locale('pronterface')
2011-08-06 23:45:52 +00:00
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 sys, glob, time, threading, traceback, cStringIO, subprocess
2011-11-18 08:52:16 +00:00
StringIO=cStringIO
2011-06-09 17:26:07 +00:00
winsize=(800,500)
2012-04-22 23:33:47 +00:00
layerindex=0
global buttonSize
buttonSize = (70, 25) # Define sizes for the buttons on top rows
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
from printrun import printcore, gviz
from printrun.xybuttons import XYButtons
from printrun.zbuttons import ZButtons
from printrun.graph import Graph
from printrun.printrun_utils import pixmapfile, configfile
import pronsole
2011-06-08 22:02:00 +00:00
def dosify(name):
return os.path.split(name)[1].split(".")[0][:8]+".g"
2012-08-02 16:26:56 +00:00
def parse_temperature_report(report, key):
return float(filter(lambda x: x.startswith(key), report.split())[0].split(":")[1].split("/")[0])
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):
try:
self.target(data)
except:
pass
self.stdout.write(data.encode("utf-8"))
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)
self.settings.build_dimensions = '200x200x100+0+0+0' #default build dimensions are 200x200x100 with 0,0,0 in the corner of the bed
self.settings.last_bed_temperature = 0.0
2011-06-29 21:32:24 +00:00
self.settings.last_file_path = ""
self.settings.last_temperature = 0.0
self.settings.preview_extrusion_width = 0.5
2011-08-07 20:00:13 +00:00
self.settings.preview_grid_step1 = 10.
self.settings.preview_grid_step2 = 50.
self.settings.bgcolor = "#FFFFFF"
self.helpdict["build_dimensions"] = _("Dimensions of Build Platform\n & optional offset of origin\n\nExamples:\n XXXxYYY\n XXX,YYY,ZZZ\n XXXxYYYxZZZ+OffX+OffY+OffZ")
self.helpdict["last_bed_temperature"] = _("Last Set Temperature for the Heated Print Bed")
self.helpdict["last_file_path"] = _("Folder of last opened file")
self.helpdict["last_temperature"] = _("Last Temperature of the Hot End")
self.helpdict["preview_extrusion_width"] = _("Width of Extrusion in Preview (default: 0.5)")
self.helpdict["preview_grid_step1"] = _("Fine Grid Spacing (default: 10)")
self.helpdict["preview_grid_step2"] = _("Coarse Grid Spacing (default: 50)")
self.helpdict["bgcolor"] = _("Pronterface background color (default: #FFFFFF)")
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(pixmapfile("P-face.ico"),wx.BITMAP_TYPE_ICO))
2011-06-08 14:19:38 +00:00
self.panel=wx.Panel(self,-1,size=size)
2011-06-08 14:19:38 +00:00
self.statuscheck=False
self.capture_skip={}
self.capture_skip_newline=False
2011-06-08 14:19:38 +00:00
self.tempreport=""
self.monitor=0
self.f=None
2011-11-18 08:52:16 +00:00
self.skeinp=None
self.monitor_interval=3
2011-06-08 14:19:38 +00:00
self.paused=False
self.sentlines=Queue.Queue(30)
2011-06-09 19:43:42 +00:00
xcol=(245,245,108)
ycol=(180,180,255)
zcol=(180,255,180)
self.cpbuttons=[
[_("Motors off"),("M84"),None,(250,250,250),0, _("Switch all motors off")],
[_("Check temp"),("M105"),(2,5),(225,200,200),(1,1), _("Check current hotend temperature")],
[_("Extrude"),("extrude"),(4,0),(225,200,200),(1,2), _("Advance extruder by set length")],
[_("Reverse"),("reverse"),(5,0),(225,200,200),(1,2), _("Reverse extruder by set length")],
]
self.custombuttons=[]
self.btndict={}
self.parse_cmdline(sys.argv[1:])
2011-12-11 09:11:47 +00:00
self.build_dimensions_list = self.get_build_dimensions(self.settings.build_dimensions)
self.panel.SetBackgroundColour(self.settings.bgcolor)
customdict={}
try:
execfile(configfile("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
2011-11-18 08:52:16 +00:00
self.skeining=0
self.mini=False
self.p.sendcb=self.sentcb
self.p.startcb=self.startcb
self.p.endcb=self.endcb
self.starttime=0
self.extra_print_time=0
2011-06-22 11:40:27 +00:00
self.curlayer=0
self.cur_button=None
self.hsetpoint=0.0
self.bsetpoint=0.0
self.webInterface=None
if self.webrequested:
try :
import cherrypy
from printrun import webinterface
except:
print _("CherryPy is not installed. Web Interface Disabled.")
try:
self.webInterface=webinterface.WebInterface(self)
self.webThread=threading.Thread(target=webinterface.StartWebInterfaceThread, args=(self.webInterface, ))
self.webThread.start()
except:
print _("Failed to start web interface")
traceback.print_exc(file = sys.stdout)
self.webInterface = None
def startcb(self):
self.starttime=time.time()
print "Print Started at: " +time.strftime('%H:%M:%S',time.localtime(self.starttime))
def endcb(self):
if(self.p.queueindex==0):
print "Print ended at: " +time.strftime('%H:%M:%S',time.localtime(time.time()))
print "and took: "+time.strftime('%H:%M:%S', time.gmtime(int(time.time()-self.starttime+self.extra_print_time))) #+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"))
import shlex
param = self.settings.final_command
pararray=[i.replace("$s",str(self.filename)).replace("$t", str(time.strftime('%H:%M:%S', time.gmtime(int(time.time()-self.starttime+self.extra_print_time))))).encode() for i in shlex.split(param.replace("\\","\\\\").encode())]
self.finalp=subprocess.Popen(pararray,stderr=subprocess.STDOUT,stdout=subprocess.PIPE)
def online(self):
print _("Printer is now online.")
2012-02-26 01:08:57 +00:00
self.connectbtn.SetLabel(_("Disconnect"))
self.connectbtn.SetToolTip(wx.ToolTip("Disconnect from the printer"))
2011-12-04 01:17:19 +00:00
self.connectbtn.Bind(wx.EVT_BUTTON,self.disconnect)
for i in self.printerControls:
wx.CallAfter(i.Enable)
# Enable XYButtons and ZButtons
wx.CallAfter(self.xyb.enable)
wx.CallAfter(self.zb.enable)
if self.filename:
wx.CallAfter(self.printbtn.Enable)
def sentcb(self, line):
if "G1" in line:
if "Z" in line:
2011-06-22 11:40:27 +00:00
try:
layer = float(line.split("Z")[1].split()[0])
if layer != self.curlayer:
self.curlayer = layer
self.gviz.hilight = []
threading.Thread(target = wx.CallAfter, args = (self.gviz.setlayer, layer)).start()
2011-06-22 11:40:27 +00:00
except:
pass
try:
self.sentlines.put_nowait(line)
except:
pass
#threading.Thread(target=self.gviz.addgcode,args=(line,1)).start()
#self.gwindow.p.addgcode(line,hilight=1)
if "M104" in line or "M109" in line:
if "S" in line:
try:
temp = float(line.split("S")[1].split("*")[0])
2012-05-04 04:40:19 +00:00
#self.hottgauge.SetTarget(temp)
wx.CallAfter(self.graph.SetExtruder0TargetTemperature, temp)
except:
pass
try:
self.sentlines.put_nowait(line)
except:
pass
if "M140" in line:
if "S" in line:
try:
temp = float(line.split("S")[1].split("*")[0])
2012-05-04 04:40:19 +00:00
#self.bedtgauge.SetTarget(temp)
wx.CallAfter(self.graph.SetBedTargetTemperature, temp)
except:
pass
try:
self.sentlines.put_nowait(line)
except:
pass
def do_extrude(self, l = ""):
try:
if not l.__class__ in (str, unicode) 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__ in (str, unicode) or not len(l):
l = str(- float(self.edist.GetValue()))
pronsole.pronsole.do_extrude(self,l)
except:
pass
def setbedgui(self, f):
self.bsetpoint = f
2012-07-15 11:43:34 +00:00
#self.bedtgauge.SetTarget(int(f))
wx.CallAfter(self.graph.SetBedTargetTemperature, int(f))
2012-07-15 11:43:34 +00:00
if f>0:
wx.CallAfter(self.btemp.SetValue, str(f))
self.set("last_bed_temperature", str(f))
wx.CallAfter(self.setboff.SetBackgroundColour, "")
wx.CallAfter(self.setboff.SetForegroundColour, "")
wx.CallAfter(self.setbbtn.SetBackgroundColour, "#FFAA66")
wx.CallAfter(self.setbbtn.SetForegroundColour, "#660000")
wx.CallAfter(self.btemp.SetBackgroundColour, "#FFDABB")
2012-07-15 11:43:34 +00:00
else:
wx.CallAfter(self.setboff.SetBackgroundColour, "#0044CC")
wx.CallAfter(self.setboff.SetForegroundColour, "white")
wx.CallAfter(self.setbbtn.SetBackgroundColour, "")
wx.CallAfter(self.setbbtn.SetForegroundColour, "")
wx.CallAfter(self.btemp.SetBackgroundColour, "white")
2012-07-15 11:43:34 +00:00
wx.CallAfter(self.btemp.Refresh)
def sethotendgui(self, f):
self.hsetpoint = f
2012-07-15 11:43:34 +00:00
#self.hottgauge.SetTarget(int(f))
wx.CallAfter(self.graph.SetExtruder0TargetTemperature, int(f))
if f > 0:
wx.CallAfter(self.htemp.SetValue, str(f))
self.set("last_temperature", str(f))
wx.CallAfter(self.settoff.SetBackgroundColour, "")
wx.CallAfter(self.settoff.SetForegroundColour, "")
wx.CallAfter(self.settbtn.SetBackgroundColour, "#FFAA66")
wx.CallAfter(self.settbtn.SetForegroundColour, "#660000")
wx.CallAfter(self.htemp.SetBackgroundColour, "#FFDABB")
2012-07-15 11:43:34 +00:00
else:
wx.CallAfter(self.settoff.SetBackgroundColour, "#0044CC")
wx.CallAfter(self.settoff.SetForegroundColour, "white")
wx.CallAfter(self.settbtn.SetBackgroundColour, "")
wx.CallAfter(self.settbtn.SetForegroundColour, "")
wx.CallAfter(self.htemp.SetBackgroundColour, "white")
2012-07-15 11:43:34 +00:00
wx.CallAfter(self.htemp.Refresh)
def do_settemp(self, l = ""):
2011-06-09 10:54:03 +00:00
try:
if not l.__class__ in (str, unicode) or not len(l):
l = str(self.htemp.GetValue().split()[0])
l = l.lower().replace(",", ".")
2011-06-09 10:54:03 +00:00
for i in self.temps.keys():
l = l.replace(i, self.temps[i])
f = float(l)
if f >= 0:
2011-06-09 10:54:03 +00:00
if self.p.online:
self.p.send_now("M104 S"+l)
print _("Setting hotend temperature to %f degrees Celsius.") % f
2012-07-15 11:43:34 +00:00
self.sethotendgui(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.")
except Exception, x:
print _("You must enter a temperature. (%s)" % (repr(x),))
if self.webInterface:
self.webInterface.AddLog("You must enter a temperature. (%s)" % (repr(x),))
def do_bedtemp(self, l = ""):
2011-06-09 10:54:03 +00:00
try:
if not l.__class__ in (str, unicode) or not len(l):
l = str(self.btemp.GetValue().split()[0])
l = l.lower().replace(",", ".")
2011-06-09 10:54:03 +00:00
for i in self.bedtemps.keys():
l = l.replace(i, self.bedtemps[i])
f = float(l)
if f >= 0:
2011-06-09 10:54:03 +00:00
if self.p.online:
self.p.send_now("M140 S"+l)
print _("Setting bed temperature to %f degrees Celsius.") % f
2012-07-15 11:43:34 +00:00
self.setbedgui(f)
2011-06-09 10:54:03 +00:00
else:
2011-08-06 23:45:52 +00:00
print _("Printer is not online.")
if self.webInterface:
self.webInterface.AddLog("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.")
if self.webInterface:
self.webInterface.AddLog("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.")
if self.webInterface:
self.webInterface.AddLog("You must enter a temperature.")
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)
2011-07-26 14:34:55 +00:00
self.update_macros_menu()
def start_macro(self, macro_name, old_macro_definition=""):
if not self.processing_rc:
def cb(definition):
if len(definition.strip()) == 0:
if old_macro_definition != "":
dialog = wx.MessageDialog(self, _("Do you want to erase the macro?"), style = wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
if dialog.ShowModal() == wx.ID_YES:
2011-07-26 14:34:55 +00:00
self.delete_macro(macro_name)
return
2011-08-06 23:45:52 +00:00
print _("Cancelled.")
if self.webInterface:
self.webInterface.AddLog("Cancelled.")
2011-07-26 14:34:55 +00:00
return
self.cur_macro_name = macro_name
self.cur_macro_def = definition
self.end_macro()
macroed(macro_name, old_macro_definition, cb)
else:
pronsole.pronsole.start_macro(self, macro_name, old_macro_definition)
def catchprint(self, l):
if self.capture_skip_newline and len(l) and not len(l.strip("\n\r")):
self.capture_skip_newline = False
return
for pat in self.capture_skip.keys():
if self.capture_skip[pat] > 0 and pat.match(l):
self.capture_skip[pat] -= 1
self.capture_skip_newline = True
return
wx.CallAfter(self.logbox.AppendText, l)
if self.webInterface:
self.webInterface.AppendLog(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":
2011-06-08 14:19:38 +00:00
try:
key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM")
i = 0
while True:
baselist += [_winreg.EnumValue(key, i)[1]]
i += 1
2011-06-08 14:19:38 +00:00
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 project(self, event):
import projectlayer
if self.p.online:
projectlayer.setframe(self, self.p).Show()
else:
print _("Printer is not online.")
if self.webInterface:
self.webInterface.AddLog("Printer is not online.")
2011-06-08 14:19:38 +00:00
def popmenu(self):
self.menustrip = wx.MenuBar()
# File menu
m = wx.Menu()
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")))
self.Bind(wx.EVT_MENU, self.clearOutput, m.Append(-1, _("Clear console"), _(" Clear output console")))
self.Bind(wx.EVT_MENU, self.project, m.Append(-1, _("Projector"), _(" Project slices")))
self.Bind(wx.EVT_MENU, self.OnExit, m.Append(wx.ID_EXIT, _("E&xit"), _(" Closes the Window")))
self.menustrip.Append(m, _("&File"))
# Settings menu
m = wx.Menu()
self.macros_menu = wx.Menu()
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.Bind(wx.EVT_MENU, lambda x: threading.Thread(target = lambda:self.do_skein("set")).start(), m.Append(-1, _("Slicing Settings"), _(" Adjust slicing settings")))
2011-09-06 19:26:37 +00:00
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)
def doneediting(self, gcode):
f = open(self.filename, "w")
2011-08-06 13:28:25 +00:00
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):
dialog = wx.Dialog(self, -1, _("Enter macro name"), size = (260, 85))
panel = wx.Panel(dialog, -1)
2011-07-26 14:34:55 +00:00
vbox = wx.BoxSizer(wx.VERTICAL)
wx.StaticText(panel, -1, _("Macro name:"), (8, 14))
dialog.namectrl = wx.TextCtrl(panel, -1, '', (110, 8), size=(130, 24), style = wx.TE_PROCESS_ENTER)
2011-07-26 14:34:55 +00:00
hbox = wx.BoxSizer(wx.HORIZONTAL)
okb = wx.Button(dialog, wx.ID_OK, _("Ok"), size = (60, 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)
hbox.Add(wx.Button(dialog, wx.ID_CANCEL, _("Cancel"), size = (60, 24)))
2011-07-26 14:34:55 +00:00
vbox.Add(panel)
vbox.Add(hbox, 1, wx.ALIGN_CENTER|wx.TOP|wx.BOTTOM, 10)
2011-07-26 14:34:55 +00:00
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 len([c for c in macro.encode("ascii","replace") if not c.isalnum() and c != "_"]):
print _("Macro name may contain only ASCII alphanumeric symbols and underscores")
if self.webInterface:
self.webInterface.AddLog("Macro name may contain only alphanumeric symbols and underscores")
return
elif hasattr(self.__class__,"do_"+macro):
print _("Name '%s' is being used by built-in command") % macro
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-07-26 14:34:55 +00:00
2011-06-08 14:19:38 +00:00
def OnExit(self, event):
self.Close()
def rescanports(self, event = None):
scan = self.scanserial()
portslist = list(scan)
if self.settings.port != "" and self.settings.port not in portslist:
portslist += [self.settings.port]
2011-11-13 20:44:45 +00:00
self.serialport.Clear()
self.serialport.AppendItems(portslist)
try:
if os.path.exists(self.settings.port) or self.settings.port in scan:
self.serialport.SetValue(self.settings.port)
elif len(portslist) > 0:
self.serialport.SetValue(portslist[0])
except:
pass
2011-06-08 14:19:38 +00:00
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:
2011-06-16 04:28:46 +00:00
uts=self.uppertopsizer=wx.BoxSizer(wx.HORIZONTAL)
self.rescanbtn=wx.Button(self.panel,-1,_("Port"),size=buttonSize)
self.rescanbtn.SetToolTip(wx.ToolTip("Communication Settings\nClick to rescan ports"))
2011-11-13 20:44:45 +00:00
self.rescanbtn.Bind(wx.EVT_BUTTON,self.rescanports)
uts.Add(self.rescanbtn,0,wx.TOP|wx.LEFT,0)
2011-06-08 14:19:38 +00:00
self.serialport = wx.ComboBox(self.panel, -1,
2011-11-13 22:54:00 +00:00
choices=self.scanserial(),
style=wx.CB_DROPDOWN, size=(100, 25))
self.serialport.SetToolTip(wx.ToolTip("Select Port Printer is connected to"))
2011-11-13 20:44:45 +00:00
self.rescanports()
2011-06-16 04:28:46 +00:00
uts.Add(self.serialport)
uts.Add(wx.StaticText(self.panel,-1,"@"),0,wx.RIGHT|wx.ALIGN_CENTER,0)
2011-06-08 14:19:38 +00:00
self.baud = wx.ComboBox(self.panel, -1,
choices=["2400", "9600", "19200", "38400", "57600", "115200", "250000"],
style=wx.CB_DROPDOWN, size=(100, 25))
self.baud.SetToolTip(wx.ToolTip("Select Baud rate for printer communication"))
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)
self.connectbtn=wx.Button(self.panel,-1,_("Connect"), size=buttonSize)
2011-06-16 04:28:46 +00:00
uts.Add(self.connectbtn)
self.connectbtn.SetToolTip(wx.ToolTip("Connect to the printer"))
2011-06-08 14:19:38 +00:00
self.connectbtn.Bind(wx.EVT_BUTTON,self.connect)
self.resetbtn=wx.Button(self.panel,-1,_("Reset"),style=wx.BU_EXACTFIT,size=(-1,buttonSize[1]))
2011-06-08 14:19:38 +00:00
self.resetbtn.Bind(wx.EVT_BUTTON,self.reset)
self.resetbtn.SetToolTip(wx.ToolTip("Reset the printer"))
2011-06-16 04:28:46 +00:00
uts.Add(self.resetbtn)
#self.minibtn=wx.Button(self.panel,-1,_("Mini mode"),style=wx.BU_EXACTFIT)
#self.minibtn.Bind(wx.EVT_BUTTON,self.toggleview)
#uts.Add((25,-1))
#uts.Add((15,-1),flag=wx.EXPAND)
#uts.Add(self.minibtn,0,wx.ALIGN_CENTER)
#SECOND ROW
ubs=self.upperbottomsizer=uts#wx.BoxSizer(wx.HORIZONTAL)
self.loadbtn=wx.Button(self.panel,-1,_("Load file"),style=wx.BU_EXACTFIT,size=(-1,buttonSize[1]))
2011-06-08 14:19:38 +00:00
self.loadbtn.Bind(wx.EVT_BUTTON,self.loadfile)
self.loadbtn.SetToolTip(wx.ToolTip("Load a 3D model file"))
2011-06-16 04:28:46 +00:00
ubs.Add(self.loadbtn)
self.platebtn=wx.Button(self.panel,-1,_("Compose"),style=wx.BU_EXACTFIT,size=(-1,buttonSize[1]))
2011-11-18 08:52:16 +00:00
self.platebtn.Bind(wx.EVT_BUTTON,self.plate)
self.platebtn.SetToolTip(wx.ToolTip("Simple Plater System"))
2011-11-18 08:52:16 +00:00
#self.printerControls.append(self.uploadbtn)
ubs.Add(self.platebtn)
self.sdbtn=wx.Button(self.panel,-1,_("SD"),style=wx.BU_EXACTFIT,size=(-1,buttonSize[1]))
2011-11-18 08:52:16 +00:00
self.sdbtn.Bind(wx.EVT_BUTTON,self.sdmenu)
self.sdbtn.SetToolTip(wx.ToolTip("SD Card Printing"))
2011-11-18 08:52:16 +00:00
self.printerControls.append(self.sdbtn)
ubs.Add(self.sdbtn)
self.printbtn=wx.Button(self.panel,-1,_("Print"), size=buttonSize)
2011-06-16 04:28:46 +00:00
self.printbtn.Bind(wx.EVT_BUTTON,self.printfile)
self.printbtn.SetToolTip(wx.ToolTip("Start Printing Loaded File"))
self.printbtn.Disable()
2011-06-16 04:28:46 +00:00
ubs.Add(self.printbtn)
self.pausebtn=wx.Button(self.panel,-1,_("Pause"), size=buttonSize)
self.pausebtn.SetToolTip(wx.ToolTip("Pause Current Print"))
2011-06-16 04:28:46 +00:00
self.pausebtn.Bind(wx.EVT_BUTTON,self.pause)
ubs.Add(self.pausebtn)
#Right full view
2011-06-16 04:28:46 +00:00
lrs=self.lowerrsizer=wx.BoxSizer(wx.VERTICAL)
2011-11-30 12:11:21 +00:00
self.logbox=wx.TextCtrl(self.panel,style = wx.TE_MULTILINE,size=(350,-1))
self.logbox.SetEditable(0)
lrs.Add(self.logbox,1,wx.EXPAND)
2011-06-16 04:28:46 +00:00
lbrs=wx.BoxSizer(wx.HORIZONTAL)
self.commandbox=wx.TextCtrl(self.panel,style = wx.TE_PROCESS_ENTER)
self.commandbox.SetToolTip(wx.ToolTip("Send commands to printer\n(Type 'help' for simple\nhelp function)"))
self.commandbox.Bind(wx.EVT_TEXT_ENTER,self.sendline)
self.commandbox.Bind(wx.EVT_CHAR, self.cbkey)
self.commandbox.history=[u""]
self.commandbox.histindex=1
#self.printerControls.append(self.commandbox)
lbrs.Add(self.commandbox,1)
self.sendbtn=wx.Button(self.panel,-1,_("Send"),style=wx.BU_EXACTFIT)
self.sendbtn.SetToolTip(wx.ToolTip("Send Command to Printer"))
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,0,wx.EXPAND)
2011-06-16 04:28:46 +00:00
#left pane
lls=self.lowerlsizer=wx.GridBagSizer()
llts=wx.BoxSizer(wx.HORIZONTAL)
#lls.Add(wx.StaticText(self.panel,-1,_("mm/min")),pos=(0,4),span=(1,4))
lls.Add(llts,pos=(0,0),span=(1,9))
2011-06-16 04:28:46 +00:00
#lls.Add((200,375))
szbuttons=wx.GridBagSizer()
self.xyb = XYButtons(self.panel, self.moveXY, self.homeButtonClicked, self.spacebarAction, self.settings.bgcolor)
szbuttons.Add(self.xyb,pos=(0,1),flag=wx.ALIGN_CENTER)
self.zb = ZButtons(self.panel, self.moveZ, self.settings.bgcolor)
szbuttons.Add(self.zb,pos=(0,2),flag=wx.ALIGN_CENTER)
#lls.Add(self.zb, pos=(2,6), span=(1,1), flag=wx.ALIGN_CENTER)
wx.CallAfter(self.xyb.SetFocus)
lls.Add(szbuttons, pos=(1,0), span=(1,8), flag=wx.ALIGN_CENTER)
2012-08-03 21:35:06 +00:00
for i in self.cpbuttons:
btn=wx.Button(self.panel,-1,i[0],style=wx.BU_EXACTFIT)
btn.SetToolTip(wx.ToolTip(i[5]))
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)
if(i[2]==None):
if(i[4]==0):
llts.Add(btn)
else:
lls.Add(btn,pos=i[2],span=i[4])
2012-08-03 21:35:06 +00:00
self.xyfeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.xy_feedrate),min=0,max=50000,size=(70,-1))
self.xyfeedc.SetToolTip(wx.ToolTip("Set Maximum Speed for X & Y axes (mm/min)"))
llts.Add(wx.StaticText(self.panel,-1,_("XY:")), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
llts.Add(self.xyfeedc)
llts.Add(wx.StaticText(self.panel,-1,_("mm/min Z:")), flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
self.zfeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.z_feedrate),min=0,max=50000,size=(70,-1))
self.zfeedc.SetToolTip(wx.ToolTip("Set Maximum Speed for Z axis (mm/min)"))
llts.Add(self.zfeedc,)
self.monitorbox=wx.CheckBox(self.panel,-1,_("Watch"))
self.monitorbox.SetToolTip(wx.ToolTip("Monitor Temperatures in Graph"))
lls.Add(self.monitorbox,pos=(2,6))
self.monitorbox.Bind(wx.EVT_CHECKBOX,self.setmonitor)
lls.Add(wx.StaticText(self.panel,-1,_("Heat")),pos=(2,0),span=(1,1),flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT)
htemp_choices=[self.temps[i]+" ("+i+")" for i in sorted(self.temps.keys(),key=lambda x:self.temps[x])]
self.settoff=wx.Button(self.panel,-1,_("Off"),size=(36,-1),style=wx.BU_EXACTFIT)
self.settoff.SetToolTip(wx.ToolTip("Switch Hotend Off"))
self.settoff.Bind(wx.EVT_BUTTON,lambda e:self.do_settemp("off"))
self.printerControls.append(self.settoff)
lls.Add(self.settoff,pos=(2,1),span=(1,1))
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=(70,-1))
self.htemp.SetToolTip(wx.ToolTip("Select Temperature for Hotend"))
self.htemp.Bind(wx.EVT_COMBOBOX,self.htemp_change)
lls.Add(self.htemp,pos=(2,2),span=(1,2))
self.settbtn=wx.Button(self.panel,-1,_("Set"),size=(38,-1),style=wx.BU_EXACTFIT)
self.settbtn.SetToolTip(wx.ToolTip("Switch Hotend On"))
2011-06-09 10:54:03 +00:00
self.settbtn.Bind(wx.EVT_BUTTON,self.do_settemp)
self.printerControls.append(self.settbtn)
lls.Add(self.settbtn,pos=(2,4),span=(1,1))
lls.Add(wx.StaticText(self.panel,-1,_("Bed:")),pos=(3,0),span=(1,1),flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT)
btemp_choices=[self.bedtemps[i]+" ("+i+")" for i in sorted(self.bedtemps.keys(),key=lambda x:self.temps[x])]
self.setboff=wx.Button(self.panel,-1,_("Off"),size=(36,-1),style=wx.BU_EXACTFIT)
self.setboff.SetToolTip(wx.ToolTip("Switch Heated Bed Off"))
self.setboff.Bind(wx.EVT_BUTTON,lambda e:self.do_bedtemp("off"))
self.printerControls.append(self.setboff)
lls.Add(self.setboff,pos=(3,1),span=(1,1))
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=(70,-1))
self.btemp.SetToolTip(wx.ToolTip("Select Temperature for Heated Bed"))
self.btemp.Bind(wx.EVT_COMBOBOX,self.btemp_change)
lls.Add(self.btemp,pos=(3,2),span=(1,2))
self.setbbtn=wx.Button(self.panel,-1,_("Set"),size=(38,-1),style=wx.BU_EXACTFIT)
self.setbbtn.SetToolTip(wx.ToolTip("Switch Heated Bed On"))
self.setbbtn.Bind(wx.EVT_BUTTON,self.do_bedtemp)
self.printerControls.append(self.setbbtn)
lls.Add(self.setbbtn,pos=(3,4),span=(1,1))
self.btemp.SetValue(str(self.settings.last_bed_temperature))
self.htemp.SetValue(str(self.settings.last_temperature))
## added for an error where only the bed would get (pla) or (abs).
#This ensures, if last temp is a default pla or abs, it will be marked so.
# if it is not, then a (user) remark is added. This denotes a manual entry
for i in btemp_choices:
if i.split()[0] == str(self.settings.last_bed_temperature).split('.')[0] or i.split()[0] == str(self.settings.last_bed_temperature):
self.btemp.SetValue(i)
for i in htemp_choices:
if i.split()[0] == str(self.settings.last_temperature).split('.')[0] or i.split()[0] == str(self.settings.last_temperature) :
self.htemp.SetValue(i)
if( '(' not in self.btemp.Value):
self.btemp.SetValue(self.btemp.Value + ' (user)')
if( '(' not in self.htemp.Value):
self.htemp.SetValue(self.htemp.Value + ' (user)')
#lls.Add(self.btemp,pos=(4,1),span=(1,3))
#lls.Add(self.setbbtn,pos=(4,4),span=(1,2))
self.tempdisp=wx.StaticText(self.panel,-1,"")
self.edist=wx.SpinCtrl(self.panel,-1,"5",min=0,max=1000,size=(60,-1))
2011-06-09 16:44:57 +00:00
self.edist.SetBackgroundColour((225,200,200))
self.edist.SetForegroundColour("black")
lls.Add(self.edist,pos=(4,2),span=(1,2))
lls.Add(wx.StaticText(self.panel,-1,_("mm")),pos=(4,4),span=(1,1))
self.edist.SetToolTip(wx.ToolTip("Amount to Extrude or Retract (mm)"))
self.efeedc=wx.SpinCtrl(self.panel,-1,str(self.settings.e_feedrate),min=0,max=50000,size=(60,-1))
self.efeedc.SetToolTip(wx.ToolTip("Extrude / Retract speed (mm/min)"))
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)
lls.Add(self.efeedc,pos=(5,2),span=(1,2))
lls.Add(wx.StaticText(self.panel,-1,_("mm/\nmin")),pos=(5,4),span=(1,1))
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")
# lls.Add((10,0),pos=(0,11),span=(1,1))
#self.hottgauge=TempGauge(self.panel,size=(200,24),title=_("Heater:"),maxval=230)
#lls.Add(self.hottgauge,pos=(7,0),span=(1,4))
#self.bedtgauge=TempGauge(self.panel,size=(200,24),title=_("Bed:"),maxval=130)
#lls.Add(self.bedtgauge,pos=(8,0),span=(1,4))
#def scroll_setpoint(e):
# if e.GetWheelRotation()>0:
# self.do_settemp(str(self.hsetpoint+1))
# elif e.GetWheelRotation()<0:
# self.do_settemp(str(max(0,self.hsetpoint-1)))
#self.tgauge.Bind(wx.EVT_MOUSEWHEEL,scroll_setpoint)
self.graph = Graph(self.panel, wx.ID_ANY)
lls.Add(self.graph, pos=(3,5), span=(3,3))
lls.Add(self.tempdisp,pos=(6,0),span=(1,1))
2011-08-07 20:00:13 +00:00
self.gviz=gviz.gviz(self.panel,(300,300),
2011-12-11 09:11:47 +00:00
build_dimensions=self.build_dimensions_list,
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.SetToolTip(wx.ToolTip("Click to examine / edit\n layers of loaded file"))
self.gviz.showall=1
try:
raise ""
import stlview
self.gwindow=stlview.GCFrame(None, wx.ID_ANY, 'Gcode view, shift to move view, mousewheel to set layer', size=(600,600))
except:
self.gwindow=gviz.window([],
2011-12-11 09:11:47 +00:00
build_dimensions=self.build_dimensions_list,
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-11-30 12:11:21 +00:00
vcs=wx.BoxSizer(wx.VERTICAL)
vcs.Add(self.gviz,1,flag=wx.SHAPED)
cs=self.centersizer=wx.GridBagSizer()
2011-11-30 12:11:21 +00:00
vcs.Add(cs,0,flag=wx.EXPAND)
2011-06-16 04:28:46 +00:00
self.uppersizer=wx.BoxSizer(wx.VERTICAL)
self.uppersizer.Add(self.uppertopsizer)
#self.uppersizer.Add(self.upperbottomsizer)
2011-06-16 04:28:46 +00:00
self.lowersizer=wx.BoxSizer(wx.HORIZONTAL)
self.lowersizer.Add(lls)
2011-11-30 12:11:21 +00:00
self.lowersizer.Add(vcs,1,wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL)
self.lowersizer.Add(lrs,0,wx.EXPAND)
2011-06-16 04:28:46 +00:00
self.topsizer=wx.BoxSizer(wx.VERTICAL)
self.topsizer.Add(self.uppersizer)
self.topsizer.Add(self.lowersizer,1,wx.EXPAND)
2011-06-16 04:28:46 +00:00
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)
2011-06-16 04:28:46 +00:00
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()
def cbkey(self,e):
if e.GetKeyCode()==wx.WXK_UP:
if self.commandbox.histindex==len(self.commandbox.history):
self.commandbox.history+=[self.commandbox.GetValue()] #save current command
if len(self.commandbox.history):
self.commandbox.histindex=(self.commandbox.histindex-1)%len(self.commandbox.history)
self.commandbox.SetValue(self.commandbox.history[self.commandbox.histindex])
self.commandbox.SetSelection(0,len(self.commandbox.history[self.commandbox.histindex]))
elif e.GetKeyCode()==wx.WXK_DOWN:
if self.commandbox.histindex==len(self.commandbox.history):
self.commandbox.history+=[self.commandbox.GetValue()] #save current command
if len(self.commandbox.history):
self.commandbox.histindex=(self.commandbox.histindex+1)%len(self.commandbox.history)
self.commandbox.SetValue(self.commandbox.history[self.commandbox.histindex])
self.commandbox.SetSelection(0,len(self.commandbox.history[self.commandbox.histindex]))
else:
e.Skip()
2011-11-18 08:52:16 +00:00
def plate(self,e):
import plater
print "plate function activated"
plater.stlwin(size=(800,580),callback=self.platecb,parent=self).Show()
2011-11-18 08:52:16 +00:00
def platecb(self,name):
print "plated: "+name
self.loadfile(None,name)
2011-11-18 08:52:16 +00:00
def sdmenu(self,e):
obj = e.GetEventObject()
popupmenu=wx.Menu()
item = popupmenu.Append(-1,_("SD Upload"))
if not self.f or not len(self.f):
item.Enable(False)
self.Bind(wx.EVT_MENU,self.upload,id=item.GetId())
2011-11-18 08:52:16 +00:00
item = popupmenu.Append(-1,_("SD Print"))
self.Bind(wx.EVT_MENU,self.sdprintfile,id=item.GetId())
2011-11-18 08:52:16 +00:00
self.panel.PopupMenu(popupmenu, obj.GetPosition())
def htemp_change(self,event):
if self.hsetpoint > 0:
self.do_settemp("")
wx.CallAfter(self.htemp.SetInsertionPoint,0)
def btemp_change(self,event):
if self.bsetpoint > 0:
self.do_bedtemp("")
wx.CallAfter(self.btemp.SetInsertionPoint,0)
def showwin(self,event):
if(self.f is not None):
self.gwindow.Show(True)
self.gwindow.SetToolTip(wx.ToolTip("Mousewheel zooms the display\nShift / Mousewheel scrolls layers"))
self.gwindow.Raise()
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)
2011-06-16 04:28:46 +00:00
#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)
2011-06-16 04:28:46 +00:00
#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())]
2011-08-03 11:26:16 +00:00
for item in cs.GetChildren():
if hasattr(item.GetWindow(),"custombutton"):
allcbs += [(cs,item.GetWindow())]
for sizer,button in allcbs:
#sizer.Remove(button)
button.Destroy()
2011-09-30 14:41:18 +00:00
self.custombuttonbuttons=[]
2011-11-14 19:35:18 +00:00
newbuttonbuttonindex = len(self.custombuttons)
while newbuttonbuttonindex>0 and self.custombuttons[newbuttonbuttonindex-1] is None:
newbuttonbuttonindex -= 1
2011-09-30 14:41:18 +00:00
while len(self.custombuttons) < 13:
self.custombuttons.append(None)
2011-08-03 11:26:16 +00:00
for i in xrange(len(self.custombuttons)):
btndef = self.custombuttons[i]
try:
b=wx.Button(self.panel,-1,btndef[0],style=wx.BU_EXACTFIT)
2011-11-14 19:43:16 +00:00
b.SetToolTip(wx.ToolTip(_("Execute command: ")+btndef[1]))
2011-08-03 11:26:16 +00:00
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:
2011-11-14 19:35:18 +00:00
if i == newbuttonbuttonindex:
self.newbuttonbutton=b=wx.Button(self.panel,-1,"+",size=(19,18),style=wx.BU_EXACTFIT)
2011-11-15 09:06:25 +00:00
#b.SetFont(wx.Font(12,wx.FONTFAMILY_SWISS,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_BOLD))
2011-11-14 19:35:18 +00:00
b.SetForegroundColour("#4444ff")
2011-11-14 19:43:16 +00:00
b.SetToolTip(wx.ToolTip(_("click to add new custom button")))
2011-11-14 19:35:18 +00:00
b.Bind(wx.EVT_BUTTON,self.cbutton_edit)
else:
b=wx.Button(self.panel,-1,".",size=(1,1))
#b=wx.StaticText(self.panel,-1,"",size=(72,22),style=wx.ALIGN_CENTRE+wx.ST_NO_AUTORESIZE) #+wx.SIMPLE_BORDER
b.Disable()
#continue
2011-08-03 11:26:16 +00:00
b.custombutton=i
b.properties=btndef
if btndef is not None:
b.Bind(wx.EVT_BUTTON,self.procbutton)
b.Bind(wx.EVT_MOUSE_EVENTS,self.editbutton)
2011-11-14 19:35:18 +00:00
#else:
# b.Bind(wx.EVT_BUTTON,lambda e:e.Skip())
2011-09-30 14:41:18 +00:00
self.custombuttonbuttons.append(b)
#if i<4:
# ubs.Add(b)
#else:
cs.Add(b,pos=((i)/4,(i)%4))
2011-08-03 11:26:16 +00:00
self.topsizer.Layout()
2011-08-03 11:26:16 +00:00
def help_button(self):
2011-08-06 23:45:52 +00:00
print _('Defines custom button. Usage: button <num> "title" [/c "colour"] command')
if self.webInterface:
self.webInterface.AddLog('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")
if self.webInterface:
self.webInterface.AddLog("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)
2011-09-30 14:41:18 +00:00
while n>0 and self.custombuttons[n-1] is None:
n -= 1
2012-04-22 23:33:47 +00:00
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()
2011-08-03 11:26:16 +00:00
def cbutton_remove(self,e,button):
n = button.custombutton
self.custombuttons[n]=None
self.cbutton_save(n,None)
2011-09-30 14:41:18 +00:00
#while len(self.custombuttons) and self.custombuttons[-1] is None:
# del self.custombuttons[-1]
2011-11-14 19:35:18 +00:00
wx.CallAfter(self.cbuttons_reload)
2011-08-03 11:26:16 +00:00
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])
2011-09-30 14:41:18 +00:00
#if self.custombuttons[-1] is None:
# del self.custombuttons[-1]
2011-08-03 11:26:16 +00:00
self.cbuttons_reload()
2011-08-03 11:26:16 +00:00
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)
2011-09-30 14:41:18 +00:00
elif e.Dragging() and e.ButtonIsDown(wx.MOUSE_BTN_LEFT):
obj = e.GetEventObject()
scrpos = obj.ClientToScreen(e.GetPosition())
if not hasattr(self,"dragpos"):
self.dragpos = scrpos
e.Skip()
return
else:
dx,dy=self.dragpos[0]-scrpos[0],self.dragpos[1]-scrpos[1]
if dx*dx+dy*dy < 5*5: # threshold to detect dragging for jittery mice
e.Skip()
return
2011-09-30 14:41:18 +00:00
if not hasattr(self,"dragging"):
# init dragging of the custom button
2011-11-14 19:35:18 +00:00
if hasattr(obj,"custombutton") and obj.properties is not None:
#self.newbuttonbutton.SetLabel("")
#self.newbuttonbutton.SetFont(wx.Font(10,wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_NORMAL))
#self.newbuttonbutton.SetForegroundColour("black")
#self.newbuttonbutton.SetSize(obj.GetSize())
#if self.upperbottomsizer.GetItem(self.newbuttonbutton) is not None:
# self.upperbottomsizer.SetItemMinSize(self.newbuttonbutton,obj.GetSize())
# self.topsizer.Layout()
for b in self.custombuttonbuttons:
#if b.IsFrozen(): b.Thaw()
if b.properties is None:
b.Enable()
b.SetLabel("")
b.SetFont(wx.Font(10,wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_NORMAL))
b.SetForegroundColour("black")
b.SetSize(obj.GetSize())
if self.upperbottomsizer.GetItem(b) is not None:
self.upperbottomsizer.SetItemMinSize(b,obj.GetSize())
self.topsizer.Layout()
# b.SetStyle(wx.ALIGN_CENTRE+wx.ST_NO_AUTORESIZE+wx.SIMPLE_BORDER)
self.dragging = wx.Button(self.panel,-1,obj.GetLabel(),style=wx.BU_EXACTFIT)
2011-09-30 14:41:18 +00:00
self.dragging.SetBackgroundColour(obj.GetBackgroundColour())
self.dragging.SetForegroundColour(obj.GetForegroundColour())
2011-09-30 14:41:18 +00:00
self.dragging.sourcebutton = obj
self.dragging.Raise()
self.dragging.Disable()
self.dragging.SetPosition(self.panel.ScreenToClient(scrpos))
self.last_drag_dest = obj
self.dragging.label = obj.s_label = obj.GetLabel()
self.dragging.bgc = obj.s_bgc = obj.GetBackgroundColour()
self.dragging.fgc = obj.s_fgc = obj.GetForegroundColour()
else:
2011-09-30 14:41:18 +00:00
# dragging in progress
self.dragging.SetPosition(self.panel.ScreenToClient(scrpos))
wx.CallAfter(self.dragging.Refresh)
btns = self.custombuttonbuttons
2011-09-30 14:41:18 +00:00
dst = None
src = self.dragging.sourcebutton
drg = self.dragging
for b in self.custombuttonbuttons:
if b.GetScreenRect().Contains(scrpos):
dst = b
break
#if dst is None and self.panel.GetScreenRect().Contains(scrpos):
# # try to check if it is after buttons at the end
# tspos = self.panel.ClientToScreen(self.upperbottomsizer.GetPosition())
# bspos = self.panel.ClientToScreen(self.centersizer.GetPosition())
# tsrect = wx.Rect(*(tspos.Get()+self.upperbottomsizer.GetSize().Get()))
# bsrect = wx.Rect(*(bspos.Get()+self.centersizer.GetSize().Get()))
# lbrect = btns[-1].GetScreenRect()
# p = scrpos.Get()
# if len(btns)<4 and tsrect.Contains(scrpos):
# if lbrect.GetRight() < p[0]:
# print "Right of last button on upper cb sizer"
# if bsrect.Contains(scrpos):
# if lbrect.GetBottom() < p[1]:
# print "Below last button on lower cb sizer"
# if lbrect.GetRight() < p[0] and lbrect.GetTop() <= p[1] and lbrect.GetBottom() >= p[1]:
# print "Right to last button on lower cb sizer"
if dst is not self.last_drag_dest:
if self.last_drag_dest is not None:
self.last_drag_dest.SetBackgroundColour(self.last_drag_dest.s_bgc)
self.last_drag_dest.SetForegroundColour(self.last_drag_dest.s_fgc)
2011-09-30 14:41:18 +00:00
self.last_drag_dest.SetLabel(self.last_drag_dest.s_label)
if dst is not None and dst is not src:
dst.s_bgc = dst.GetBackgroundColour()
dst.s_fgc = dst.GetForegroundColour()
2011-09-30 14:41:18 +00:00
dst.s_label = dst.GetLabel()
src.SetBackgroundColour(dst.GetBackgroundColour())
src.SetForegroundColour(dst.GetForegroundColour())
2011-09-30 14:41:18 +00:00
src.SetLabel(dst.GetLabel())
dst.SetBackgroundColour(drg.bgc)
dst.SetForegroundColour(drg.fgc)
2011-09-30 14:41:18 +00:00
dst.SetLabel(drg.label)
else:
src.SetBackgroundColour(drg.bgc)
src.SetForegroundColour(drg.fgc)
2011-09-30 14:41:18 +00:00
src.SetLabel(drg.label)
self.last_drag_dest = dst
elif hasattr(self,"dragging") and not e.ButtonIsDown(wx.MOUSE_BTN_LEFT):
# dragging finished
obj = e.GetEventObject()
scrpos = obj.ClientToScreen(e.GetPosition())
dst = None
src = self.dragging.sourcebutton
drg = self.dragging
for b in self.custombuttonbuttons:
if b.GetScreenRect().Contains(scrpos):
dst = b
break
if dst is not None:
src_i = src.custombutton
dst_i = dst.custombutton
self.custombuttons[src_i],self.custombuttons[dst_i] = self.custombuttons[dst_i],self.custombuttons[src_i]
self.cbutton_save(src_i,self.custombuttons[src_i])
self.cbutton_save(dst_i,self.custombuttons[dst_i])
while self.custombuttons[-1] is None:
del self.custombuttons[-1]
wx.CallAfter(self.dragging.Destroy)
del self.dragging
wx.CallAfter(self.cbuttons_reload)
del self.last_drag_dest
del self.dragpos
2011-08-03 11:26:16 +00:00
else:
2011-09-30 14:41:18 +00:00
e.Skip()
def homeButtonClicked(self, corner):
if corner == 0: # upper-left
self.onecmd('home X')
if corner == 1: # upper-right
self.onecmd('home Y')
if corner == 2: # lower-right
self.onecmd('home Z')
if corner == 3: # lower-left
self.onecmd('home')
# When user clicks on the XY control, the Z control no longer gets spacebar/repeat signals
self.zb.clearRepeat()
2011-11-07 19:41:14 +00:00
def moveXY(self, x, y):
if x != 0:
self.onecmd('move X %s' % x)
if y != 0:
self.onecmd('move Y %s' % y)
# When user clicks on the XY control, the Z control no longer gets spacebar/repeat signals
self.zb.clearRepeat()
2011-11-07 19:41:14 +00:00
def moveZ(self, z):
if z != 0:
self.onecmd('move Z %s' % z)
# When user clicks on the Z control, the XY control no longer gets spacebar/repeat signals
self.xyb.clearRepeat()
def spacebarAction(self):
self.zb.repeatLast()
self.xyb.repeatLast()
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")
if self.webInterface:
self.webInterface.AddLog("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()
if self.webInterface:
from printrun import webinterface
webinterface.KillWebInterfaceThread()
def do_monitor(self,l=""):
if l.strip()=="":
self.monitorbox.SetValue(not self.monitorbox.GetValue())
elif l.strip()=="off":
wx.CallAfter(self.monitorbox.SetValue,False)
else:
try:
self.monitor_interval=float(l)
wx.CallAfter(self.monitorbox.SetValue,self.monitor_interval>0)
except:
2011-08-06 23:45:52 +00:00
print _("Invalid period given.")
if self.webInterface:
self.webInterface.AddLog("Invalid period given.")
self.setmonitor(None)
if self.monitor:
2011-08-06 23:45:52 +00:00
print _("Monitoring printer.")
if self.webInterface:
self.webInterface.AddLog("Monitoring printer.")
else:
2011-08-06 23:45:52 +00:00
print _("Done monitoring.")
if self.webInterface:
self.webInterface.AddLog("Done monitoring.")
2011-06-08 14:19:38 +00:00
def setmonitor(self,e):
self.monitor=self.monitorbox.GetValue()
if self.monitor:
2012-05-04 04:40:19 +00:00
wx.CallAfter(self.graph.StartPlotting,1000)
else:
2012-05-04 04:40:19 +00:00
wx.CallAfter(self.graph.StopPlotting)
2011-06-08 14:19:38 +00:00
def sendline(self,e):
command=self.commandbox.GetValue()
if not len(command):
return
wx.CallAfter(self.logbox.AppendText,">>>"+command+"\n")
if self.webInterface:
self.webInterface.AppendLog(">>>"+command+"\n")
2011-06-11 21:03:01 +00:00
self.onecmd(str(command))
self.commandbox.SetSelection(0,len(command))
self.commandbox.history+=[command]
self.commandbox.histindex=len(self.commandbox.history)
def clearOutput(self,e):
self.logbox.Clear()
2011-06-08 14:19:38 +00:00
def statuschecker(self):
try:
while(self.statuscheck):
string=""
2012-05-06 17:00:56 +00:00
#if(self.p.online):
# string+=_("Printer is online. ")
#try:
# string+=_("Loaded ")+os.path.split(self.filename)[1]+" "
#except:
# pass
#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 ",""))
try:
#self.hottgauge.SetValue(parse_temperature_report(self.tempreport, "T:"))
wx.CallAfter(self.graph.SetExtruder0Temperature, parse_temperature_report(self.tempreport, "T:"))
#self.bedtgauge.SetValue(parse_temperature_report(self.tempreport, "B:"))
wx.CallAfter(self.graph.SetBedTemperature, parse_temperature_report(self.tempreport, "B:"))
except:
pass
fractioncomplete = 0.0
2011-06-08 14:19:38 +00:00
if self.sdprinting:
fractioncomplete = float(self.percentdone/100.0)
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:
fractioncomplete = float(self.p.queueindex)/len(self.p.mainqueue)
string+= _(" Printing:%04.2f %% |") % (100*float(self.p.queueindex)/len(self.p.mainqueue),)
string+= _(" Line# %d of %d lines |" ) % (self.p.queueindex, len(self.p.mainqueue))
if fractioncomplete > 0.0:
secondselapsed = int(time.time()-self.starttime+self.extra_print_time)
secondsestimate = secondselapsed/fractioncomplete
secondsremain = secondsestimate - secondselapsed
string+= _(" Est: %s of %s remaining | ") % (time.strftime('%H:%M:%S', time.gmtime(secondsremain)),
time.strftime('%H:%M:%S', time.gmtime(secondsestimate)))
string+= _(" Z: %0.2f mm") % self.curlayer
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")
if not hasattr(self,"auto_monitor_pattern"):
self.auto_monitor_pattern = re.compile(r"(ok\s+)?T:[\d\.]+(\s+B:[\d\.]+)?(\s+@:[\d\.]+)?\s*")
self.capture_skip[self.auto_monitor_pattern]=self.capture_skip.setdefault(self.auto_monitor_pattern,0)+1
2011-06-08 14:19:38 +00:00
self.p.send_now("M105")
time.sleep(self.monitor_interval)
while not self.sentlines.empty():
try:
gc=self.sentlines.get_nowait()
wx.CallAfter(self.gviz.addgcode,gc,1)
except:
break
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
2012-07-31 06:45:15 +00:00
2011-06-08 14:19:38 +00:00
def capture(self, func, *args, **kwargs):
stdout=sys.stdout
cout=None
try:
cout=self.cout
except:
pass
if cout is None:
cout=cStringIO.StringIO()
2011-06-08 14:19:38 +00:00
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 ",""))
try:
#self.hottgauge.SetValue(parse_temperature_report(self.tempreport, "T:"))
wx.CallAfter(self.graph.SetExtruder0Temperature, parse_temperature_report(self.tempreport, "T:"))
2012-08-02 16:26:56 +00:00
wx.CallAfter(self.graph.SetBedTemperature, parse_temperature_report(self.tempreport, "B:"))
except:
2012-08-02 16:26:56 +00:00
traceback.print_exc()
tstring=l.rstrip()
#print tstring
if (tstring!="ok") and (tstring!="wait") and ("ok T:" not in tstring):
# print "*"+tstring+"*"
# print "[" + time.strftime('%H:%M:%S',time.localtime(time.time())) + "] " + tstring
wx.CallAfter(self.logbox.AppendText,tstring+"\n")
2011-06-08 14:19:38 +00:00
for i in self.recvlisteners:
i(l)
2011-06-08 14:19:38 +00:00
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()]
2011-06-08 14:19:38 +00:00
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
2011-06-08 14:19:38 +00:00
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
def getfiles(self):
if not self.p.online:
self.sdfiles=[]
return
self.listing=0
self.sdfiles=[]
self.recvlisteners+=[self.listfiles]
self.p.send_now("M21")
2011-06-08 14:19:38 +00:00
self.p.send_now("M20")
2011-06-08 14:19:38 +00:00
def skein_func(self):
try:
2011-11-18 08:52:16 +00:00
import shlex
param = self.expandcommand(self.settings.slicecommand).encode()
2011-11-18 08:52:16 +00:00
print "Slicing: ",param
if self.webInterface:
self.webInterface.AddLog("Slicing: "+param)
pararray=[i.replace("$s",self.filename).replace("$o",self.filename.replace(".stl","_export.gcode").replace(".STL","_export.gcode")).encode() for i in shlex.split(param.replace("\\","\\\\").encode())]
#print pararray
2011-11-18 08:52:16 +00:00
self.skeinp=subprocess.Popen(pararray,stderr=subprocess.STDOUT,stdout=subprocess.PIPE)
while True:
o = self.skeinp.stdout.read(1)
if o == '' and self.skeinp.poll() != None: break
sys.stdout.write(o)
self.skeinp.wait()
2011-06-08 14:19:38 +00:00
self.stopsf=1
except:
print _("Failed to execute slicing software: ")
if self.webInterface:
self.webInterface.AddLog("Failed to execute slicing software: ")
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-11-18 08:52:16 +00:00
wx.CallAfter(self.status.SetStatusText,_("Slicing..."))#+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").replace(".obj","_export.gcode").replace(".OBJ","_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
2011-11-18 08:52:16 +00:00
wx.CallAfter(self.loadbtn.SetLabel,_("Load File"))
self.skeining=0
self.skeinp=None
2011-06-08 14:19:38 +00:00
def skein(self,filename):
2011-11-18 08:52:16 +00:00
wx.CallAfter(self.loadbtn.SetLabel,_("Cancel"))
print _("Slicing ") + filename
2011-06-08 14:19:38 +00:00
self.cout=StringIO.StringIO()
self.filename=filename
self.stopsf=0
2011-11-18 08:52:16 +00:00
self.skeining=1
2012-08-03 21:35:06 +00:00
threading.Thread(target=self.skein_func).start()
threading.Thread(target=self.skein_monitor).start()
2011-08-06 13:28:25 +00:00
def loadfile(self,event,filename=None):
2011-11-18 08:52:16 +00:00
if self.skeining and self.skeinp is not None:
self.skeinp.terminate()
return
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(_("OBJ, STL, and GCODE files (*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ)|*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ|All Files (*.*)|*.*"))
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)
elif name.lower().endswith(".obj"):
self.skein(name)
2011-06-08 14:19:38 +00:00
else:
self.filename=name
of=open(self.filename)
self.f=[i.replace("\n","").replace("\r","") for i in of]
of.close
self.status.SetStatusText(_("Loaded %s, %d lines") % (name, len(self.f)))
2011-08-06 23:45:52 +00:00
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()
2012-04-22 23:33:47 +00:00
2011-06-21 16:52:11 +00:00
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")
print _("the print goes from %f mm to %f mm in X\nand is %f mm wide\n") % (Xmin, Xmax, Xtot)
if self.webInterface:
self.webInterface.AddLog(_("the print goes from %f mm to %f mm in X\nand is %f mm wide\n") % (Xmin, Xmax, Xtot))
print _("the print goes from %f mm to %f mm in Y\nand is %f mm wide\n") % (Ymin, Ymax, Ytot)
print _("the print goes from %f mm to %f mm in Z\nand is %f mm high\n") % (Zmin, Zmax, Ztot)
try:
print _("Estimated duration (pessimistic): "), pronsole.estimate_duration(self.f)
except:
pass
#import time
#t0=time.time()
2011-06-21 16:52:11 +00:00
self.gviz.clear()
self.gwindow.p.clear()
self.gviz.addfile(self.f)
#print "generated 2d view in %f s"%(time.time()-t0)
#t0=time.time()
self.gwindow.p.addfile(self.f)
#print "generated 3d view in %f s"%(time.time()-t0)
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):
self.extra_print_time=0
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
2011-06-08 22:02:00 +00:00
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):
if not self.f or not len(self.f):
2011-06-08 22:02:00 +00:00
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-11-30 13:18:12 +00:00
self.p.send_now("M21")
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
def pause(self,event):
print _("Paused.")
2011-06-08 14:19:38 +00:00
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
self.extra_print_time += int(time.time() - self.starttime)
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()
2011-06-08 14:19:38 +00:00
def connect(self,event):
print _("Connecting...")
2011-06-08 14:19:38 +00:00
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-08 14:19:38 +00:00
def disconnect(self,event):
print _("Disconnected.")
2011-06-08 14:19:38 +00:00
self.p.disconnect()
self.statuscheck=False
2011-12-04 01:17:19 +00:00
self.connectbtn.SetLabel("Connect")
self.connectbtn.SetToolTip(wx.ToolTip("Connect to the printer"))
2011-12-04 01:17:19 +00:00
self.connectbtn.Bind(wx.EVT_BUTTON,self.connect)
wx.CallAfter(self.printbtn.Disable);
wx.CallAfter(self.pausebtn.Disable);
for i in self.printerControls:
wx.CallAfter(i.Disable)
# Disable XYButtons and ZButtons
wx.CallAfter(self.xyb.disable)
wx.CallAfter(self.zb.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):
print _("Reset.")
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()
2012-07-15 11:43:34 +00:00
self.sethotendgui(0)
self.setbedgui(0)
self.p.printing=0
wx.CallAfter(self.printbtn.SetLabel, _("Print"))
2011-06-10 18:34:04 +00:00
if self.paused:
self.p.paused=0
2011-08-06 23:45:52 +00:00
wx.CallAfter(self.pausebtn.SetLabel, _("Pause"))
2011-06-10 18:34:04 +00:00
self.paused=0
2011-12-11 09:11:47 +00:00
def get_build_dimensions(self,bdim):
import re
# a string containing up to six numbers delimited by almost anything
# first 0-3 numbers specify the build volume, no sign, always positive
# remaining 0-3 numbers specify the coordinates of the "southwest" corner of the build platform
# "XXX,YYY"
# "XXXxYYY+xxx-yyy"
# "XXX,YYY,ZZZ+xxx+yyy-zzz"
# etc
bdl = re.match(
"[^\d+-]*(\d+)?" + # X build size
"[^\d+-]*(\d+)?" + # Y build size
"[^\d+-]*(\d+)?" + # Z build size
"[^\d+-]*([+-]\d+)?" + # X corner coordinate
"[^\d+-]*([+-]\d+)?" + # Y corner coordinate
"[^\d+-]*([+-]\d+)?" # Z corner coordinate
,bdim).groups()
defaults = [200, 200, 100, 0, 0, 0]
bdl_float = [float(value) if value else defaults[i] for i, value in enumerate(bdl)]
2011-12-11 09:11:47 +00:00
return bdl_float
class macroed(wx.Dialog):
"""Really simple editor to edit macro definitions"""
2012-04-22 23:33:47 +00:00
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)
2012-04-22 23:33:47 +00:00
titletext = wx.StaticText(self.panel,-1," _") #title%macro_name)
2011-09-04 22:08:09 +00:00
#title.SetFont(wx.Font(11,wx.NORMAL,wx.NORMAL,wx.BOLD))
2012-04-22 23:33:47 +00:00
titlesizer.Add(titletext,1)
self.findb = wx.Button(self.panel, -1, _("Find"),style=wx.BU_EXACTFIT) #New button for "Find" (Jezmy)
2012-04-22 23:33:47 +00:00
self.findb.Bind(wx.EVT_BUTTON, self.find)
self.okb = wx.Button(self.panel, -1, _("Save"),style=wx.BU_EXACTFIT)
2011-08-06 23:45:52 +00:00
self.okb.Bind(wx.EVT_BUTTON, self.save)
2011-09-04 22:08:09 +00:00
self.Bind(wx.EVT_CLOSE, self.close)
2012-04-22 23:33:47 +00:00
titlesizer.Add(self.findb)
titlesizer.Add(self.okb)
self.cancelb = wx.Button(self.panel, -1, _("Cancel"),style=wx.BU_EXACTFIT)
2011-08-06 23:45:52 +00:00
self.cancelb.Bind(wx.EVT_BUTTON, self.close)
titlesizer.Add(self.cancelb)
topsizer=wx.BoxSizer(wx.VERTICAL)
topsizer.Add(titlesizer,0,wx.EXPAND)
2012-04-22 23:33:47 +00:00
self.e=wx.TextCtrl(self.panel,style=wx.TE_MULTILINE+wx.HSCROLL,size=(400,400))
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()
2012-04-22 23:33:47 +00:00
def find(self,ev):
# Ask user what to look for, find it and point at it ... (Jezmy)
S = self.e.GetStringSelection()
if not S :
S = "Z"
FindValue = wx.GetTextFromUser('Please enter a search string:', caption="Search", default_value=S, parent=None)
somecode = self.e.GetValue()
numLines = len(somecode)
position = somecode.find(FindValue, self.e.GetInsertionPoint())
if position == -1 :
# ShowMessage(self,-1, "Not found!")
titletext = wx.TextCtrl(self.panel,-1,"Not Found!")
else:
# self.title.SetValue("Position : "+str(position))
titletext = wx.TextCtrl(self.panel,-1,str(position))
# ananswer = wx.MessageBox(str(numLines)+" Lines detected in file\n"+str(position), "OK")
self.e.SetFocus()
self.e.SetInsertionPoint(position)
self.e.SetSelection(position, position + len(FindValue))
self.e.ShowPosition(position)
def ShowMessage(self, ev , message):
dlg = wxMessageDialog(self, message,
"Info!", wxOK | wxICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
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()
if self.webInterface:
webinterface.KillWebInterfaceThread()
def unindent(self,text):
self.indent_chars = text[:len(text)-len(text.lstrip())]
if len(self.indent_chars)==0:
self.indent_chars=" "
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
lines = re.split(r"(?:\r\n?|\n)",text)
if len(lines) <= 1:
return text
reindented = ""
for line in lines:
if line.strip() != "":
reindented += self.indent_chars + line + "\n"
return reindented
2011-07-26 16:19:45 +00:00
class options(wx.Dialog):
"""Options editor"""
def __init__(self,pronterface):
wx.Dialog.__init__(self, None, title=_("Edit settings"), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
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.FlexGridSizer(rows=0,cols=2,hgap=8,vgap=2)
grid.SetFlexibleDirection( wx.BOTH )
grid.AddGrowableCol( 1 )
grid.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
2011-07-26 16:19:45 +00:00
vbox.Add(grid,0,wx.EXPAND)
ctrls = {}
for k,v in sorted(pronterface.settings._all_settings().items()):
ctrls[k,0] = wx.StaticText(self,-1,k)
ctrls[k,1] = wx.TextCtrl(self,-1,str(v))
if k in pronterface.helpdict:
ctrls[k,0].SetToolTipString(pronterface.helpdict.get(k))
ctrls[k,1].SetToolTipString(pronterface.helpdict.get(k))
grid.Add(ctrls[k,0],0,wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.ALIGN_RIGHT)
grid.Add(ctrls[k,1],1,wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.EXPAND)
2011-07-26 16:19:45 +00:00
topsizer.Add(self.CreateSeparatedButtonSizer(wx.OK+wx.CANCEL),0,wx.EXPAND)
self.SetSizer(topsizer)
2011-07-26 16:19:45 +00:00
topsizer.Layout()
topsizer.Fit(self)
if self.ShowModal()==wx.ID_OK:
for k,v in pronterface.settings._all_settings().items():
if ctrls[k,1].GetValue() != str(v):
pronterface.set(k,str(ctrls[k,1].GetValue()))
2011-07-26 16:19:45 +00:00
self.Destroy()
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)
grid=wx.FlexGridSizer(rows=0,cols=2,hgap=4,vgap=2)
grid.AddGrowableCol(1,1)
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)
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,1,wx.EXPAND)
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)
topsizer.Add(grid,0,wx.EXPAND)
topsizer.Add( (0,0),1)
topsizer.Add(self.CreateStdDialogButtonSizer(wx.OK|wx.CANCEL),0,wx.ALIGN_CENTER)
self.SetSizer(topsizer)
2012-07-31 06:45:15 +00:00
def macrob_enabler(self,e):
macro = self.command.GetValue()
valid = False
try:
if macro == "":
valid = True
elif self.pronterface.macros.has_key(macro):
valid = True
elif hasattr(self.pronterface.__class__,u"do_"+macro):
valid = False
elif len([c for c in macro if not c.isalnum() and c != "_"]):
valid = False
else:
valid = True
except:
if macro == "":
valid = True
elif self.pronterface.macros.has_key(macro):
valid = True
elif len([c for c in macro if not c.isalnum() and c != "_"]):
valid = False
else:
valid = True
self.macrob.Enable(valid)
2012-07-31 06:45:15 +00:00
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-10-25 19:58:13 +00:00
class TempGauge(wx.Panel):
2012-07-31 06:45:15 +00:00
def __init__(self,parent,size=(200,22),title="",maxval=240,gaugeColour=None):
2011-10-25 19:58:13 +00:00
wx.Panel.__init__(self,parent,-1,size=size)
self.Bind(wx.EVT_PAINT,self.paint)
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
self.width,self.height=size
self.title=title
self.max=maxval
self.gaugeColour=gaugeColour
2011-10-25 19:58:13 +00:00
self.value=0
self.setpoint=0
self.recalc()
2012-07-31 06:45:15 +00:00
2011-10-25 19:58:13 +00:00
def recalc(self):
mmax=max(int(self.setpoint*1.05),self.max)
self.scale=float(self.width-2)/float(mmax)
self.ypt=max(16,int(self.scale*max(self.setpoint,self.max/6)))
2012-07-31 06:45:15 +00:00
2011-10-25 19:58:13 +00:00
def SetValue(self,value):
self.value=value
wx.CallAfter(self.Refresh)
2012-07-31 06:45:15 +00:00
2011-10-25 19:58:13 +00:00
def SetTarget(self,value):
self.setpoint=value
self.recalc()
wx.CallAfter(self.Refresh)
2012-07-31 06:45:15 +00:00
def interpolatedColour(self,val,vmin,vmid,vmax,cmin,cmid,cmax):
if val < vmin: return cmin
if val > vmax: return cmax
if val <= vmid:
lo,hi,val,valhi = cmin,cmid,val-vmin,vmid-vmin
else:
lo,hi,val,valhi = cmid,cmax,val-vmid,vmax-vmid
vv = float(val)/valhi
rgb=lo.Red()+(hi.Red()-lo.Red())*vv,lo.Green()+(hi.Green()-lo.Green())*vv,lo.Blue()+(hi.Blue()-lo.Blue())*vv
rgb=map(lambda x:x*0.8,rgb)
return wx.Colour(*map(int,rgb))
2012-07-31 06:45:15 +00:00
2011-10-25 19:58:13 +00:00
def paint(self,ev):
x0,y0,x1,y1,xE,yE = 1,1,self.ypt+1,1,self.width+1-2,20
2011-10-25 19:58:13 +00:00
dc=wx.PaintDC(self)
dc.SetBackground(wx.Brush((255,255,255)))
dc.Clear()
cold,medium,hot = wx.Colour(0,167,223),wx.Colour(239,233,119),wx.Colour(210,50.100)
gauge1,gauge2 = wx.Colour(255,255,210),(self.gaugeColour or wx.Colour(234,82,0))
shadow1,shadow2 = wx.Colour(110,110,110),wx.Colour(255,255,255)
2011-10-25 19:58:13 +00:00
gc = wx.GraphicsContext.Create(dc)
# draw shadow first
# corners
gc.SetBrush(gc.CreateRadialGradientBrush(xE-7,9,xE-7,9,8,shadow1,shadow2))
gc.DrawRectangle(xE-7,1,8,8)
gc.SetBrush(gc.CreateRadialGradientBrush(xE-7,17,xE-7,17,8,shadow1,shadow2))
gc.DrawRectangle(xE-7,17,8,8)
gc.SetBrush(gc.CreateRadialGradientBrush(x0+6,17,x0+6,17,8,shadow1,shadow2))
gc.DrawRectangle(0,17,x0+6,8)
# edges
gc.SetBrush(gc.CreateLinearGradientBrush(xE-13,0,xE-6,0,shadow1,shadow2))
gc.DrawRectangle(xE-6,9,10,8)
gc.SetBrush(gc.CreateLinearGradientBrush(x0,yE-2,x0,yE+5,shadow1,shadow2))
gc.DrawRectangle(x0+6,yE-2,xE-12,7)
# draw gauge background
gc.SetBrush(gc.CreateLinearGradientBrush(x0,y0,x1+1,y1,cold,medium))
gc.DrawRoundedRectangle(x0,y0,x1+4,yE,6)
gc.SetBrush(gc.CreateLinearGradientBrush(x1-2,y1,xE,y1,medium,hot))
gc.DrawRoundedRectangle(x1-2,y1,xE-x1,yE,6)
# draw gauge
2011-10-25 19:58:13 +00:00
width=12
w1=y0+9-width/2
2011-10-25 19:58:13 +00:00
w2=w1+width
value=x0+max(10,min(self.width+1-2,int(self.value*self.scale)))
#gc.SetBrush(gc.CreateLinearGradientBrush(x0,y0+3,x0,y0+15,gauge1,gauge2))
#gc.SetBrush(gc.CreateLinearGradientBrush(0,3,0,15,wx.Colour(255,255,255),wx.Colour(255,90,32)))
gc.SetBrush(gc.CreateLinearGradientBrush(x0,y0+3,x0,y0+15,gauge1,self.interpolatedColour(value,x0,x1,xE,cold,medium,hot)))
2011-10-25 19:58:13 +00:00
val_path = gc.CreatePath()
val_path.MoveToPoint(x0,w1)
2011-10-25 19:58:13 +00:00
val_path.AddLineToPoint(value,w1)
val_path.AddLineToPoint(value+2,w1+width/4)
val_path.AddLineToPoint(value+2,w2-width/4)
val_path.AddLineToPoint(value,w2)
#val_path.AddLineToPoint(value-4,10)
val_path.AddLineToPoint(x0,w2)
2011-10-25 19:58:13 +00:00
gc.DrawPath(val_path)
# draw setpoint markers
setpoint=x0+max(10,int(self.setpoint*self.scale))
2011-10-25 19:58:13 +00:00
gc.SetBrush(gc.CreateBrush(wx.Brush(wx.Colour(0,0,0))))
setp_path = gc.CreatePath()
setp_path.MoveToPoint(setpoint-4,y0)
setp_path.AddLineToPoint(setpoint+4,y0)
setp_path.AddLineToPoint(setpoint,y0+5)
setp_path.MoveToPoint(setpoint-4,yE)
setp_path.AddLineToPoint(setpoint+4,yE)
setp_path.AddLineToPoint(setpoint,yE-5)
2011-10-25 19:58:13 +00:00
gc.DrawPath(setp_path)
# draw readout
2011-10-25 19:58:13 +00:00
text=u"T\u00B0 %u/%u"%(self.value,self.setpoint)
#gc.SetFont(gc.CreateFont(wx.Font(12,wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_BOLD),wx.WHITE))
#gc.DrawText(text,29,-2)
gc.SetFont(gc.CreateFont(wx.Font(10,wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_BOLD),wx.WHITE))
gc.DrawText(self.title,x0+19,y0+4)
gc.DrawText(text, x0+119,y0+4)
2011-10-25 19:58:13 +00:00
gc.SetFont(gc.CreateFont(wx.Font(10,wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_BOLD)))
gc.DrawText(self.title,x0+18,y0+3)
gc.DrawText(text, x0+118,y0+3)
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