6261 lines
295 KiB
Python
6261 lines
295 KiB
Python
'''
|
|
plasmac2 is an add-on to the LinuxCNC Axis GUI for creating
|
|
a plasma cutting configuration using the plasmac component
|
|
|
|
This program 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 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program 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.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
'''
|
|
|
|
VER = '21'
|
|
|
|
##############################################################################
|
|
# the next line suppresses undefined variable errors in VSCode #
|
|
# pyright: reportUndefinedVariable = false
|
|
##############################################################################
|
|
|
|
|
|
##############################################################################
|
|
# UPDATES #
|
|
##############################################################################
|
|
def update_check():
|
|
''' check for updates - the newest update must be added last here '''
|
|
# v15 (2024 Jan 30) set user_m_path to include <plasmac2/lib>
|
|
path = 'plasmac2/lib'
|
|
mPath = inifile.find('RS274NGC', 'USER_M_PATH')
|
|
if path not in mPath:
|
|
version = 'v15'
|
|
try:
|
|
if os.path.isfile(os.path.join(configPath, 'M190')):
|
|
os.rename(os.path.join(configPath, 'M190'), os.path.join(configPath, 'M190.bak'))
|
|
tmpFile = f'{s.ini_filename}~'
|
|
COPY(s.ini_filename, tmpFile)
|
|
with open(tmpFile, 'r') as inFile:
|
|
with open(s.ini_filename, 'w') as outFile:
|
|
for line in inFile:
|
|
if line.startswith('USER_M_PATH'):
|
|
line = line.replace(mPath, f'./:{path}')
|
|
outFile.write(line)
|
|
if os.path.isfile(tmpFile):
|
|
os.remove(tmpFile)
|
|
except Exception as e:
|
|
title = 'error'
|
|
msg0 = f"Update to {version} failed due to:\n\n{e}"
|
|
notifications.add('error', f"{msg0}\n")
|
|
else:
|
|
title = 'info'
|
|
msg0 = f"Updated successfully to {version}\nA restart is required"
|
|
notifications.add(title, f"{msg0}\n")
|
|
|
|
|
|
##############################################################################
|
|
# NEW CLASSES #
|
|
##############################################################################
|
|
# class for preferences file
|
|
prefP = configparser.ConfigParser
|
|
class plasmacPreferences(prefP):
|
|
optionxform = str
|
|
types = {bool: prefP.getboolean,
|
|
float: prefP.getfloat,
|
|
int: prefP.getint,
|
|
str: prefP.get,
|
|
repr: lambda self, section, option: eval(prefP.get(self, section, option)),
|
|
}
|
|
|
|
def __init__(self):
|
|
prefP.__init__(self, strict=False, interpolation=None)
|
|
self.fn = os.path.join(configPath, f"{vars.machine.get()}.prefs")
|
|
self.read(self.fn)
|
|
|
|
# class for materials file
|
|
matsP = configparser.ConfigParser
|
|
class plasmacMaterials(matsP):
|
|
optionxform = str
|
|
types = {bool: matsP.getboolean,
|
|
float: matsP.getfloat,
|
|
int: matsP.getint,
|
|
str: matsP.get,
|
|
repr: lambda self, section, option: eval(matsP.get(self, section, option)),
|
|
}
|
|
|
|
def __init__(self):
|
|
matsP.__init__(self)
|
|
self.fn = os.path.join(configPath, f"{vars.machine.get()}_material.cfg")
|
|
self.read(self.fn)
|
|
|
|
# class for temp materials file
|
|
tempP = configparser.ConfigParser
|
|
class plasmacTempMaterial(tempP):
|
|
optionxform = str
|
|
types = {bool: tempP.getboolean,
|
|
float: tempP.getfloat,
|
|
int: tempP.getint,
|
|
str: tempP.get,
|
|
repr: lambda self,section, option: eval(tempP.get(self, section, option)),
|
|
}
|
|
|
|
def __init__(self):
|
|
tempP.__init__(self)
|
|
self.fn = os.path.join(tmpPath, f"{vars.machine.get()}_material.gcode")
|
|
self.read(self.fn)
|
|
|
|
# class for popup dialogs
|
|
class plasmacPopUp(Tkinter.Toplevel):
|
|
def __init__(self, func, title, msg, vkb=None, optional=None):
|
|
super().__init__(root_window)
|
|
self.attributes('-type', 'popup_menu')
|
|
self.overrideredirect(True)
|
|
if pVars.popLocation.get() == 'pointer':
|
|
rE(f"tk::PlaceWindow {self} pointer")
|
|
elif pVars.popLocation.get() == 'gui center':
|
|
rE(f"tk::PlaceWindow {self} widget {root_window}")
|
|
else:
|
|
rE(f"tk::PlaceWindow {self} center")
|
|
self.wait_visibility()
|
|
if func != 'offsets':
|
|
self.grab_set()
|
|
self.title(title)
|
|
self.protocol("WM_DELETE_WINDOW", lambda:self.popup_complete(False, False))
|
|
self.frm = Tkinter.Frame(self, bg=colorBack, bd=2, relief='ridge')
|
|
ttl = Tkinter.Label(self.frm, text=title, fg=colorBack, bg=colorFore)
|
|
ttl.pack(fill='x')
|
|
b1Text = b2Text = b3Text = b4Text = None
|
|
if func == 'rfl_type':
|
|
b1Text, b2Text = self.popup_rfl_type(func)
|
|
elif func == 'rfl':
|
|
b1Text, b2Text = self.popup_run_from_line(func)
|
|
elif func == 'sc':
|
|
b1Text, b2Text = self.popup_single_cut(func)
|
|
elif func == 'offsets':
|
|
b1Text, b2Text, b3Text, b4Text = self.popup_entry(func, msg, optional)
|
|
else:
|
|
b1Text, b2Text = self.popup_entry(func, msg, optional)
|
|
bbox = Tkinter.Frame(self.frm, bg=colorBack)
|
|
b1Value = True if func != 'offsets' else 'laser'
|
|
b1 = Tkinter.Button(bbox, text=b1Text, command=lambda:self.popup_complete(b1Value, func), width=8)
|
|
b1.configure(fg=colorFore, bg=colorBack, activebackground=colorBack, highlightthickness=0)
|
|
b1.pack(side='left')
|
|
b2Value = False if func != 'offsets' else 'scribe'
|
|
if b2Text:
|
|
b2 = Tkinter.Button(bbox, text=b2Text, command=lambda:self.popup_complete(b2Value, func), width=8)
|
|
b2.configure(fg=colorFore, bg=colorBack, activebackground=colorBack, highlightthickness=0)
|
|
b2.pack(side='left', padx=(8,0))
|
|
if b3Text:
|
|
b3 = Tkinter.Button(bbox, text=b3Text, command=lambda:self.popup_complete('probe', func), width=8)
|
|
b3.configure(fg=colorFore, bg=colorBack, activebackground=colorBack, highlightthickness=0)
|
|
b3.pack(side='left', padx=(8,0))
|
|
if b4Text:
|
|
b4 = Tkinter.Button(bbox, text=b4Text, command=lambda:self.popup_complete('cancel', func), width=8)
|
|
b4.configure(fg=colorFore, bg=colorBack, activebackground=colorBack, highlightthickness=0)
|
|
b4.pack(side='left', padx=(8,0))
|
|
bbox.pack(padx=4, pady=4)
|
|
self.frm.pack()
|
|
if vkb:
|
|
vkbData['required'] = True
|
|
vkb_show(vkb)
|
|
root_window.wait_window(self)
|
|
|
|
def popup_rfl_type(self, func):
|
|
self.rflType = Tkinter.StringVar(self, 'run')
|
|
f1 = Tkinter.Frame(self.frm, bg=colorBack)
|
|
run = Tkinter.Radiobutton(f1, text=_('Here to end'), variable=self.rflType, value='run', width=12, bg=colorBack, highlightthickness=0, anchor='w')
|
|
cut = Tkinter.Radiobutton(f1, text=_('This cutpath'), variable=self.rflType, value='cut', width=12, bg=colorBack, highlightthickness=0, anchor='w')
|
|
run.pack(anchor='w')
|
|
cut.pack(anchor='w')
|
|
f1.pack(padx=4, pady=4, anchor='w')
|
|
return _('OK'), _('Cancel')
|
|
|
|
def popup_run_from_line(self, func):
|
|
self.leadIn = Tkinter.BooleanVar()
|
|
self.leadLength = Tkinter.StringVar()
|
|
self.leadAngle = Tkinter.StringVar()
|
|
f1 = Tkinter.Frame(self.frm, bg=colorBack)
|
|
lbl1 = Tkinter.Label(f1, text=_('Use Leadin:'), fg=colorFore, bg=colorBack, width=12, anchor='e')
|
|
lbl1.pack(side='left')
|
|
leadinDo = Tkinter.Checkbutton(f1, fg=colorFore, bg=colorBack, variable=self.leadIn, indicatoron=False, width=2, bd=1)
|
|
leadinDo.configure(highlightthickness=0, activebackground=colorBack, selectcolor=colorActive, relief='raised', overrelief='raised')
|
|
leadinDo.pack(side='left')
|
|
f1.pack(padx=4, pady=4, anchor='w')
|
|
f2 = Tkinter.Frame(self.frm, bg=colorBack)
|
|
lbl2 = Tkinter.Label(f2, text=_('Leadin Length:'), fg=colorFore, bg=colorBack, width=12, anchor='e')
|
|
lbl2.pack(side='left')
|
|
leadinLength = Tkinter.Spinbox(f2, fg=colorFore, bg=colorBack, textvariable=self.leadLength, width=10)
|
|
leadinLength.configure(highlightthickness=0)
|
|
leadinLength.pack(side='left')
|
|
f2.pack(padx=4, pady=4, anchor='w')
|
|
f3 = Tkinter.Frame(self.frm, bg=colorBack)
|
|
lbl3 = Tkinter.Label(f3, text=_('Leadin Angle:'), fg=colorFore, bg=colorBack, width=12, anchor='e')
|
|
lbl3.pack(side='left')
|
|
leadinAngle = Tkinter.Spinbox(f3, fg=colorFore, bg=colorBack, textvariable=self.leadAngle, width=10)
|
|
leadinAngle.configure(highlightthickness=0)
|
|
leadinAngle.pack(side='left')
|
|
f3.pack(padx=4, pady=4, anchor='w')
|
|
self.leadIn.set(False)
|
|
if s.linear_units == 1:
|
|
leadinLength.config(width=10, from_=1, to=25, increment=1, format='%0.0f', wrap=1)
|
|
self.leadLength.set(5)
|
|
else:
|
|
leadinLength.config(width=10, from_=0.05, to=1, increment=0.05, format='%0.2f', wrap=1)
|
|
self.leadLength.set(0.2)
|
|
leadinAngle.config(width=10, from_=-359, to=359, increment=1, format='%0.0f', wrap=1)
|
|
self.leadAngle.set(0)
|
|
return _('Load'), _('Cancel')
|
|
|
|
def popup_single_cut(self, func):
|
|
self.xLength = Tkinter.StringVar()
|
|
self.yLength = Tkinter.StringVar()
|
|
f1 = Tkinter.Frame(self.frm, bg=colorBack)
|
|
lbl1 = Tkinter.Label(f1, text=_('X Length:'), fg=colorFore, bg=colorBack, width=12, anchor='e')
|
|
lbl1.pack(side='left')
|
|
xLength = Tkinter.Entry(f1, fg=colorFore, bg=colorBack, textvariable=self.xLength, width=10)
|
|
xLength.configure(highlightthickness=0)
|
|
xLength.pack(side='left')
|
|
f1.pack(padx=4, pady=4, anchor='w')
|
|
f2 = Tkinter.Frame(self.frm, bg=colorBack)
|
|
lbl2 = Tkinter.Label(f2, text=_('Y Length:'), fg=colorFore, bg=colorBack, width=12, anchor='e')
|
|
lbl2.pack(side='left')
|
|
yLength = Tkinter.Entry(f2, fg=colorFore, bg=colorBack, textvariable=self.yLength, width=10)
|
|
yLength.configure(highlightthickness=0)
|
|
yLength.pack(side='left')
|
|
f2.pack(padx=4, pady=4, anchor='w')
|
|
self.xLength.set(getPrefs(PREF, 'SINGLE_CUT', 'X length', 0, float))
|
|
self.yLength.set(getPrefs(PREF, 'SINGLE_CUT', 'Y length', 0, float))
|
|
return _('Load'), _('Cancel')
|
|
|
|
def popup_entry(self, func, msg, optional):
|
|
label = Tkinter.Label(self.frm, text=msg, fg=colorFore, bg=colorBack)
|
|
if msg[:3] == '1. ':
|
|
label.configure(justify='left')
|
|
label.pack(padx=4, pady=4)
|
|
if func in ['entry', 'touch']:
|
|
self.entry = Tkinter.Entry(self.frm, justify='right', fg=colorFore, bg=colorBack)
|
|
self.entry.configure(highlightthickness=0, selectforeground=colorBack, selectbackground=colorFore)
|
|
if optional is not None:
|
|
self.entry.insert('end', optional)
|
|
self.entry.pack(padx=4, pady=4)
|
|
self.entry.focus_set()
|
|
if func == 'touch':
|
|
self.entry.insert('end', '0.0')
|
|
opl = Tkinter.Label(self.frm, text=_('Coordinate System'), fg=colorFore, bg=colorBack)
|
|
opl.pack(padx=4, pady=4)
|
|
self.c = c = StringVar(t)
|
|
c.set(optional)
|
|
self.opt = Tkinter.OptionMenu(self.frm, c, *all_systems[:])
|
|
self.opt.configure(fg=colorFore, bg=colorBack, activebackground=colorBack, highlightthickness=0)
|
|
self.opt.children['menu'].configure(fg=colorFore, bg=colorBack, activeforeground=colorBack, activebackground=colorFore)
|
|
self.opt.pack(padx=4, pady=4)
|
|
if func in ['info', 'error', 'warn']:
|
|
return _('OK'), None
|
|
elif func in ['yesno']:
|
|
return _('Yes'), _('No')
|
|
elif func in ['offsets']:
|
|
return _('Laser'), _('Scribe'), _('Offset Probe'), _('Cancel')
|
|
elif func in ['entry', 'touch']:
|
|
return _('OK'), _('Cancel')
|
|
|
|
def popup_complete(self, value, func):
|
|
if func == 'rfl_type':
|
|
self.reply = value, self.rflType.get()
|
|
elif func == 'rfl':
|
|
self.reply = value, self.leadIn.get(), float(self.leadLength.get()), float(self.leadAngle.get())
|
|
elif func == 'sc':
|
|
self.reply = value, self.xLength.get(), self.yLength.get()
|
|
elif func in ['entry']:
|
|
self.reply = value, self.entry.get()
|
|
elif func in ['touch']:
|
|
self.reply = value, self.entry.get(), self.c.get()
|
|
else:
|
|
self.reply = value
|
|
self.destroy()
|
|
|
|
|
|
##############################################################################
|
|
# PREFERENCE FUNCTIONS #
|
|
##############################################################################
|
|
def getPrefs(prefs, section, option, default=False, typ=bool):
|
|
m = prefs.types.get(typ)
|
|
if prefs.has_section(section):
|
|
if prefs.has_option(section, option):
|
|
try:
|
|
return m(prefs, section, option)
|
|
except Exception as err:
|
|
msg0 = f"[{section}]{option} is invalid, default of {typ(default)} applied"
|
|
notifications.add('error', f"{msg0}\n")
|
|
prefs.set(section, option, str(typ(default)))
|
|
prefs.write(open(prefs.fn, 'w'))
|
|
return typ(default)
|
|
else:
|
|
prefs.set(section, option, str(typ(default)))
|
|
prefs.write(open(prefs.fn, 'w'))
|
|
print(f"Preferences file, adding {option} to [{section}] section")
|
|
return typ(default)
|
|
else:
|
|
prefs.add_section(section)
|
|
prefs.set(section, option, str(typ(default)))
|
|
prefs.write(open(prefs.fn, 'w'))
|
|
print(f"Preferences file, adding [{section}] section")
|
|
print(f"Preferences file, adding {option} to [{section}] section")
|
|
return typ(default)
|
|
|
|
def putPrefs(prefs, section, option, value, typ=bool):
|
|
if prefs.has_section(section):
|
|
prefs.set(section, option, str(typ(value)))
|
|
prefs.write(open(prefs.fn, 'w'))
|
|
else:
|
|
prefs.add_section(section)
|
|
prefs.set(section.upper(), option, str(typ(value)))
|
|
prefs.write(open(prefs.fn, 'w'))
|
|
|
|
def removePrefsSect(prefs, section):
|
|
prefs.remove_section(section)
|
|
prefs.write(open(prefs.fn, 'w'))
|
|
|
|
def sortPrefs(prefs):
|
|
prefs._sections = OrderedDict(sorted(prefs._sections.items(), key=lambda t: int(t[0].rsplit('_',1)[1]) ))
|
|
prefs.write(open(prefs.fn, 'w'))
|
|
|
|
|
|
##############################################################################
|
|
# WINDOW FUNCTIONS #
|
|
##############################################################################
|
|
def mode_changed():
|
|
if pVars.plasmacMode.get() == 2:
|
|
rE(f"grid forget {foverride}")
|
|
rE(f"grid forget {fplasma}.arcvl")
|
|
rE(f"grid forget {fplasma}.arc-voltage")
|
|
rE(f"grid forget {fleds}.led-void-locked")
|
|
rE(f"grid forget {fleds}.led-void-lockedL")
|
|
rE(f"grid forget {fruns}.check.av")
|
|
rE(f"grid forget {fruns}.check.avL")
|
|
rE(f"grid forget {fparam}.c2.thc.thc-auto")
|
|
rE(f"grid forget {fparam}.c2.thc.thc-autoL")
|
|
rE(f"grid forget {fparam}.c2.thc.thc-delay")
|
|
rE(f"grid forget {fparam}.c2.thc.thc-delayL")
|
|
rE(f"grid forget {fparam}.c2.thc.thc-sample-counts")
|
|
rE(f"grid forget {fparam}.c2.thc.thc-sample-countsL")
|
|
rE(f"grid forget {fparam}.c2.thc.thc-sample-threshold")
|
|
rE(f"grid forget {fparam}.c2.thc.thc-sample-thresholdL")
|
|
rE(f"grid forget {fparam}.c2.thc.thc-threshold")
|
|
rE(f"grid forget {fparam}.c2.thc.thc-thresholdL")
|
|
rE(f"grid forget {fparam}.c2.thc.pid-i-gain")
|
|
rE(f"grid forget {fparam}.c2.thc.pid-i-gainL")
|
|
rE(f"grid forget {fparam}.c2.thc.pid-d-gain")
|
|
rE(f"grid forget {fparam}.c2.thc.pid-d-gainL")
|
|
rE(f"grid forget {fparam}.c2.thc.voidlock-slope")
|
|
rE(f"grid forget {fparam}.c2.thc.voidlock-slopeL")
|
|
rE(f"grid forget {fparam}.c3.arc.arc-voltage-scale")
|
|
rE(f"grid forget {fparam}.c3.arc.arc-voltage-scaleL")
|
|
rE(f"grid forget {fparam}.c3.arc.arc-voltage-offset")
|
|
rE(f"grid forget {fparam}.c3.arc.arc-voltage-offsetL")
|
|
rE(f"grid forget {fparam}.c3.arc.arc-ok-high")
|
|
rE(f"grid forget {fparam}.c3.arc.arc-ok-highL")
|
|
rE(f"grid forget {fparam}.c3.arc.arc-ok-low")
|
|
rE(f"grid forget {fparam}.c3.arc.arc-ok-lowL")
|
|
elif pVars.plasmacMode.get() == 1:
|
|
rE(f"grid forget {fparam}.c3.arc.arc-ok-high")
|
|
rE(f"grid forget {fparam}.c3.arc.arc-ok-highL")
|
|
rE(f"grid forget {fparam}.c3.arc.arc-ok-low")
|
|
rE(f"grid forget {fparam}.c3.arc.arc-ok-lowL")
|
|
else:
|
|
rE(f"grid {fparam}.c3.arc.arc-ok-highL -column 0 -row 5 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c3.arc.arc-ok-high -column 1 -row 5 -sticky e -padx {{0 4}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c3.arc.arc-ok-lowL -column 0 -row 6 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c3.arc.arc-ok-low -column 1 -row 6 -sticky e -padx {{0 4}} -pady {{4 0}}")
|
|
if pVars.plasmacMode.get() < 2:
|
|
rE(f"grid {foverride} -column 0 -row 3 -padx 2 -pady {{0 4}} -sticky w")
|
|
rE(f"grid {fplasma}.arcvl -column 0 -row 0 -sticky nw")
|
|
rE(f"grid {fplasma}.arc-voltage -column 0 -row 1 -sticky se -rowspan 2")
|
|
rE(f"grid {fleds}.led-void-locked -column 4 -row 3 -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fleds}.led-void-lockedL -column 5 -row 3 -padx {{0 0}} -pady {{4 0}} -sticky W")
|
|
rE(f"grid {fruns}.check.av -column 0 -row 0 -sticky w")
|
|
rE(f"grid {fruns}.check.avL -column 1 -row 0 -sticky w")
|
|
rE(f"grid {fparam}.c2.thc.thc-autoL -column 0 -row 0 -sticky e")
|
|
rE(f"grid {fparam}.c2.thc.thc-auto -column 1 -row 0 -sticky e -padx {{0 4}}")
|
|
if pVars.thcAuto.get():
|
|
rE(f"grid forget {fparam}.c2.thc.thc-delay")
|
|
rE(f"grid forget {fparam}.c2.thc.thc-delayL")
|
|
rE(f"grid {fparam}.c2.thc.thc-sample-countsL -column 0 -row 2 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c2.thc.thc-sample-counts -column 1 -row 2 -sticky e -padx {{0 4}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c2.thc.thc-sample-thresholdL -column 0 -row 3 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c2.thc.thc-sample-threshold -column 1 -row 3 -sticky e -padx {{0 4}} -pady {{4 0}}")
|
|
else:
|
|
rE(f"grid forget {fparam}.c2.thc.thc-sample-counts")
|
|
rE(f"grid forget {fparam}.c2.thc.thc-sample-countsL")
|
|
rE(f"grid forget {fparam}.c2.thc.thc-sample-threshold")
|
|
rE(f"grid forget {fparam}.c2.thc.thc-sample-thresholdL")
|
|
rE(f"grid {fparam}.c2.thc.thc-delayL -column 0 -row 1 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c2.thc.thc-delay -column 1 -row 1 -sticky e -padx {{0 4}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c2.thc.thc-thresholdL -column 0 -row 4 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c2.thc.thc-threshold -column 1 -row 4 -sticky e -padx {{0 4}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c2.thc.pid-i-gainL -column 0 -row 6 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c2.thc.pid-i-gain -column 1 -row 6 -sticky e -padx {{0 4}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c2.thc.pid-d-gainL -column 0 -row 7 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c2.thc.pid-d-gain -column 1 -row 7 -sticky e -padx {{0 4}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c2.thc.voidlock-slopeL -column 0 -row 9 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c2.thc.voidlock-slope -column 1 -row 9 -sticky e -padx {{0 4}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c3.arc.arc-voltage-scaleL -column 0 -row 3 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c3.arc.arc-voltage-scale -column 1 -row 3 -sticky e -padx {{0 4}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c3.arc.arc-voltage-offsetL -column 0 -row 4 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c3.arc.arc-voltage-offset -column 1 -row 4 -sticky e -padx {{0 4}} -pady {{4 0}}")
|
|
hal.set_p('plasmac.mode', str(pVars.plasmacMode.get()))
|
|
|
|
def cone_size_changed():
|
|
o.set_cone_basesize(float(rE(f"{fsetup}.l.gui.cone get")))
|
|
|
|
def font_changed(value=0):
|
|
if value:
|
|
populate_gcode_fonts()
|
|
if 'mono' not in pVars.codeFont.get().lower():
|
|
pVars.codeFont.set(pVars.guiFont.get())
|
|
global lastFontSize
|
|
rE(f"font configure TkDefaultFont -family {{{pVars.guiFont.get()}}} -size {pVars.fontSize.get()}")
|
|
rE(f"font configure fontGui -family {{{pVars.guiFont.get()}}} -size {pVars.fontSize.get()}")
|
|
rE(f"font configure fontArc -family {{{pVars.guiFont.get()}}} -size {int(pVars.fontSize.get())*3}")
|
|
rE(f"font configure fontCode -family {{{pVars.codeFont.get()}}} -size {pVars.fontSize.get()}")
|
|
rE(f".info.gcodef.gcodes configure -font fontGui")
|
|
rE(f"{fplasma}.arc-voltage configure -font fontArc")
|
|
rE(f".pane.bottom.t.text configure -font fontCode")
|
|
if s.paused:
|
|
txt = _('Cut Recovery')
|
|
rE(f"{ftabs} itemconfigure cutrecs -text {txt}")
|
|
else:
|
|
rE(f"{ftabs} delete manual 0")
|
|
rE(f"{ftabs} delete mdi 0")
|
|
rE(f"{ftabs} insert end manual")
|
|
rE(f"{ftabs} insert end mdi")
|
|
rE(f"{ftabs} raise manual")
|
|
txt = _('Manual')
|
|
rE(f"{ftabs} itemconfigure manual -text {txt}")
|
|
txt = _('MDI')
|
|
rE(f"{ftabs} itemconfigure mdi -text {txt}")
|
|
rE(f"{fright} delete preview 0")
|
|
rE(f"{fright} delete numbers 0")
|
|
rE(f"{fright} delete stats 0")
|
|
rE(f"{fright} insert end preview")
|
|
rE(f"{fright} insert end numbers")
|
|
rE(f"{fright} insert end stats")
|
|
rE(f"{fright} raise preview")
|
|
txt = _('Preview')
|
|
rE(f"{fright} itemconfigure preview -text {txt}")
|
|
txt = _('DRO')
|
|
rE(f"{fright} itemconfigure numbers -text {txt}")
|
|
txt = _('Statistics')
|
|
rE(f"{fright} itemconfigure stats -text {txt}")
|
|
for nbook in [ftabs, fright]:
|
|
pages = rE(f"{nbook} pages").split()
|
|
for page in pages:
|
|
rE(f"{nbook} itemconfigure {page} -foreground {colorFore} -background {colorBack}")
|
|
rE(f"{fright}.fpreview configure -bd 2")
|
|
rE(f"{fright}.fnumbers configure -bd 2")
|
|
rE(f"{fright}.fstats configure -bd 2")
|
|
for box in spinBoxes:
|
|
rE(f"{box} configure -font fontGui")
|
|
for box in rSpinBoxes:
|
|
rE(f"{box} configure -font fontGui")
|
|
ledFrame = int(pVars.fontSize.get()) * 2
|
|
ledScale = int(pVars.fontSize.get()) / int(lastFontSize)
|
|
lastFontSize = pVars.fontSize.get()
|
|
for led in wLeds:
|
|
rE(f"{led} configure -width {ledFrame} -height {ledFrame}")
|
|
rE(f"{led} scale 1 1 1 {ledScale} {ledScale}")
|
|
bSize = int(int(pVars.fontSize.get()) / 10 * 24) if int(pVars.fontSize.get()) > 10 else 24
|
|
for w in toolButtons:
|
|
rE(f".toolbar.{w} configure -width {bSize} -height {bSize}")
|
|
for w in matButtons:
|
|
rE(f"{toolmat}.{w} configure -width {bSize} -height {bSize}")
|
|
get_coordinate_font(None)
|
|
set_window_size()
|
|
# set combobox list widths
|
|
longest = max(fontsGui, key=len)
|
|
l = Label(bd=0, padx=0, pady=0, highlightthickness=0, font='fontGui', text=longest)
|
|
ll = int(rE(f"winfo reqwidth {l}")) + 20
|
|
rE(f"{fsetup}.l.gui.fgui configure -listboxwidth {ll}")
|
|
longest = max(fontsCode, key=len)
|
|
l = Label(bd=0, padx=0, pady=0, highlightthickness=0, font='fontCode', text=longest)
|
|
ll = int(rE(f"winfo reqwidth {l}")) + 20
|
|
rE(f"{fsetup}.l.gui.fcode configure -listboxwidth {ll}")
|
|
material_list_width()
|
|
|
|
def material_list_width():
|
|
if rE(f"{fruns}.material.materials cget -values"):
|
|
longest = max(tuple_from_tcl_string(matNames), key=len)
|
|
l = Label(bd=0, padx=0, pady=0, highlightthickness=0, font='fontGui', text=longest)
|
|
ll = int(rE(f"winfo reqwidth {l}")) + 20
|
|
rE(f"{fruns}.material.materials configure -listboxwidth {ll}")
|
|
|
|
def populate_gcode_fonts():
|
|
for font in sorted(fontsCode):
|
|
rE(f"{fsetup}.l.gui.fcode insert end {{{font}}}")
|
|
|
|
def tuple_from_tcl_string(str):
|
|
multi = False
|
|
tmp = ''
|
|
tup = ()
|
|
for char in str:
|
|
if char == '{':
|
|
multi = True
|
|
elif char == '}':
|
|
if tmp and tmp not in tup:
|
|
tup += (tmp,)
|
|
tmp = ''
|
|
multi = False
|
|
elif multi:
|
|
tmp += char
|
|
elif char == ' ':
|
|
if tmp and tmp not in tup:
|
|
tup += (tmp,)
|
|
tmp = ''
|
|
else:
|
|
tmp += char
|
|
if tmp and tmp not in tup:
|
|
tup += (tmp,)
|
|
return(tup)
|
|
|
|
def close_window():
|
|
rE(f"focus {fbuttons}.torch-enable")
|
|
vkb_hide()
|
|
if pVars.closeDialog.get():
|
|
msgs = ''
|
|
if pVars.closeText.get():
|
|
customText = getPrefs(PREF, 'GUI_OPTIONS', 'Exit warning text', '', str).split('\\')
|
|
if customText:
|
|
for t in customText:
|
|
msgs += f"{t}\n\n"
|
|
text2 = _('Do you really want to close LinuxCNC ?')
|
|
msgs += text2
|
|
if not plasmacPopUp('yesno', _('CONFIRM CLOSE'), msgs).reply:
|
|
return
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Window last', rE(f"winfo geometry {root_window}").split('+', 1)[0], str)
|
|
if hal.component_exists('pmx485'):
|
|
hal.set_p('pmx485.enable', '0')
|
|
root_window.destroy()
|
|
|
|
def set_window_size(winSize=False):
|
|
global wSize, bPane
|
|
winSize = rE(f"winfo geometry {root_window}").split('+', 1)[0] if winSize == 'combo' else winSize
|
|
size = pVars.winSize.get()
|
|
if size not in ['default', 'last', 'fullscreen', 'maximized']:
|
|
msg0 = _('Invalid parameters in [GUI_OPTIONS]Window size in preferences file')
|
|
notifications.add('error', f"{msg0}\n")
|
|
return False
|
|
else:
|
|
if pVars.orient.get() == 'portrait':
|
|
# window height, window height with pmx enabled, window width, bottom pane height
|
|
wSize = { '7': [ 720, 756, 644, 92], '8': [ 7588, 796, 644, 102],
|
|
'9': [ 814, 856, 662, 108], '10': [ 880, 924, 664, 116],
|
|
'11': [ 918, 966, 734, 124], '12': [ 962, 1012, 806, 132],
|
|
'13': [1058, 1114, 878, 140], '14': [1102, 1158, 950, 148],
|
|
'15': [1146, 1206,1024, 156], '16': [1214, 1278,1094, 164],
|
|
'17': [1270, 1336,1166, 172], '18': [1334, 1404,1166, 180],
|
|
'19': [1366, 1438,1240, 188], '20': [1442, 1514,1310, 196],
|
|
}
|
|
offset = 1 if pmPort else 0
|
|
height = wSize[pVars.fontSize.get()][offset]
|
|
width = wSize[pVars.fontSize.get()][2]
|
|
bPane = wSize[pVars.fontSize.get()][3]
|
|
else:
|
|
# window height, bottom pane height
|
|
wSize = { '7': [456, 92], '8': [482, 102],
|
|
'9': [516, 108], '10': [562, 116],
|
|
'11': [586, 124], '12': [612, 132],
|
|
'13': [686, 140], '14': [710, 148],
|
|
'15': [736, 156], '16': [784, 164],
|
|
'17': [811, 172], '18': [858, 180],
|
|
'19': [882, 188], '20': [932, 196],
|
|
}
|
|
height = wSize[pVars.fontSize.get()][0]
|
|
width = int(height * 1.75)
|
|
bPane = wSize[pVars.fontSize.get()][1]
|
|
rE(f".pane paneconfigure $pane_top -minsize {bPane}")
|
|
rE(f".pane paneconfigure $pane_bottom -minsize {bPane}")
|
|
rE(f".pane paneconfigure $pane_bottom -height {bPane}")
|
|
if size == 'maximized':
|
|
root_window.attributes('-fullscreen', False, '-zoomed', True)
|
|
elif size == 'fullscreen':
|
|
root_window.attributes('-fullscreen', True, '-zoomed', False)
|
|
else:
|
|
root_window.attributes('-fullscreen', False, '-zoomed', False)
|
|
last = winSize if winSize else restoreSetup['winLast']
|
|
if size == 'last' and last != 'none':
|
|
width = int(last.split('x')[0])
|
|
height = int(last.split('x')[1])
|
|
xPos = int((root_window.maxsize()[0] - width) / 2)
|
|
yPos = int((root_window.maxsize()[1] - height) / 2)
|
|
root_window.geometry(f"{width}x{height}+{xPos}+{yPos}")
|
|
rE(f"{fsetup}.r.ubuttons.canvas xview moveto 0.0")
|
|
rE(f"{fsetup}.r.ubuttons.canvas yview moveto 0.0")
|
|
root_window.update_idletasks()
|
|
|
|
def wcs_rotation(mode):
|
|
global currentX, currentY, currentRot
|
|
if mode == 'get':
|
|
currentX = s.g5x_offset[0]
|
|
currentY = s.g5x_offset[1]
|
|
currentRot = s.rotation_xy
|
|
elif mode == 'set':
|
|
ensure_mode(linuxcnc.MODE_MDI)
|
|
c.mdi(f"G10 L2 P0 X{currentX} Y{currentY} R{currentRot}")
|
|
c.wait_complete()
|
|
if currentRot != s.rotation_xy:
|
|
reload_file()
|
|
|
|
def preview_toggle(conv=False):
|
|
if pVars.previewLarge.get() or conv:
|
|
rE('grid forget .pane.top.tabs')
|
|
rE(f"grid forget {ftop}.feedoverride")
|
|
rE(f"grid forget {ftop}.rapidoverride")
|
|
rE(f"grid forget {ftop}.jogspeed")
|
|
rE(f"grid forget {ftop}.ajogspeed")
|
|
rE('.pane paneconfigure $pane_bottom -minsize 1')
|
|
rE('.pane paneconfigure $pane_bottom -height 1')
|
|
if pVars.orient.get() == 'portrait':
|
|
rE(f"grid forget {fportrait}")
|
|
else:
|
|
rE(f"grid forget {fbuttons}")
|
|
rE(f"grid forget {toolmat}")
|
|
rE(f"grid forget {fruns}")
|
|
else:
|
|
rE('grid .pane.top.tabs -column 0 -row 1 -sticky nesw -padx 2 -pady 2')
|
|
rE('grid .pane.top.feedoverride -column 0 -row 2 -sticky new')
|
|
rE('grid .pane.top.rapidoverride -column 0 -row 3 -sticky new')
|
|
rE('grid .pane.top.jogspeed -column 0 -row 5 -sticky new')
|
|
# test if we need the angular jog slider (56 = 0x38 = 000111000 = ABC)
|
|
if s.axis_mask & 56 == 0 and 'ANGULAR' in joint_type:
|
|
rE('grid .pane.top.ajogspeed -column 0 -row 6 -sticky new')
|
|
rE(f".pane paneconfigure $pane_top -minsize {bPane}")
|
|
rE(f".pane paneconfigure $pane_bottom -minsize {bPane}")
|
|
rE(f".pane paneconfigure $pane_bottom -height {bPane}")
|
|
populate_run_panel()
|
|
|
|
def setup_toggle(state):
|
|
if int( state):
|
|
hide_default()
|
|
enable_menus(False)
|
|
rE('grid .toolsetup -column 0 -row 0 -columnspan 3 -sticky nesw')
|
|
rE(f"grid {fsetup} -column 1 -row 1 -rowspan 2 -sticky nsew")
|
|
keyboard_bindings(False)
|
|
vkbData['required'] = True
|
|
vkb_show('keyboard')
|
|
else:
|
|
rE('grid forget .toolsetup')
|
|
rE(f"grid forget {fsetup}")
|
|
show_default()
|
|
|
|
def param_toggle(state):
|
|
if int(state):
|
|
hide_default()
|
|
enable_menus(False)
|
|
rE('grid .toolparam -column 0 -row 0 -columnspan 3 -sticky nesw')
|
|
rE(f"grid {fparam} -column 1 -row 1 -rowspan 2 -sticky nsew")
|
|
keyboard_bindings(False)
|
|
vkbData['required'] = True
|
|
vkb_show('numpad')
|
|
else:
|
|
rE('grid forget .toolparam')
|
|
rE(f"grid forget {fparam}")
|
|
show_default()
|
|
|
|
def conv_toggle(state, convSent=False):
|
|
global CONV, convFirstRun, preConvFile, loaded_file, lastViewType
|
|
if int(state):
|
|
lastViewType = get_view_type()
|
|
preview_toggle(True)
|
|
enable_menus(False)
|
|
if pVars.orient.get() == 'portrait':
|
|
rE('grid .toolconv -column 1 -row 2 -columnspan 1 -sticky nesw')
|
|
rE('grid .fconv -column 1 -row 3 -rowspan 1 -sticky nsew')
|
|
else:
|
|
rE('grid .toolconv -column 0 -row 0 -columnspan 3 -sticky nesw')
|
|
rE('grid .fconv -column 0 -row 1 -rowspan 2 -sticky nsew')
|
|
rE(f"{fright} itemconfigure numbers -state disabled")
|
|
for page in rE(f"{fright} pages").split():
|
|
if page != 'preview':
|
|
rE(f"{fright} itemconfigure {page} -state disabled")
|
|
rE(f"{fright} raise preview")
|
|
matIndex = rE(f"{fruns}.material.materials getvalue")
|
|
if comp['development']:
|
|
reload(conversational)
|
|
if convFirstRun or comp['development']:
|
|
CONV = conversational.Conv(convFirstRun, root_window, widgets.toolFrame, \
|
|
widgets.convFrame, bwidget.ComboBox, imagePath, tmpPath, pVars, \
|
|
unitsPerMm, comp, PREF, getPrefs, putPrefs, open_file_guts, \
|
|
wcs_rotation, conv_toggle, color_change, plasmacPopUp, o)
|
|
convFirstRun = False
|
|
# set_conv_preview()
|
|
if loaded_file:
|
|
COPY(loaded_file, preConvFile)
|
|
CONV.start(materialFileDict, matIndex, vars.taskfile.get(), s.g5x_index, commands.set_view_z)
|
|
set_conv_preview()
|
|
keyboard_bindings(False)
|
|
vkbData['required'] = True
|
|
vkb_show('numpad')
|
|
else:
|
|
preview_toggle()
|
|
rE('grid forget .toolconv')
|
|
rE('grid forget .fconv')
|
|
show_default()
|
|
for page in rE(f"{fright} pages").split():
|
|
rE(f"{fright} itemconfigure {page} -state normal")
|
|
reset_conv_preview()
|
|
if convSent:
|
|
loaded_file = vars.taskfile.get()
|
|
else:
|
|
if loaded_file:
|
|
if 'shape.ngc' in loaded_file:
|
|
COPY(preConvFile, loaded_file)
|
|
open_file_guts(loaded_file, True, False)
|
|
commands.set_view_z()
|
|
else:
|
|
clear_program()
|
|
root_window.update_idletasks()
|
|
if lastViewType == 'p':
|
|
commands.set_view_p()
|
|
elif lastViewType == 't':
|
|
commands.set_view_t()
|
|
else:
|
|
commands.set_view_z()
|
|
CONV.oldConvButton = 'line'
|
|
|
|
def clear_program():
|
|
file = os.path.join(tmpPath, 'clear.ngc')
|
|
with open(file, 'w') as outFile:
|
|
outFile.write('m2')
|
|
open_file_guts(file, True, False)
|
|
t.configure(state='normal')
|
|
t.delete(0.0, 'end')
|
|
t.configure(state='disabled')
|
|
|
|
def set_conv_preview():
|
|
''' configure the preview for conversational '''
|
|
global convViewOptions, joint_dro_format_old , dro_format_old
|
|
convViewOptions['alpha'] = vars.program_alpha.get()
|
|
convViewOptions['dtg'] = vars.show_distance_to_go.get()
|
|
convViewOptions['extents'] = vars.show_extents.get()
|
|
convViewOptions['limits'] = vars.show_machine_limits.get()
|
|
convViewOptions['offsets'] = vars.show_offsets.get()
|
|
convViewOptions['plot'] = vars.show_live_plot.get()
|
|
convViewOptions['rapids'] = vars.show_rapids.get()
|
|
convViewOptions['speed'] = vars.show_machine_speed.get()
|
|
convViewOptions['tool'] = vars.show_tool.get()
|
|
convViewOptions['cone'] = o.cone_basesize
|
|
convViewOptions['origin'] = o.show_small_origin
|
|
vars.program_alpha.set(False)
|
|
vars.show_distance_to_go.set(False)
|
|
vars.show_extents.set(True)
|
|
vars.show_machine_limits.set(False)
|
|
vars.show_offsets.set(False)
|
|
vars.show_live_plot.set(False)
|
|
vars.show_rapids.set(True)
|
|
vars.show_machine_speed.set(False)
|
|
vars.show_tool.set(False)
|
|
o.cone_basesize = .025
|
|
o.show_small_origin = False
|
|
o.hide_icons = True
|
|
o.set_view_z()
|
|
joint_dro_format_old = o.joint_dro_format
|
|
o.joint_dro_format = joint_dro_format_new
|
|
dro_format_old = o.dro_format
|
|
o.dro_format = dro_format_new
|
|
|
|
|
|
def reset_conv_preview():
|
|
''' configure the preview for gcode file '''
|
|
global convViewOptions
|
|
vars.program_alpha.set(convViewOptions['alpha'])
|
|
vars.show_distance_to_go.set(convViewOptions['dtg'])
|
|
vars.show_extents.set(convViewOptions['extents'])
|
|
vars.show_machine_limits.set(convViewOptions['limits'])
|
|
vars.show_offsets.set(convViewOptions['offsets'])
|
|
vars.show_live_plot.set(convViewOptions['plot'])
|
|
vars.show_rapids.set(convViewOptions['rapids'])
|
|
vars.show_machine_speed.set(convViewOptions['speed'])
|
|
vars.show_tool.set(convViewOptions['tool'])
|
|
o.cone_basesize = convViewOptions['cone']
|
|
o.show_small_origin = convViewOptions['origin']
|
|
o.joint_dro_format = joint_dro_format_old
|
|
o.dro_format = dro_format_old
|
|
o.hide_icons = False
|
|
|
|
def joint_dro_format_new(s,spd,num_of_joints,limit, homed):
|
|
''' replace dro with selected material '''
|
|
text = conv_material_text()
|
|
return limit, homed, text, text
|
|
|
|
def dro_format_new(s,spd,dtg,limit,homed,positions,axisdtg,g5x_offset,g92_offset,tlo_offset):
|
|
''' replace dro with selected material '''
|
|
text = conv_material_text()
|
|
return limit, homed, text, text
|
|
|
|
def conv_material_text():
|
|
''' return a list of material parameters to display '''
|
|
res = 3 if s.linear_units != 1 else 2
|
|
text = f"Cut Speed={materialFileDict[int(CONV.matCombo.get().split(':')[0])]['cut_speed']:.0f}"
|
|
text += f" Cut Height={materialFileDict[int(CONV.matCombo.get().split(':')[0])]['cut_height']:.{res}f}"
|
|
text += f" Kerf Width={materialFileDict[int(CONV.matCombo.get().split(':')[0])]['kerf_width']:.{res}f}"
|
|
return [text]
|
|
|
|
def hide_default():
|
|
rE('grid forget .pane')
|
|
rE('grid forget .fconv')
|
|
rE('grid forget .toolbar')
|
|
if pVars.orient.get() == 'portrait':
|
|
rE(f"grid forget {fportrait}")
|
|
else:
|
|
rE(f"grid forget {fbuttons}")
|
|
rE(f"grid forget {toolmat}")
|
|
rE(f"grid forget {fruns}")
|
|
|
|
def show_default():
|
|
rE('grid .toolbar -column 0 -row 0 -columnspan 3 -sticky nesw')
|
|
rE('grid .pane -column 1 -row 1 -rowspan 2 -sticky nsew')
|
|
rE(f".pane paneconfigure $pane_bottom -height {bPane}")
|
|
if not pVars.previewLarge.get():
|
|
populate_run_panel()
|
|
enable_menus(True)
|
|
keyboard_bindings(pVars.kbShortcuts.get())
|
|
vkbData['required'] = False
|
|
rE('focus .')
|
|
|
|
def enable_menus(state):
|
|
state = 'normal' if state else 'disabled'
|
|
menus = ['File', 'Machine', 'View', 'Conversational', 'Parameters', 'Setup', 'Help']
|
|
for menu in menus:
|
|
rE(f".menu entryconfig {menu} -state {state}")
|
|
|
|
|
|
##############################################################################
|
|
# TABLE VIEW FUNCTIONS #
|
|
##############################################################################
|
|
def set_view_t(event=None, scale=None):
|
|
# set button states
|
|
widgets.view_z.configure(relief='link')
|
|
widgets.view_z2.configure(relief='link')
|
|
widgets.view_x.configure(relief='link')
|
|
widgets.view_y.configure(relief='link')
|
|
widgets.view_y2.configure(relief='link')
|
|
widgets.view_t.configure(relief='sunken')
|
|
widgets.view_p.configure(relief='link')
|
|
vars.view_type.set(5)
|
|
# set view
|
|
mult = 1 if s.linear_units != 1 else 25.4
|
|
zoomScale = scale * 2 if scale else float(rE(f"{fsetup}.l.gui.zoom get")) * 2
|
|
xTableLength = machineBounds['xLen'] / mult / zoomScale
|
|
yTableLength = machineBounds['yLen'] / mult / zoomScale
|
|
xTableCenter = (machineBounds['X-'] + (machineBounds['xLen'] / 2)) / mult
|
|
yTableCenter = (machineBounds['Y-'] + (machineBounds['yLen'] / 2)) / mult
|
|
o.reset()
|
|
o.translate_modelview(-xTableCenter, -yTableCenter, 0)
|
|
o.set_eyepoint_from_extents(xTableLength, yTableLength)
|
|
o.perspective = False
|
|
o.lat = o.lon = 0
|
|
glRotateScene(o, 1.0, xTableCenter, yTableCenter, 0, 0, 0, 0, 0)
|
|
o._redraw()
|
|
|
|
def get_view_type():
|
|
if str(widgets.view_x['relief']) == 'sunken':
|
|
view = 'x'
|
|
elif (str(widgets.view_y['relief']) == 'sunken' or
|
|
str(widgets.view_y2['relief']) == 'sunken'):
|
|
view = 'y'
|
|
elif (str(widgets.view_z['relief']) == 'sunken' or
|
|
str(widgets.view_z2['relief']) == 'sunken'):
|
|
view = 'z'
|
|
elif (str(widgets.view_t['relief']) == 'sunken'):
|
|
view = 't'
|
|
else:
|
|
view = 'p'
|
|
return view
|
|
|
|
|
|
##############################################################################
|
|
# STATISTICS FUNCTIONS #
|
|
##############################################################################
|
|
def secs_to_hms(s):
|
|
m, s = divmod(int(s), 60)
|
|
h, m = divmod(m, 60)
|
|
return f"{h:02.0f}:{m:02.0f}:{s:02.0f}"
|
|
|
|
def hms_to_secs(hms):
|
|
h, m, s = hms.split(':')
|
|
return int(h)*3600 + int(m)*60 + int(s)
|
|
|
|
def save_total_stats():
|
|
if hal.get_value('plasmac.torch-enable'):
|
|
val = float(pVars.lengthT.get()[:len(pVars.lengthT.get()) - 1]) * statDivisor
|
|
pVars.lengthS.set(val)
|
|
putPrefs(PREF, 'STATISTICS', 'Cut length', val, float)
|
|
val = pVars.pierceT.get()
|
|
pVars.pierceS.set(val)
|
|
putPrefs(PREF, 'STATISTICS', 'Pierce count', val, int)
|
|
val = hms_to_secs(pVars.rapidT.get())
|
|
pVars.rapidS.set(val)
|
|
putPrefs(PREF, 'STATISTICS', 'Rapid time', val, int)
|
|
val = hms_to_secs(pVars.probeT.get())
|
|
pVars.probeS.set(val)
|
|
putPrefs(PREF, 'STATISTICS', 'Probe time', val, int)
|
|
val = hms_to_secs(pVars.torchT.get())
|
|
pVars.torchS.set(val)
|
|
putPrefs(PREF, 'STATISTICS', 'Torch on time', val, int)
|
|
val = hms_to_secs(pVars.cutT.get())
|
|
pVars.cutS.set(val)
|
|
putPrefs(PREF, 'STATISTICS', 'Cut time', val, int)
|
|
val = hms_to_secs(pVars.pausedT.get())
|
|
pVars.pausedS.set(val)
|
|
putPrefs(PREF, 'STATISTICS', 'Paused time', val, int)
|
|
val = hms_to_secs(pVars.runT.get())
|
|
pVars.runS.set(val)
|
|
putPrefs(PREF, 'STATISTICS', 'Program run time', val, int)
|
|
|
|
def clear_job_stats():
|
|
pVars.lengthJ.set(f"0.00{statSuffix}")
|
|
pVars.pierceJ.set(0)
|
|
pVars.rapidJ.set('00:00:00')
|
|
pVars.probeJ.set('00:00:00')
|
|
pVars.torchJ.set('00:00:00')
|
|
pVars.cutJ.set('00:00:00')
|
|
pVars.pausedJ.set('00:00:00')
|
|
pVars.runJ.set('00:00:00')
|
|
|
|
def reset_all_stats(stat):
|
|
if stat == 'length':
|
|
pVars.lengthS.set(0)
|
|
pVars.lengthJ.set(f"0.00{statSuffix}")
|
|
pVars.lengthT.set(f"0.00{statSuffix}")
|
|
putPrefs(PREF, 'STATISTICS', 'Cut length', 0, float)
|
|
elif stat == 'pierce':
|
|
pVars.pierceS.set(0)
|
|
pVars.pierceJ.set('0')
|
|
pVars.pierceT.set('0')
|
|
putPrefs(PREF, 'STATISTICS', 'Pierce count', 0, int)
|
|
elif stat == 'rapid':
|
|
pVars.rapidS.set(0)
|
|
pVars.rapidJ.set('00:00:00')
|
|
pVars.rapidT.set('00:00:00')
|
|
putPrefs(PREF, 'STATISTICS', 'Rapid time', 0, int)
|
|
elif stat == 'probe':
|
|
pVars.probeS.set(0)
|
|
pVars.probeJ.set('00:00:00')
|
|
pVars.probeT.set('00:00:00')
|
|
putPrefs(PREF, 'STATISTICS', 'Probe time', 0, int)
|
|
elif stat == 'torch':
|
|
pVars.torchS.set(0)
|
|
pVars.torchJ.set('00:00:00')
|
|
pVars.torchT.set('00:00:00')
|
|
putPrefs(PREF, 'STATISTICS', 'Torch on time', 0, int)
|
|
elif stat == 'cut':
|
|
pVars.cutS.set(0)
|
|
pVars.cutJ.set('00:00:00')
|
|
pVars.cutT.set('00:00:00')
|
|
putPrefs(PREF, 'STATISTICS', 'Cut time', 0, int)
|
|
elif stat == 'paused':
|
|
pVars.pausedS.set(0)
|
|
pVars.pausedJ.set('00:00:00')
|
|
pVars.pausedT.set('00:00:00')
|
|
putPrefs(PREF, 'STATISTICS', 'Paused time', 0, int)
|
|
elif stat == 'run':
|
|
pVars.runS.set(0)
|
|
pVars.runJ.set('00:00:00')
|
|
pVars.runT.set('00:00:00')
|
|
putPrefs(PREF, 'STATISTICS', 'Program run time', 0, int)
|
|
|
|
|
|
##############################################################################
|
|
# PARAMETER FUNCTIONS #
|
|
##############################################################################
|
|
# set appropriate hal pin if parameter changed
|
|
def param_changed(widget, value):
|
|
global widgetValues
|
|
item = widget.rsplit('.',1)[1]
|
|
if item in ['x-single-cut','y-single-cut']:
|
|
return
|
|
widgetValues[widget] = value
|
|
if item == 'cut-amps':
|
|
if pmx485['exists']:
|
|
pmx485_current_changed(int(value))
|
|
elif item == 'cut-mode':
|
|
if pmx485['exists']:
|
|
pmx485_mode_changed(int(value))
|
|
elif item == 'gas-pressure':
|
|
if pmx485['exists']:
|
|
pmx485_pressure_changed(float(value))
|
|
elif item == 'cut-speed':
|
|
hal.set_p('plasmac.cut-feed-rate',f"{value}")
|
|
elif item[1:] == '-pierce-offset':
|
|
if extHalPins:
|
|
comp[item] = value
|
|
else:
|
|
hal.set_p(f"plasmac.{item}",f"{value}")
|
|
|
|
def validate_spinbox(widget, spinType, resolution, value, original):
|
|
dbPrint = True if (not firstRun and comp['development']) else False
|
|
if dbPrint: print(f"\nvalidating {widget}")
|
|
if value == '':
|
|
if dbPrint: print('blank = still valid')
|
|
return True
|
|
minval = float(rE(f"{widget} cget -from")) if spinType == 'flt' else int(float(rE(f"{widget} cget -from")))
|
|
maxval = float(rE(f"{widget} cget -to")) if spinType == 'flt' else int(float(rE(f"{widget} cget -to")))
|
|
# a negative value if range min equals zero is invalid
|
|
if value == '-' and minval >= 0:
|
|
if dbPrint: print('cannot be less than zero = invalid')
|
|
return False
|
|
# a decimal point in an int is invalid
|
|
if '.' in str(value) and spinType == 'int':
|
|
if dbPrint: print('a decimal in an int = invalid')
|
|
return False
|
|
# more digits than the resolution of a float is invalid
|
|
if '.' in str(value) and len(str(value).split('.')[1]) > int(resolution):
|
|
# don't error on first run so we can import parameters from qtplasmac
|
|
if dbPrint: print('float resolution too large = invalid')
|
|
if not firstRun:
|
|
return False
|
|
# we cannot do math on "-", ".", or "-." but they are valid for a float
|
|
if value == '.' or value == '-' or value == '-.':
|
|
if dbPrint: print('illegal math = still valid')
|
|
return True
|
|
# if a float cannot be calculated from value then it is invalid
|
|
# we won't change the hal pin yet
|
|
try:
|
|
v = float(value)
|
|
except:
|
|
if dbPrint: print('cannot calculate a float = invalid')
|
|
return False
|
|
# if value is too large it is invalid
|
|
if v > maxval:
|
|
if dbPrint: print('value out of bounds = invalid')
|
|
return False
|
|
# if value is too small it may be valid
|
|
if v < minval or v > maxval:
|
|
if dbPrint: print('value out of bounds = still valid')
|
|
return True
|
|
# must be a good number...
|
|
if widget == f"{fsetup}.l.gui.zoom":
|
|
commands.set_view_t(None, v)
|
|
elif widget == f"{fsetup}.l.gui.jogspeed":
|
|
jog_default_changed(value)
|
|
elif widget == f"{fsetup}.l.gui.crspeed":
|
|
cut_rec_default_changed(value)
|
|
else:
|
|
param_changed(widget,value)
|
|
if dbPrint: print('valid entry')
|
|
return True
|
|
|
|
def load_param_clicked():
|
|
for widget in cpList:
|
|
try:
|
|
# bring in all parameters as floats to allow reading QtPlasmaC parameters
|
|
value = getPrefs(PREF, 'PLASMA_PARAMETERS', str(widget[8]), widget[3], float)
|
|
except:
|
|
value = 0
|
|
title = _('PARAMETER ERROR')
|
|
msg0 = _('Invalid parameter for')
|
|
plasmacPopUp('error', title, f"{msg0}: {widget[8]}")
|
|
continue
|
|
# convert to int here if required
|
|
value = value if widget[2] > 0 else int(value)
|
|
rE(f"{widget[0]}.{widget[1]} set {value}")
|
|
widgetValues[f"{widget[0]}.{widget[1]}"] = value
|
|
value = getPrefs(PREF, 'ENABLE_OPTIONS', 'THC auto', False, bool)
|
|
pVars.thcAuto.set(value)
|
|
mode_changed()
|
|
|
|
def save_param_clicked():
|
|
for widget in cpList:
|
|
value = rE(f"{widget[0]}.{widget[1]} get")
|
|
if widget[2] > 0:
|
|
putPrefs(PREF, 'PLASMA_PARAMETERS', str(widget[8]), value, float)
|
|
else:
|
|
putPrefs(PREF, 'PLASMA_PARAMETERS', str(widget[8]), value, int)
|
|
value = pVars.thcAuto.get()
|
|
putPrefs(PREF, 'ENABLE_OPTIONS', 'THC auto', value, bool)
|
|
|
|
def load_setup_clicked():
|
|
fontChanged = False
|
|
rE(f"{fsetup}.l.gui.jogspeed set {restoreSetup['jogSpeed']}")
|
|
jog_default_changed(restoreSetup['jogSpeed'])
|
|
if pVars.plasmacMode.get() != restoreSetup['plasmacMode']:
|
|
pVars.plasmacMode.set(restoreSetup['plasmacMode'])
|
|
mode_changed()
|
|
if pVars.winSize.get() != restoreSetup['winSize'] or \
|
|
rE(f"winfo geometry {root_window}").split('+', 1)[0] != restoreSetup['winLast']:
|
|
pVars.winSize.set(restoreSetup['winSize'])
|
|
set_window_size(restoreSetup['winLast'])
|
|
if pVars.orient.get() != restoreSetup['orient']:
|
|
pVars.orient.set(restoreSetup['orient'])
|
|
set_orientation()
|
|
if pVars.fontSize.get() != restoreSetup['fontSize']:
|
|
pVars.fontSize.set(restoreSetup['fontSize'])
|
|
fontChanged = True
|
|
if pVars.guiFont.get() != restoreSetup['guiFont']:
|
|
pVars.guiFont.set(restoreSetup['guiFont'])
|
|
fontChanged = True
|
|
if pVars.codeFont.get() != restoreSetup['codeFont']:
|
|
pVars.codeFont.set(restoreSetup['codeFont'])
|
|
fontChanged = True
|
|
if fontChanged:
|
|
font_changed()
|
|
if pVars.coneSize.get() != restoreSetup['coneSize']:
|
|
pVars.coneSize.set(restoreSetup['coneSize'])
|
|
cone_size_changed()
|
|
if pVars.popLocation.get() != restoreSetup['popLocation']:
|
|
pVars.popLocation.set(restoreSetup['popLocation'])
|
|
if pVars.matDefault.get() != restoreSetup['matDefault']:
|
|
pVars.matDefault.set(restoreSetup['matDefault'])
|
|
display_selected_material(restoreSetup['matDefault'])
|
|
if pVars.useVirtKB.get() != restoreSetup['useVirtKB']:
|
|
pVars.useVirtKB.set(restoreSetup['useVirtKB'])
|
|
virtual_kb_changed()
|
|
if pVars.useVirtKB.get():
|
|
pVars.kbShortcuts.set(0)
|
|
keyboard_bindings(0)
|
|
else:
|
|
if pVars.kbShortcuts.get() != restoreSetup['kbShortcuts']:
|
|
pVars.kbShortcuts.set(restoreSetup['kbShortcuts'])
|
|
keyboard_bindings(restoreSetup['kbShortcuts'])
|
|
if int(rE(f"{fsetup}.l.gui.crspeed get")) == restoreSetup['crPercent']:
|
|
rE(f"{fcrspeed}.display.cut-rec-speed set {restoreSetup['crPercent']}")
|
|
else:
|
|
rE(f"{fsetup}.l.gui.crspeed set {restoreSetup['crPercent']}")
|
|
pVars.closeDialog.set(restoreSetup['closeDialog'])
|
|
pVars.closeText.set(restoreSetup['closeText'])
|
|
rE(f"{fsetup}.l.gui.zoom set {restoreSetup['tableZoom']}")
|
|
if not (isPaused or isRunning):
|
|
user_button_load()
|
|
read_colors()
|
|
color_change()
|
|
|
|
def save_setup_clicked():
|
|
if int(rE(f"{fsetup}.l.gui.jogspeed get")) < minJogSpeed:
|
|
rE(f"{fsetup}.l.gui.jogspeed set {minJogSpeed}")
|
|
restoreSetup['jogSpeed'] = rE(f"{fsetup}.l.gui.jogspeed get")
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Jog speed', restoreSetup['jogSpeed'], int)
|
|
restoreSetup['plasmacMode'] = pVars.plasmacMode.get()
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Mode', restoreSetup['plasmacMode'], int)
|
|
restoreSetup['closeText'] = pVars.closeText.get()
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Exit warning text', restoreSetup['closeText'], str)
|
|
restoreSetup['closeDialog'] = pVars.closeDialog.get()
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Exit warning', restoreSetup['closeDialog'], bool)
|
|
restoreSetup['winSize'] = pVars.winSize.get()
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Window size', restoreSetup['winSize'], str)
|
|
restoreSetup['winLast'] = rE(f"winfo geometry {root_window}").split('+', 1)[0]
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Window last', restoreSetup['winLast'], str)
|
|
restoreSetup['orient'] = pVars.orient.get()
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Orientation', restoreSetup['orient'], str)
|
|
restoreSetup['fontSize'] = pVars.fontSize.get()
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Font size', restoreSetup['fontSize'], str)
|
|
restoreSetup['guiFont'] = pVars.guiFont.get()
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'GUI font', restoreSetup['guiFont'], str)
|
|
restoreSetup['codeFont'] = pVars.codeFont.get()
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Gcode font', restoreSetup['codeFont'], str)
|
|
restoreSetup['coneSize'] = pVars.coneSize.get()
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Preview cone size', restoreSetup['coneSize'], float)
|
|
restoreSetup['popLocation'] = pVars.popLocation.get()
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Popup location', restoreSetup['popLocation'], str)
|
|
restoreSetup['tableZoom'] = float(rE(f"{fsetup}.l.gui.zoom get"))
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Table zoom', restoreSetup['tableZoom'], float)
|
|
restoreSetup['matDefault'] = pVars.matDefault.get()
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Default material', restoreSetup['matDefault'], int)
|
|
restoreSetup['crPercent'] = rE(f"{fsetup}.l.gui.crspeed get")
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Cut recovery speed %', restoreSetup['crPercent'], int)
|
|
rE(f"{fcrspeed}.display.cut-rec-speed set {restoreSetup['crPercent']}")
|
|
restoreSetup['kbShortcuts'] = pVars.kbShortcuts.get()
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Use keyboard shortcuts', restoreSetup['kbShortcuts'], bool)
|
|
restoreSetup['useVirtKB'] = pVars.useVirtKB.get()
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Use soft keyboard', restoreSetup['useVirtKB'], bool)
|
|
if not (isPaused or isRunning):
|
|
user_button_save()
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Foreground color', colorFore, str)
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Background color', colorBack, str)
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Disabled color', colorDisable, str)
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Active color', colorActive, str)
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Warning color', colorWarn, str)
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Voltage color', colorVolt, str)
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Arc OK color', colorArc, str)
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'LED color', colorLed, str)
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Trough color', colorTrough, str)
|
|
for button in togglePins:
|
|
set_toggle_pins(button)
|
|
|
|
|
|
##############################################################################
|
|
# GENERAL FUNCTIONS #
|
|
##############################################################################
|
|
def thc_enable_toggled():
|
|
hal.set_p('plasmac.thc-enable', str(pVars.thcEnable.get()))
|
|
putPrefs(PREF, 'ENABLE_OPTIONS','THC enable', pVars.thcEnable.get(), bool)
|
|
|
|
def corner_enable_toggled():
|
|
hal.set_p('plasmac.cornerlock-enable', str(pVars.cornerEnable.get()))
|
|
putPrefs(PREF, 'ENABLE_OPTIONS','Corner lock enable', pVars.cornerEnable.get(), bool)
|
|
|
|
def void_enable_toggled():
|
|
hal.set_p('plasmac.voidlock-enable', str(pVars.voidEnable.get()))
|
|
putPrefs(PREF, 'ENABLE_OPTIONS','Void lock enable', pVars.voidEnable.get(), bool)
|
|
|
|
def auto_volts_toggled():
|
|
hal.set_p('plasmac.use-auto-volts', str(pVars.autoVolts.get()))
|
|
putPrefs(PREF, 'ENABLE_OPTIONS', 'Use auto volts', pVars.autoVolts.get(), bool)
|
|
|
|
def ohmic_enable_toggled():
|
|
hal.set_p('plasmac.ohmic-probe-enable', str(pVars.ohmicEnable.get()))
|
|
putPrefs(PREF, 'ENABLE_OPTIONS', 'Ohmic probe enable', pVars.ohmicEnable.get(), bool)
|
|
|
|
def ignore_arc_ok_toggled():
|
|
hal.set_p('plasmac.ignore-arc-ok-1', str(pVars.ignorArcOk.get()))
|
|
|
|
def laser_button_enable():
|
|
if laserOffsets['X'] or laserOffsets['Y']:
|
|
rE(f"grid {fjogf}.zerohome.laser -column 3 -row 0")
|
|
rE(f"grid {fcrbuttons}.laser -column 0 -row 0")
|
|
else:
|
|
rE(f"grid forget {fjogf}.zerohome.laser")
|
|
rE(f"grid forget {fcrbuttons}.laser")
|
|
|
|
def offset_probe_setup():
|
|
hal.set_p('plasmac.offset-probe-x', f"{probeOffsets['X']}")
|
|
hal.set_p('plasmac.offset-probe-y', f"{probeOffsets['Y']}")
|
|
hal.set_p('plasmac.offset-probe-delay', f"{probeOffsets['Delay']}")
|
|
if probeOffsets['X'] or probeOffsets['Y']:
|
|
rE(f"grid {fparam}.c1.probe.offset-feed-rateL -column 0 -row 6 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fparam}.c1.probe.offset-feed-rate -column 1 -row 6 -sticky e -padx {{0 4}} -pady {{4 0}}")
|
|
else:
|
|
rE(f"grid forget {fparam}.c1.probe.offset-feed-rateL")
|
|
rE(f"grid forget {fparam}.c1.probe.offset-feed-rate")
|
|
|
|
def set_toggle_pins(button):
|
|
togglePins[button]['state'] = hal.get_value(togglePins[button]['pin'])
|
|
if togglePins[button]['state']:
|
|
rE(f"{fbuttons}.button{button} configure -bg {colorActive}")
|
|
rE(f"{fbuttons}.button{button} configure -text {{{togglePins[button]['ontext']}}}")
|
|
else:
|
|
if togglePins[button]['runcritical']:
|
|
rE(f"{fbuttons}.button{button} configure -bg {colorWarn}")
|
|
else:
|
|
rE(f"{fbuttons}.button{button} configure -bg {colorBack}")
|
|
rE(f"{fbuttons}.button{button} configure -text {{{togglePins[button]['offtext']}}}")
|
|
|
|
def jog_default_changed(value):
|
|
set_jog_slider(int(value) / (vars.max_speed.get() * 60))
|
|
|
|
def set_jog_slider(value):
|
|
# jog slider value is from 0 to 1
|
|
if not manualCut['state']:
|
|
rE(f"set jog_slider_val {value}")
|
|
rE(f"update_jog_slider_vel {value}")
|
|
|
|
def tar_filter(tarinfo):
|
|
if os.path.splitext(tarinfo.name)[1] in ['.pyc']:
|
|
return None
|
|
else:
|
|
return tarinfo
|
|
|
|
def backup_clicked():
|
|
n = time.localtime()
|
|
d = f"{str(n.tm_year)[-2:]}{n.tm_mon:02d}{n.tm_mday:02d}"
|
|
t = f"{n.tm_hour:02d}{n.tm_min:02d}{n.tm_sec:02d}"
|
|
configDir = os.path.dirname(vars.emcini.get())
|
|
outName = f"{vars.machine.get()}_v{VER}_{d}_{t}.tar.gz"
|
|
outFile = os.path.join(os.path.expanduser('~'), outName)
|
|
with tarfile.open(outFile, mode='w:gz', ) as archive:
|
|
archive.add(configDir, filter=tar_filter)
|
|
title = _('BACKUP')
|
|
msg0 = _('A compressed backup of the machine configuration has been saved in your home directory')
|
|
msg1 = _('The file name is')
|
|
msg2 = _('This file may be attached to a post on the LinuxCNC forum to aid in problem solving')
|
|
plasmacPopUp('info', title, f"{msg0}\n\n{msg1}: {outName}\n\n{msg2}\n")
|
|
|
|
def torch_enable():
|
|
hal.set_p('plasmac.torch-enable', str(not hal.get_value('plasmac.torch-enable')))
|
|
color_torch()
|
|
|
|
def update_preview(clear=False):
|
|
c.wait_complete(.25)
|
|
s.poll()
|
|
while s.interp_state != linuxcnc.INTERP_IDLE:
|
|
o.tkRedraw()
|
|
o.redraw_dro()
|
|
o.update_idletasks()
|
|
root_window.update()
|
|
s.poll()
|
|
if clear:
|
|
live_plotter.clear()
|
|
|
|
def user_manual():
|
|
web = webbrowser.open_new_tab('https://phillc54.github.io/plasmac2-docs/plasmac2.html')
|
|
if not web:
|
|
msg0 = _('Cannot open user manual web page')
|
|
notifications.add('error', f"{msg0}")
|
|
|
|
|
|
##############################################################################
|
|
# JOINTS/AXES FUNCTIONS #
|
|
##############################################################################
|
|
def ja_button_setup(widget, button, text):
|
|
rE(f"radiobutton {widget} -value {button} -text {text} -anchor center \
|
|
-variable ja_rbutton -command ja_button_activated -padx 10 -pady 6 \
|
|
-indicatoron 0 -bd 2 -highlightthickness 0 -selectcolor {colorActive}")
|
|
|
|
def ja_button_activated():
|
|
if vars.ja_rbutton.get() in 'xyzabcuvw':
|
|
widget = getattr(widgets, f"axis_{vars.ja_rbutton.get()}")
|
|
widget.focus()
|
|
rE(f"{fjogf}.zerohome.zero configure -text {vars.ja_rbutton.get().upper()}0")
|
|
if not homing_order_defined:
|
|
pre = _('Home')
|
|
widgets.homebutton.configure(text = f"{pre} {vars.ja_rbutton.get().upper()}")
|
|
else:
|
|
widget = getattr(widgets, f"joint_{vars.ja_rbutton.get()}")
|
|
widget.focus()
|
|
commands.axis_activated()
|
|
|
|
def joint_mode_switch(a, b, c):
|
|
global lastMotionMode
|
|
if vars.motion_mode.get() == linuxcnc.TRAJ_MODE_FREE and s.kinematics_type != linuxcnc.KINEMATICS_IDENTITY:
|
|
rE(f"grid forget {fmanual}.axes")
|
|
rE(f"grid {fmanual}.joints -column 0 -row 0 -padx 2 -sticky w")
|
|
widget = getattr(widgets, 'joint_0')
|
|
widget.focus()
|
|
vars.ja_rbutton.set(0)
|
|
elif lastMotionMode == linuxcnc.TRAJ_MODE_FREE or not lastMotionMode:
|
|
rE(f"grid forget {fmanual}.joints")
|
|
rE(f"grid {fmanual}.axes -column 0 -row 0 -padx 2 -sticky w")
|
|
widget = getattr(widgets, f"axis_{first_axis}")
|
|
widget.focus()
|
|
vars.ja_rbutton.set(first_axis)
|
|
lastMotionMode = vars.motion_mode.get()
|
|
|
|
##############################################################################
|
|
# MANUAL CUT #
|
|
##############################################################################
|
|
def manual_cut(event):
|
|
global manualCut
|
|
if manual_ok():
|
|
if not hal.get_value('spindle.0.on'):
|
|
if not critical_button_check():
|
|
return
|
|
msg = bounds_check_probe(True)
|
|
if msg:
|
|
notifications.add('error', msg)
|
|
return
|
|
c.spindle(linuxcnc.SPINDLE_FORWARD, 1)
|
|
manualCut['feed'] = vars.jog_speed.get()
|
|
vars.jog_speed.set(int(rE(f"{fruns}.material.cut-feed-rate get")))
|
|
manualCut['state'] = True
|
|
rE('.pane.top.jogspeed.s configure -state disabled')
|
|
clear_job_stats()
|
|
else:
|
|
manualCut['state'] = False
|
|
c.spindle(linuxcnc.SPINDLE_OFF)
|
|
vars.jog_speed.set(manualCut['feed'])
|
|
rE('.pane.top.jogspeed.s configure -state normal')
|
|
save_total_stats()
|
|
|
|
|
|
##############################################################################
|
|
# SINGLE CUT #
|
|
##############################################################################
|
|
def single_cut():
|
|
global result, singleCut
|
|
result = False
|
|
|
|
def cut_file(event):
|
|
global result
|
|
result = True
|
|
sc.quit()
|
|
|
|
def cancel_file(event):
|
|
sc.quit()
|
|
|
|
title = _('SINGLE CUT')
|
|
valid, xLength, yLength = plasmacPopUp('sc', title, None, 'numpad').reply
|
|
vkbData['required'] = False
|
|
if not valid:
|
|
return
|
|
try:
|
|
xLength = float(xLength)
|
|
yLength = float(yLength)
|
|
except:
|
|
title = _('ENTRY ERROR')
|
|
msg = _('Lengths need to be floating point values')
|
|
plasmacPopUp('error', title, msg)
|
|
return
|
|
singleCut['state'] = True
|
|
singleCut['G91'] = True if 910 in s.gcodes else False
|
|
putPrefs(PREF, 'SINGLE_CUT', 'X length', xLength, float)
|
|
putPrefs(PREF, 'SINGLE_CUT', 'Y length', yLength, float)
|
|
xEnd = s.position[0] + float(xLength)
|
|
yEnd = s.position[1] + float(yLength)
|
|
scFile = os.path.join(tmpPath, 'single_cut.ngc')
|
|
with open(scFile, 'w') as f:
|
|
f.write('G90\n')
|
|
f.write('F#<_hal[plasmac.cut-feed-rate]>\n')
|
|
f.write(f"G53 G0 X{s.position[0]:0.6f} Y{s.position[1]:0.6f}\n")
|
|
f.write('M3 $0 S1\n')
|
|
f.write(f"G53 G1 X{xEnd:0.6f} Y{yEnd:0.6f}\n")
|
|
f.write('M5 $0\n')
|
|
f.write('M2\n')
|
|
if loaded_file != scFile:
|
|
pVars.preRflFile.set(loaded_file)
|
|
open_file_guts(scFile, False, False)
|
|
commands.set_view_z()
|
|
|
|
|
|
##############################################################################
|
|
# ALIGNMENT FUNCTIONS #
|
|
##############################################################################
|
|
def touch_off_xy(state, x, y):
|
|
if state == '0' and isIdleHomed:
|
|
if manual_ok():
|
|
save_task_mode = s.task_mode
|
|
ensure_mode(linuxcnc.MODE_MDI)
|
|
c.mdi(f"G10 L20 P0 X{x} Y{y}")
|
|
c.wait_complete()
|
|
s.poll()
|
|
o.tkRedraw()
|
|
reload_file(False)
|
|
ensure_mode(save_task_mode)
|
|
set_motion_teleop(1)
|
|
o.redraw_dro()
|
|
|
|
def laser_button_toggled(state, button):
|
|
global laserTimer, laserButtonState, laserText, laserOffsets
|
|
global machineBounds, isIdleHomed
|
|
if state == '1': # button pressed
|
|
if s.paused and not hal.get_value('plasmac.laser-recovery-state'):
|
|
xPos = s.position[0] + laserOffsets['X']
|
|
yPos = s.position[1] + laserOffsets['Y']
|
|
if xPos < machineBounds['X-'] or xPos > machineBounds['X+'] or yPos < machineBounds['Y-'] or yPos > machineBounds['Y+']:
|
|
msg0 = _('Torch cannot move outside the machine boundary')
|
|
notifications.add('error', f"{msg0}")
|
|
return
|
|
hal.set_p('plasmac.laser-x-offset', f"{str(int(laserOffsets['X'] / hal.get_value('plasmac.offset-scale')))}")
|
|
hal.set_p('plasmac.laser-y-offset', f"{str(int(laserOffsets['Y'] / hal.get_value('plasmac.offset-scale')))}")
|
|
hal.set_p('plasmac.laser-recovery-start', '1')
|
|
hal.set_p('plasmac.cut-recovery', '1')
|
|
comp['laser-on'] = 1
|
|
return
|
|
# long press timer
|
|
elif isIdleHomed:
|
|
laserTimer = 700
|
|
root_window.after(100, laser_long_press_timer)
|
|
else: # button released
|
|
if laserButtonState == 'reset':
|
|
laserButtonState = 'laser'
|
|
return
|
|
laserTimer = 0
|
|
if not isIdleHomed:
|
|
return
|
|
xPos = s.position[0] - laserOffsets['X']
|
|
yPos = s.position[1] - laserOffsets['Y']
|
|
if xPos < machineBounds['X-'] or xPos > machineBounds['X+'] or yPos < machineBounds['Y-'] or yPos > machineBounds['Y+']:
|
|
msg0 = _('Laser is outside the machine boundary')
|
|
notifications.add('error', f"{msg0}")
|
|
return
|
|
if laserButtonState == 'laser':
|
|
pVars.laserText.set(_('Mark'))
|
|
laserButtonState = 'markedge'
|
|
comp['laser-on'] = 1
|
|
return
|
|
elif laserButtonState == 'setorigin':
|
|
comp['laser-on'] = 0
|
|
laserButtonState = sheet_align('laser', laserButtonState, laserOffsets['X'], laserOffsets['Y'])
|
|
|
|
def laser_long_press_timer():
|
|
global laserTimer, laserButtonState
|
|
if laserTimer > 0:
|
|
laserTimer -= 100
|
|
if laserTimer <= 0:
|
|
comp['laser-on'] = 0
|
|
laserButtonState = 'reset'
|
|
pVars.laserText.set(_('Laser'))
|
|
else:
|
|
root_window.after(100, laser_long_press_timer)
|
|
|
|
def sheet_align(mode, buttonState, offsetX, offsetY):
|
|
global relPos, startAlignPos
|
|
msgList = []
|
|
if buttonState == 'markedge':
|
|
#FIXME: NO CAMERA - IS A CAMERA WORTHWHILE ON A PLASMA TABLE?
|
|
# zAngle = self.w.camview.rotation = 0
|
|
ensure_mode(linuxcnc.MODE_MDI)
|
|
c.mdi('G10 L2 P0 R0')
|
|
c.wait_complete()
|
|
live_plotter.clear()
|
|
#FIXME: NO CAMERA - IS A CAMERA WORTHWHILE ON A PLASMA TABLE?
|
|
# self.w.cam_goto.setEnabled(False)
|
|
pVars.laserText.set(_('Origin'))
|
|
buttonState = 'setorigin'
|
|
startAlignPos['X'] = relPos['X']
|
|
startAlignPos['Y'] = relPos['Y']
|
|
else:
|
|
if mode == 'laser':
|
|
pVars.laserText.set(_('Laser'))
|
|
buttonState = 'laser'
|
|
else:
|
|
pVars.laserText.set(_('Mark'))
|
|
buttonState = 'markedge'
|
|
xDiff = relPos['X'] - startAlignPos['X']
|
|
yDiff = relPos['Y'] - startAlignPos['Y']
|
|
if xDiff and yDiff:
|
|
zAngle = math.degrees(math.atan(yDiff / xDiff))
|
|
if xDiff > 0:
|
|
zAngle += 180
|
|
elif yDiff > 0:
|
|
zAngle += 360
|
|
if abs(xDiff) < abs(yDiff):
|
|
zAngle -= 90
|
|
elif xDiff:
|
|
if xDiff > 0:
|
|
zAngle = 180
|
|
else:
|
|
zAngle = 0
|
|
elif yDiff:
|
|
if yDiff > 0:
|
|
zAngle = 180
|
|
else:
|
|
zAngle = 0
|
|
else:
|
|
zAngle = 0
|
|
#FIXME: NO CAMERA - IS A CAMERA WORTHWHILE ON A PLASMA TABLE?
|
|
# self.w.camview.rotation = zAngle
|
|
ensure_mode(linuxcnc.MODE_MDI)
|
|
c.mdi(f"G10 L20 P0 X{offsetX} Y{offsetY}")
|
|
c.wait_complete()
|
|
c.mdi(f"G10 L2 P0 R{zAngle}")
|
|
c.wait_complete()
|
|
if loaded_file:
|
|
commands.reload_file(False)
|
|
if 1:
|
|
ensure_mode(linuxcnc.MODE_MDI)
|
|
c.mdi('G0 X0 Y0')
|
|
c.wait_complete()
|
|
#FIXME: NO CAMERA - IS A CAMERA WORTHWHILE ON A PLASMA TABLE?
|
|
# self.w.cam_goto.setEnabled(True)
|
|
live_plotter.clear()
|
|
return buttonState
|
|
|
|
|
|
##############################################################################
|
|
# FRAMING FUNCTIONS #
|
|
##############################################################################
|
|
def frame_error(torch, msgList):
|
|
title = _('AXIS LIMIT ERROR')
|
|
if not torch:
|
|
msgList += '\n'
|
|
msgList += _('Do you want to try with the torch?')
|
|
reply = plasmacPopUp('yesno', title, msgList).reply
|
|
else:
|
|
msgList += '\n'
|
|
msgList += _('Framing cannot proceed')
|
|
reply = plasmacPopUp('error', title, msgList).reply
|
|
return reply
|
|
|
|
def frame_job(feed, height):
|
|
global framingState, activeFunction
|
|
if o.canon:
|
|
msgList, frame_points = bounds_check_framing(laserOffsets['X'], laserOffsets['Y'], True)
|
|
if msgList:
|
|
reply = frame_error(False, msgList)
|
|
if not reply:
|
|
return
|
|
msgList, frame_points = bounds_check_framing()
|
|
if msgList:
|
|
reply = frame_error(True, msgList)
|
|
return
|
|
if s.interp_state == linuxcnc.INTERP_IDLE:
|
|
activeFunction = True
|
|
if not msgList:
|
|
comp['laser-on'] = 1
|
|
if not feed:
|
|
feed = widgetValues[f"{fruns}.material.cut-feed-rate"]
|
|
ensure_mode(linuxcnc.MODE_MDI)
|
|
previousMode = None
|
|
# metric machine imperial units
|
|
if s.linear_units == 1 and s.program_units == 1:
|
|
previousMode = 'G20'
|
|
c.mdi('G21')
|
|
# imperial machine metric units
|
|
elif s.linear_units != 1 and s.program_units == 2:
|
|
previousMode = 'G21'
|
|
c.mdi('G20')
|
|
c.wait_complete()
|
|
if not height:
|
|
height = machineBounds['Z+'] - (hal.get_value('plasmac.max-offset') * unitsPerMm)
|
|
c.mdi(f"G53 G0 Z{height:0.4f}")
|
|
c.mdi(f"G53 G0 X{frame_points[1][0]:0.2f} Y{frame_points[1][1]:0.2f}")
|
|
c.mdi(f"G53 G1 X{frame_points[2][0]:0.2f} Y{frame_points[2][1]:0.2f} F{feed:0.0f}")
|
|
c.mdi(f"G53 G1 X{frame_points[3][0]:0.2f} Y{frame_points[3][1]:0.2f}")
|
|
c.mdi(f"G53 G1 X{frame_points[4][0]:0.2f} Y{frame_points[4][1]:0.2f}")
|
|
c.mdi(f"G53 G1 X{frame_points[1][0]:0.2f} Y{frame_points[1][1]:0.2f}")
|
|
c.mdi('G0 X0 Y0')
|
|
if previousMode:
|
|
c.mdi(previousMode)
|
|
framingState = True
|
|
|
|
def rotate_frame(coordinates):
|
|
angle = math.radians(s.rotation_xy)
|
|
cos = math.cos(angle)
|
|
sin = math.sin(angle)
|
|
frame_points = [coordinates[0]]
|
|
ox = frame_points[0][0]
|
|
oy = frame_points[0][1]
|
|
for x, y in coordinates[1:]:
|
|
tox = x - ox
|
|
toy = y - oy
|
|
rx = (tox * cos) - (toy * sin) + ox
|
|
ry = (tox * sin) + (toy * cos) + oy
|
|
frame_points.append([rx, ry])
|
|
xMin = min(frame_points[1:])[0]
|
|
xMax = max(frame_points[1:])[0]
|
|
yMin = min(frame_points[1:])[1]
|
|
yMax = max(frame_points[1:])[1]
|
|
return frame_points, xMin, yMin, xMax, yMax
|
|
|
|
##############################################################################
|
|
# BOUNDS CHECKS #
|
|
##############################################################################
|
|
def bounds_check_file():
|
|
msg = _('G-code')
|
|
# canon units are always returned as imperial
|
|
# ensure returned units are in machine units
|
|
unitsMultiplier = 25.4 if s.linear_units == 1 else 1
|
|
xMin = (o.canon.min_extents[0] * unitsMultiplier)
|
|
xMax = (o.canon.max_extents[0] * unitsMultiplier)
|
|
yMin = (o.canon.min_extents[1] * unitsMultiplier)
|
|
yMax = (o.canon.max_extents[1] * unitsMultiplier)
|
|
errMsg = bounds_compare(xMin, xMax, yMin, yMax, msg)
|
|
return errMsg
|
|
|
|
def bounds_check_probe(local):
|
|
msg = _('Move to probe offset')
|
|
xPierceOffset = yPierceOffset = xMinP = xMaxP = yMinP = yMaxP = 0
|
|
if local:
|
|
xMinP = xMaxP = s.position[0] + probeOffsets['X']
|
|
yMinP = yMaxP = s.position[1] + probeOffsets['Y']
|
|
elif any((comp['x_min_pierce_extent'], comp['x_max_pierce_extent'], \
|
|
comp['y_min_pierce_extent'], comp['y_max_pierce_extent'])):
|
|
if comp['cut-type']:
|
|
#TODO PHILL - Do you want this from the GUI or HAL??
|
|
xPierceOffset = comp['x-pierce-offset']
|
|
yPierceOffset = comp['y-pierce-offset']
|
|
if s.linear_units == 1 and not vars.metric.get():
|
|
unitsMultiplier = 25.4
|
|
elif s.linear_units != 1 and vars.metric.get():
|
|
unitsMultiplier = 1 / 25.4
|
|
else:
|
|
unitsMultiplier = 1
|
|
xMinP = comp['x_min_pierce_extent'] * unitsMultiplier + probeOffsets['X'] + s.g5x_offset[0] + xPierceOffset
|
|
xMaxP = comp['x_max_pierce_extent'] * unitsMultiplier + probeOffsets['X'] + s.g5x_offset[0] + xPierceOffset
|
|
yMinP = comp['y_min_pierce_extent'] * unitsMultiplier + probeOffsets['Y'] + s.g5x_offset[1] + yPierceOffset
|
|
yMaxP = comp['y_max_pierce_extent'] * unitsMultiplier + probeOffsets['Y'] + s.g5x_offset[1] + yPierceOffset
|
|
errMsg = bounds_compare(xMinP, xMaxP, yMinP, yMaxP, msg)
|
|
return errMsg
|
|
|
|
def bounds_check_framing(xOffset=0, yOffset=0, laser=False):
|
|
msg = _('Framing move')
|
|
if laser:
|
|
msg1 = _('due to laser offset')
|
|
else:
|
|
msg1 = ''
|
|
# canon units are always returned as imperial
|
|
# ensure returned units are in machine units
|
|
unitsMultiplier = 25.4 if s.linear_units == 1 else 1
|
|
xMin = (o.canon.min_extents_zero_rxy[0] * unitsMultiplier + xOffset)
|
|
xMax = (o.canon.max_extents_zero_rxy[0] * unitsMultiplier + xOffset)
|
|
yMin = (o.canon.min_extents_zero_rxy[1] * unitsMultiplier + yOffset)
|
|
yMax = (o.canon.max_extents_zero_rxy[1] * unitsMultiplier + yOffset)
|
|
coordinates = [[s.g5x_offset[0], s.g5x_offset[1]], [xMin, yMin], [xMin, yMax], [xMax, yMax], [xMax, yMin]]
|
|
frame_points, xMin, yMin, xMax, yMax = rotate_frame(coordinates)
|
|
errMsg = bounds_compare(xMin, xMax, yMin, yMax, msg, msg1)
|
|
return (errMsg, frame_points)
|
|
|
|
def bounds_compare(xMin, xMax, yMin, yMax, msg, msg1=''):
|
|
global machineBounds
|
|
errMsg = ''
|
|
epsilon = 1e-4
|
|
txtxMin = _('exceeds the X minimum limit by')
|
|
txtxMax = _('exceeds the X maximum limit by')
|
|
txtyMin = _('exceeds the Y minimum limit by')
|
|
txtyMax = _('exceeds the Y maximum limit by')
|
|
lessThan = _('less than')
|
|
if xMin < machineBounds['X-']:
|
|
errMsg += f'{msg} {txtxMin} {lessThan} {epsilon} {unitSuffix} {msg1}\n' if (machineBounds['X-'] - xMin) < epsilon \
|
|
else f'{msg} {txtxMin} {machineBounds["X-"] - xMin:0.4f} {unitSuffix} {msg1}\n'
|
|
if xMax > machineBounds['X+']:
|
|
errMsg += f'{msg} {txtxMax} {lessThan} {epsilon} {unitSuffix} {msg1}\n' if (xMax - machineBounds['X+']) < epsilon \
|
|
else f'{msg} {txtxMax} {xMax - machineBounds["X+"]:0.4f} {unitSuffix} {msg1}\n'
|
|
if yMin < machineBounds['Y-']:
|
|
errMsg += f'{msg} {txtyMin} {lessThan} {epsilon} {unitSuffix} {msg1}\n' if (machineBounds['Y-'] - yMin) < epsilon \
|
|
else f'{msg} {txtyMin} {machineBounds["Y-"] - yMin:0.4f} {unitSuffix} {msg1}\n'
|
|
if yMax > machineBounds['Y+']:
|
|
errMsg += f'{msg} {txtyMax} {lessThan} {epsilon} {unitSuffix} {msg1}\n' if (yMax - machineBounds['Y+']) < epsilon \
|
|
else f'{msg} {txtyMax} {yMax - machineBounds["Y+"]:0.4f} {unitSuffix} {msg1}\n'
|
|
return errMsg
|
|
|
|
##############################################################################
|
|
# PERIPHERAL OFFSET FUNCTIONS #
|
|
##############################################################################
|
|
def offsets_text():
|
|
text = []
|
|
text.append(_('1. Jog until the peripheral is centered on the mark'))
|
|
text.append(_('2. Click the Yes button to get the offsets'))
|
|
return text
|
|
|
|
def set_peripheral_offsets():
|
|
toolFile = os.path.realpath(tooltable)
|
|
setup_toggle(False)
|
|
while 1:
|
|
reply = offsets_show(toolFile)
|
|
if not reply:
|
|
break
|
|
|
|
def offsets_show(toolFile):
|
|
text = []
|
|
text.append(_('1. Place some scrap material under the torch'))
|
|
text.append(_('2. Touchoff the torch to X0Y0'))
|
|
text.append(_('3. Mark the material with a torch pulse'))
|
|
text.append(_('4. Click the appropriate button to activate the peripheral'))
|
|
reply = plasmacPopUp('offsets', _('SET PERIPHERAL OFFSETS'), ' \n'.join(text)).reply
|
|
if reply == 'laser':
|
|
comp['laser-on'] = True
|
|
offsets_laser_clicked()
|
|
elif reply == 'scribe':
|
|
comp['offset-set-scribe'] = True
|
|
offsets_scribe_clicked(toolFile)
|
|
elif reply == 'probe':
|
|
comp['offset-set-probe'] = True
|
|
offsets_probe_clicked()
|
|
else:
|
|
comp['laser-on'] = False
|
|
comp['offset-set-scribe'] = False
|
|
comp['offset-set-probe'] = False
|
|
return False
|
|
return True
|
|
|
|
def offsets_laser_clicked():
|
|
reply = plasmacPopUp('yesno', _('SET LASER OFFSETS'), ' \n'.join(offsets_text())).reply
|
|
if not reply:
|
|
comp['laser-on'] = False
|
|
return
|
|
newOffsets = {'X':round(s.position[0] - s.g5x_offset[0] - s.g92_offset[0], 4) + 0, \
|
|
'Y':round(s.position[1] - s.g5x_offset[1] - s.g92_offset[1], 4) + 0}
|
|
if offsets_prompt(_('CHANGE LASER OFFSETS'), laserOffsets, newOffsets):
|
|
laserOffsets['X'] = newOffsets['X']
|
|
laserOffsets['Y'] = newOffsets['Y']
|
|
putPrefs(PREF, 'LASER_OFFSET', 'X axis', laserOffsets['X'], float)
|
|
putPrefs(PREF, 'LASER_OFFSET', 'Y axis', laserOffsets['Y'], float)
|
|
laser_button_enable()
|
|
comp['laser-on'] = False
|
|
title = _('LASER OFFSETS')
|
|
msg = _('Laser offsets have been saved')
|
|
plasmacPopUp('info', title, msg)
|
|
comp['laser-on'] = False
|
|
|
|
def offsets_scribe_clicked(toolFile):
|
|
try:
|
|
scribeOffsets = {'X': 0, 'Y': 0}
|
|
tool = []
|
|
with open(toolFile, 'r') as inFile:
|
|
for line in inFile:
|
|
if line.startswith('T1'):
|
|
tool = line.split()
|
|
inFile.close()
|
|
break
|
|
if tool:
|
|
for item in tool:
|
|
if item.startswith('X'):
|
|
scribeOffsets['X'] = float(item.replace('X','').replace('+',''))
|
|
elif item.startswith('Y'):
|
|
scribeOffsets['Y'] = float(item.replace('Y','').replace('+',''))
|
|
except:
|
|
title = _('TOOL FILE ERROR')
|
|
msg = _('Could not get current scribe offsets from tooltable')
|
|
plasmacPopUp('info', title, msg)
|
|
return
|
|
reply = plasmacPopUp('yesno', _('SET SCRIBE OFFSETS'), ' \n'.join(offsets_text())).reply
|
|
if not reply:
|
|
comp['offset-set-scribe'] = False
|
|
return
|
|
newOffsets = {'X':round(s.position[0] - s.g5x_offset[0] - s.g92_offset[0], 4) + 0, \
|
|
'Y':round(s.position[1] - s.g5x_offset[1] - s.g92_offset[1], 4) + 0}
|
|
if offsets_prompt(_('CHANGE SCRIBE OFFSETS'), scribeOffsets, newOffsets):
|
|
scribeOffsets['X'] = newOffsets['X']
|
|
scribeOffsets['Y'] = newOffsets['Y']
|
|
offsets_write_scribe(toolFile, scribeOffsets)
|
|
c.load_tool_table()
|
|
comp['offset-set-scribe'] = False
|
|
title = _('SCRIBE OFFSETS')
|
|
msg = _('Scribe offsets have been saved')
|
|
plasmacPopUp('info', title, msg)
|
|
comp['offset-set-scribe'] = False
|
|
|
|
def offsets_probe_clicked():
|
|
reply = plasmacPopUp('yesno', _('SET PROBE OFFSETS'), ' \n'.join(offsets_text())).reply
|
|
if not reply:
|
|
comp['offset-set-probe'] = False
|
|
return
|
|
title = _('OFFSET PROBE DELAY')
|
|
prompt = _('Delay (Seconds)')
|
|
while 1:
|
|
valid, delay = plasmacPopUp('entry', title, prompt, True, probeOffsets['Delay']).reply
|
|
if not valid:
|
|
comp['offset-set-probe'] = False
|
|
return
|
|
if not delay:
|
|
delay = 0
|
|
try:
|
|
delay = float(delay)
|
|
break
|
|
except:
|
|
msg = ('Delay entry is invalid')
|
|
plasmacPopUp('info', title, msg)
|
|
newOffsets = {'X':round(s.position[0] - s.g5x_offset[0] - s.g92_offset[0], 4) + 0, \
|
|
'Y':round(s.position[1] - s.g5x_offset[1] - s.g92_offset[1], 4) + 0, \
|
|
'Delay':delay}
|
|
if offsets_prompt(_('CHANGE PROBE OFFSETS'), probeOffsets, newOffsets, True):
|
|
probeOffsets['X'] = newOffsets['X']
|
|
probeOffsets['Y'] = newOffsets['Y']
|
|
probeOffsets['Delay'] = newOffsets['Delay']
|
|
putPrefs(PREF, 'OFFSET_PROBING', 'X axis', probeOffsets['X'], float)
|
|
putPrefs(PREF, 'OFFSET_PROBING', 'Y axis', probeOffsets['Y'], float)
|
|
putPrefs(PREF, 'OFFSET_PROBING', 'Delay', probeOffsets['Delay'], float)
|
|
offset_probe_setup()
|
|
comp['offset-set-probe'] = False
|
|
title = _('PROBE OFFSETS')
|
|
msg = _('Probe offsets have been saved')
|
|
plasmacPopUp('info', title, msg)
|
|
comp['offset-set-probe'] = False
|
|
|
|
def offsets_prompt(title, oldOffsets, newOffsets, probe=False):
|
|
dly = _('Delay')
|
|
prompt = _('From')
|
|
prompt += f":\nX:{oldOffsets['X']:0.3f} Y:{oldOffsets['Y']:0.3f}"
|
|
if probe:
|
|
prompt += f" {dly}:{oldOffsets['Delay']:0.2f}"
|
|
prompt += '\n\n'
|
|
prompt += _('To')
|
|
prompt += f":\nX:{newOffsets['X']:0.3f} Y:{newOffsets['Y']:0.3f}"
|
|
if probe:
|
|
prompt += f" {dly}:{newOffsets['Delay']:0.2f}"
|
|
prompt += '\n'
|
|
return plasmacPopUp('yesno', title, prompt, True).reply
|
|
|
|
def offsets_write_scribe(toolFile, offsets):
|
|
written = False
|
|
COPY(toolFile, f"{toolFile}~")
|
|
with open(f"{toolFile}~", 'r') as inFile:
|
|
with open(toolFile, 'w') as outFile:
|
|
for line in inFile:
|
|
if line.startswith('T1'):
|
|
outFile.write(f"T1 P1 X{offsets['X']:0.3f} Y{offsets['Y']:0.3f} ;scribe\n")
|
|
written = True
|
|
else:
|
|
outFile.write(line)
|
|
if not written:
|
|
outFile.write(f"T1 P1 X{offsets['X']:0.3f} Y{offsets['Y']:0.3f} ;scribe\n")
|
|
os.remove(f"{toolFile}~")
|
|
|
|
|
|
##############################################################################
|
|
# HEIGHT OVERRIDE #
|
|
##############################################################################
|
|
def height_lower():
|
|
if rE(f"{foverride}.lower cget -state") == 'disabled':
|
|
return
|
|
global torchHeight
|
|
torchHeight -= 0.1
|
|
height_set(f"{torchHeight:.1f}")
|
|
|
|
def height_raise():
|
|
if rE(f"{foverride}.raise cget -state") == 'disabled':
|
|
return
|
|
global torchHeight
|
|
torchHeight += 0.1
|
|
height_set(f"{torchHeight:.1f}")
|
|
|
|
def height_reset():
|
|
if rE(f"{foverride}.reset cget -state") == 'disabled':
|
|
return
|
|
global torchHeight
|
|
torchHeight = 0
|
|
height_set(f"{torchHeight:.1f}")
|
|
|
|
def height_set(height):
|
|
rE(f"{foverride}.height-override configure -text {height}V")
|
|
hal.set_p('plasmac.height-override', height)
|
|
|
|
|
|
##############################################################################
|
|
# CUT RECOVERY FUNCTIONS #
|
|
##############################################################################
|
|
def cut_rec_default_changed(percent):
|
|
rE(f"{fcrspeed}.display.cut-rec-speed set {percent}")
|
|
|
|
def cut_rec_slider_changed(percent):
|
|
pVars.crSpeed.set(f"{int(widgetValues[f'{fruns}.material.cut-feed-rate']) * int(percent) * 0.01:0.0f}")
|
|
|
|
def cut_rec_motion(direction):
|
|
if int(direction):
|
|
speed = float(rE(f"{fcrspeed}.display.cut-rec-speed get")) * 0.01
|
|
hal.set_p('plasmac.paused-motion-speed',f"{speed * int(direction):.2f}")
|
|
else:
|
|
hal.set_p('plasmac.paused-motion-speed','0')
|
|
|
|
def cut_rec_move(x, y):
|
|
if not s.paused:
|
|
return
|
|
maxMove = 10
|
|
if s.linear_units != 1:
|
|
maxMove = 0.4
|
|
laser = hal.get_value('plasmac.laser-recovery-state') > 0
|
|
distX = float(pVars.kerfWidth.get()) * int(x)
|
|
distY = float(pVars.kerfWidth.get()) * int(y)
|
|
xNew = hal.get_value('plasmac.axis-x-position') + hal.get_value('axis.x.eoffset') - (laserOffsets['X'] * laser) + distX
|
|
yNew = hal.get_value('plasmac.axis-y-position') + hal.get_value('axis.y.eoffset') - (laserOffsets['Y'] * laser) + distY
|
|
if xNew < machineBounds['X-'] or xNew > machineBounds['X+'] or yNew < machineBounds['Y-'] or yNew > machineBounds['Y+']:
|
|
return
|
|
xTotal = hal.get_value('axis.x.eoffset') - (laserOffsets['X'] * laser) + distX
|
|
yTotal = hal.get_value('axis.y.eoffset') - (laserOffsets['Y'] * laser) + distY
|
|
if xTotal > maxMove or xTotal < -maxMove or yTotal > maxMove or yTotal < -maxMove:
|
|
return
|
|
moveX = int(distX / hal.get_value('plasmac.offset-scale'))
|
|
moveY = int(distY / hal.get_value('plasmac.offset-scale'))
|
|
hal.set_p('plasmac.x-offset', f"{str(hal.get_value('plasmac.x-offset') + moveX)}")
|
|
hal.set_p('plasmac.y-offset', f"{str(hal.get_value('plasmac.y-offset') + moveY)}")
|
|
hal.set_p('plasmac.cut-recovery', '1')
|
|
|
|
def cut_rec_cancel():
|
|
hal.set_p('plasmac.cut-recovery', '0')
|
|
hal.set_p('plasmac.laser-recovery-start', '0')
|
|
hal.set_p('plasmac.x-offset', '0')
|
|
hal.set_p('plasmac.y-offset', '0')
|
|
comp['laser-on'] = 0
|
|
|
|
|
|
##############################################################################
|
|
# MONKEYPATCHED FUNCTIONS FROM AXIS.PY #
|
|
##############################################################################
|
|
def get_view():
|
|
''' add view t '''
|
|
x,y,z,p = 0,1,2,3
|
|
if str(widgets.view_x['relief']) == 'sunken':
|
|
view = x
|
|
elif (str(widgets.view_y['relief']) == 'sunken' or
|
|
str(widgets.view_y2['relief']) == 'sunken'):
|
|
view = y
|
|
elif (str(widgets.view_z['relief']) == 'sunken' or
|
|
str(widgets.view_z2['relief']) == 'sunken' or
|
|
str(widgets.view_t['relief']) == 'sunken'):
|
|
view = z
|
|
else:
|
|
view = p
|
|
return view
|
|
|
|
def filter_program_new(program_filter, infilename, outfilename):
|
|
''' remove temporary materials before calling original filter_program function '''
|
|
mats = [m for m in materialNumList if m >= 1000000]
|
|
if mats:
|
|
for mat in mats:
|
|
materialFileDict.pop(mat)
|
|
materialNumList.remove(mat)
|
|
if get_displayed_material() >= 1000000:
|
|
change_default_material()
|
|
insert_materials()
|
|
exitcode, stderr = filter_program_old(program_filter, infilename, outfilename)
|
|
return exitcode, stderr
|
|
|
|
|
|
##############################################################################
|
|
# MONKEYPATCHED FUNCTIONS FROM GLCANON.PY #
|
|
##############################################################################
|
|
def draw_grid():
|
|
''' do not return if view = P '''
|
|
x,y,z,p = 0,1,2,3
|
|
view = get_view()
|
|
rotation = math.radians(s.rotation_xy % 90)
|
|
permutations = [
|
|
lambda x_y_z: (x_y_z[2], x_y_z[1], x_y_z[0]), # YZ X
|
|
lambda x_y_z1: (x_y_z1[2], x_y_z1[0], x_y_z1[1]), # ZX Y
|
|
lambda x_y_z2: (x_y_z2[0], x_y_z2[1], x_y_z2[2])] # XY Z
|
|
inverse_permutations = [
|
|
lambda z_y_x: (z_y_x[2], z_y_x[1], z_y_x[0]), # YZ X
|
|
lambda z_x_y: (z_x_y[1], z_x_y[2], z_x_y[0]), # ZX Y
|
|
lambda x_y_z3: (x_y_z3[0], x_y_z3[1], x_y_z3[2])] # XY Z
|
|
o.draw_grid_permuted(rotation, permutations[2],
|
|
inverse_permutations[2])
|
|
|
|
def posstrs():
|
|
''' show height above material probed height '''
|
|
s = o.stat
|
|
limit = list(s.limit[:])
|
|
homed = list(s.homed[:])
|
|
spd = o.to_internal_linear_unit(s.current_vel)
|
|
if not o.get_joints_mode() or o.no_joint_display:
|
|
if o.get_show_commanded():
|
|
positions = s.position
|
|
else:
|
|
positions = s.actual_position
|
|
if o.get_show_relative():
|
|
positions = [(i-j) for i, j in zip(positions, s.tool_offset)]
|
|
positions = [(i-j) for i, j in zip(positions, s.g5x_offset)]
|
|
t = -s.rotation_xy
|
|
t = math.radians(t)
|
|
x = positions[0]
|
|
y = positions[1]
|
|
positions[0] = x * math.cos(t) - y * math.sin(t)
|
|
positions[1] = x * math.sin(t) + y * math.cos(t)
|
|
positions = [(i-j) for i, j in zip(positions, s.g92_offset)]
|
|
else:
|
|
positions = list(positions)
|
|
if o.get_a_axis_wrapped():
|
|
positions[3] = math.fmod(positions[3], 360.0)
|
|
if positions[3] < 0: positions[3] += 360.0
|
|
if o.get_b_axis_wrapped():
|
|
positions[4] = math.fmod(positions[4], 360.0)
|
|
if positions[4] < 0: positions[4] += 360.0
|
|
if o.get_c_axis_wrapped():
|
|
positions[5] = math.fmod(positions[5], 360.0)
|
|
if positions[5] < 0: positions[5] += 360.0
|
|
positions = o.to_internal_units(positions)
|
|
axisdtg = o.to_internal_units(s.dtg)
|
|
g5x_offset = o.to_internal_units(s.g5x_offset)
|
|
g92_offset = o.to_internal_units(s.g92_offset)
|
|
tlo_offset = o.to_internal_units(s.tool_offset)
|
|
dtg = o.to_internal_linear_unit(s.distance_to_go)
|
|
if o.get_show_metric():
|
|
positions = o.from_internal_units(positions, 1)
|
|
axisdtg = o.from_internal_units(axisdtg, 1)
|
|
g5x_offset = o.from_internal_units(g5x_offset, 1)
|
|
g92_offset = o.from_internal_units(g92_offset, 1)
|
|
tlo_offset = o.from_internal_units(tlo_offset, 1)
|
|
dtg *= 25.4
|
|
spd = spd * 25.4
|
|
spd = spd * 60
|
|
# show height above material probed height
|
|
if s.linear_units == 1 and not vars.metric.get():
|
|
scale = 1 / 25.4
|
|
elif s.linear_units != 1 and vars.metric.get():
|
|
scale = 25.4
|
|
else:
|
|
scale = 1
|
|
if hal.get_value('plasmac.offsets-active') or isPaused:
|
|
positions[2] = hal.get_value('plasmac.z-height') * scale
|
|
return o.dro_format(o.stat,spd,dtg,limit,homed,positions,
|
|
axisdtg,g5x_offset,g92_offset,tlo_offset)
|
|
else:
|
|
return o.joint_dro_format(s,spd,o.get_num_joints(),limit, homed)
|
|
|
|
|
|
##############################################################################
|
|
# TCL CALLED PYTHON FUNCTIONS HIJACKED FROM AXIS.PY #
|
|
##############################################################################
|
|
def reload_file(refilter=True):
|
|
''' file to load depends on type of file
|
|
set view to Z
|
|
clear the plot '''
|
|
if running(): return
|
|
s.poll()
|
|
if not loaded_file and not pVars.preRflFile.get():
|
|
root_window.tk.call('set_mode_from_tab')
|
|
return
|
|
line = vars.highlight_line.get()
|
|
o.set_highlight_line(None)
|
|
if pVars.preRflFile.get():
|
|
f = pVars.preRflFile.get()
|
|
elif '/shape.ngc' in loaded_file:
|
|
f = os.path.join(tmpPath, 'shape.ngc')
|
|
else:
|
|
f = loaded_file
|
|
if refilter or not get_filter(loaded_file):
|
|
# we copy the file to a temporary file so that even if it subsequently
|
|
# changes on disk, LinuxCNC is parsing the file contents from the time
|
|
# the user opened the file
|
|
tempfile = os.path.join(tempdir, os.path.basename(loaded_file))
|
|
if loaded_file != tempfile:
|
|
shutil.copyfile(loaded_file, tempfile)
|
|
open_file_guts(tempfile, False, False)
|
|
else:
|
|
tempfile = os.path.join(tempdir, "filtered-" + os.path.basename(loaded_file))
|
|
open_file_guts(tempfile, True, False)
|
|
msg = bounds_check_file()
|
|
msg += bounds_check_probe(False)
|
|
if msg:
|
|
notifications.add('error', msg)
|
|
commands.set_view_z()
|
|
if line:
|
|
o.set_highlight_line(line)
|
|
live_plotter.clear()
|
|
|
|
def task_run(*event):
|
|
global dryRun
|
|
if event and event[0]== 'dry-run' and loaded_file:
|
|
if laserOffsets['X'] or laserOffsets['Y']:
|
|
framingError = bounds_check_framing(laserOffsets['X'], laserOffsets['Y'], True)[0]
|
|
if framingError:
|
|
title = _('AXIS LIMIT ERROR')
|
|
plasmacPopUp('warn', title, framingError)
|
|
return
|
|
dryRun = [s.g5x_offset[0], s.g5x_offset[1]]
|
|
newX = s.actual_position[0] - s.g5x_offset[0] - laserOffsets['X']
|
|
newY = s.actual_position[1] - s.g5x_offset[1] - laserOffsets['Y']
|
|
units = '21' if vars.metric.get() else '20'
|
|
if s.linear_units == 1 and units == '20':
|
|
unitsMultiplier = 1 / 25.4
|
|
elif s.linear_units != 1 and units == '20':
|
|
unitsMultiplier = 25.4
|
|
else:
|
|
unitsMultiplier = 1
|
|
ensure_mode(linuxcnc.MODE_MDI)
|
|
c.mdi(f'G{units} G10 L20 P0 X{newX * unitsMultiplier} Y{newY * unitsMultiplier}')
|
|
c.wait_complete()
|
|
comp['laser-on'] = 1
|
|
hal.set_p('plasmac.dry-run', '1')
|
|
if run_warn() or not critical_button_check():
|
|
return
|
|
global program_start_line, program_start_line_last
|
|
program_start_line_last = program_start_line;
|
|
ensure_mode(linuxcnc.MODE_AUTO)
|
|
c.auto(linuxcnc.AUTO_RUN, program_start_line)
|
|
program_start_line = 0
|
|
t.tag_remove("ignored", "0.0", "end")
|
|
o.set_highlight_line(None)
|
|
|
|
def task_run_line():
|
|
''' get leadin if required
|
|
preprocess gcode up to selected line '''
|
|
if vars.highlight_line.get() == 0:
|
|
return
|
|
pVars.startLine.set(vars.highlight_line.get() - 1)
|
|
if loaded_file != os.path.join(tmpPath, 'rfl.ngc'):
|
|
rflIn = os.path.join(tmpPath, 'filtered_bkp.ngc')
|
|
else:
|
|
rflIn = loaded_file
|
|
if comp['development']:
|
|
reload(RFL)
|
|
# get rfl type
|
|
rfl = {}
|
|
title = _('RUN FROM LINE')
|
|
valid, type_ = plasmacPopUp('rfl_type', title, None, 'numpad').reply
|
|
vkbData['required'] = False
|
|
if not valid:
|
|
pVars.rflActive = False
|
|
pVars.startLine.set(0)
|
|
return
|
|
lastLine = 0
|
|
# get start and end of cutpath
|
|
if type_ == 'cut':
|
|
count = 0
|
|
start = 0
|
|
with open(rflIn, 'r') as inFile:
|
|
for line in inFile:
|
|
line = line.strip()
|
|
if line[:3] == 'G00':
|
|
start = count
|
|
if line[:3] == 'M05' and count > pVars.startLine.get():
|
|
break
|
|
count += 1
|
|
lastLine = count
|
|
pVars.startLine.set(start)
|
|
rfl['do'] = False
|
|
rfl['length'] = 0.0
|
|
rfl['angle'] = 0.0
|
|
# get leadin parameters
|
|
else:
|
|
valid, rfl['do'], rfl['length'], rfl['angle'] = plasmacPopUp('rfl', title, None, 'numpad').reply
|
|
vkbData['required'] = False
|
|
# cancel rfl
|
|
if not valid:
|
|
pVars.rflActive = False
|
|
pVars.startLine.set(0)
|
|
return
|
|
# get the old data
|
|
setup = RFL.run_from_line_get(rflIn, pVars.startLine.get(), lastLine)
|
|
if setup['error']:
|
|
# cannot do run from line within a subroutine or if using cutter compensation
|
|
if setup['compError']:
|
|
msg0 = _('Cannot run from line while cutter compensation is active')
|
|
notifications.add('error', f"{msg0}\n")
|
|
if setup['subError']:
|
|
msg0 = _('Cannot do run from line inside a subroutine')
|
|
msg1 = ''
|
|
for sub in setup['subError']:
|
|
msg1 += f" {sub}"
|
|
notifications.add('error', f"{msg0} {msg1}\n")
|
|
pVars.rflActive = False
|
|
pVars.startLine.set(0)
|
|
else:
|
|
# set the new data
|
|
rflFile = os.path.join(tmpPath, 'rfl.ngc')
|
|
result = RFL.run_from_line_set(rflFile, setup, rfl, unitsPerMm)
|
|
# if leadin cannot be used
|
|
if result['error']:
|
|
msg0 = _('Unable to calculate a leadin for this cut')
|
|
msg1 = _('Program will run from selected line with no leadin applied')
|
|
notifications.add('error', f"{msg0}\n{msg1}\n")
|
|
# load rfl file
|
|
if loaded_file != os.path.join(tmpPath, 'rfl.ngc'):
|
|
pVars.preRflFile.set(loaded_file)
|
|
open_file_guts(os.path.join(tmpPath, 'rfl.ngc'), False, False)
|
|
commands.set_view_z()
|
|
|
|
def open_file_name(f): # from axis.py
|
|
''' set view to Z '''
|
|
global loaded_file
|
|
loaded_file = f
|
|
open_file_guts(f)
|
|
commands.set_view_z()
|
|
if o.canon is not None:
|
|
x = (o.canon.min_extents[0] + o.canon.max_extents[0])/2
|
|
y = (o.canon.min_extents[1] + o.canon.max_extents[1])/2
|
|
z = (o.canon.min_extents[2] + o.canon.max_extents[2])/2
|
|
o.set_centerpoint(x, y, z)
|
|
live_plotter.clear()
|
|
msg = bounds_check_file()
|
|
msg += bounds_check_probe(False)
|
|
if msg:
|
|
notifications.add('error', msg)
|
|
|
|
def set_view_p(event=None): # from axis.py
|
|
''' add view t '''
|
|
widgets.view_z.configure(relief='link')
|
|
widgets.view_z2.configure(relief='link')
|
|
widgets.view_x.configure(relief='link')
|
|
widgets.view_y.configure(relief='link')
|
|
widgets.view_y2.configure(relief='link')
|
|
widgets.view_t.configure(relief='link')
|
|
widgets.view_p.configure(relief='sunken')
|
|
vars.view_type.set(5)
|
|
o.set_view_p()
|
|
|
|
def set_view_z(event=None): # from axis.py
|
|
''' add view t '''
|
|
widgets.view_z.configure(relief='sunken')
|
|
widgets.view_z2.configure(relief='link')
|
|
widgets.view_x.configure(relief='link')
|
|
widgets.view_y.configure(relief='link')
|
|
widgets.view_y2.configure(relief='link')
|
|
widgets.view_t.configure(relief='link')
|
|
widgets.view_p.configure(relief='link')
|
|
vars.view_type.set(1)
|
|
o.set_view_z()
|
|
|
|
def get_jog_speed(a):
|
|
''' convert speeds to suit gcode units'''
|
|
if vars.teleop_mode.get():
|
|
if axis_type[a] == "LINEAR" :
|
|
return vars.jog_speed.get() / 60 * pVars.jogMultiplier.get()
|
|
else:
|
|
return vars.jog_aspeed.get() / 60 * pVars.jogMultiplier.get()
|
|
else:
|
|
if joint_type[a] == 'LINEAR':
|
|
return vars.jog_speed.get() / 60 * pVars.jogMultiplier.get()
|
|
else:
|
|
return vars.jog_aspeed.get() / 60 * pVars.jogMultiplier.get()
|
|
|
|
def send_mdi_command(command):
|
|
''' reload file if G10 in gcode '''
|
|
''' disallow M3, M4, M5, and G92 in MDI '''
|
|
global mdi_history_index, mdi_history_save_filename
|
|
if command != "":
|
|
command= command.lstrip().rstrip()
|
|
test = command.lower().replace(' ','')
|
|
if 'g92' in test and not 'g92.1' in test:
|
|
msg0 = _('G92 offsets are not allowed')
|
|
notifications.add('error', f"{msg0}\n")
|
|
return
|
|
if 'm3' in test:
|
|
msg0 = _('M3 commands are not allowed in MDI mode')
|
|
notifications.add('error', f"{msg0}\n")
|
|
return
|
|
elif 'm4' in test:
|
|
msg0 = _('M4 commands are not allowed in MDI mode')
|
|
notifications.add('error', f"{msg0}\n")
|
|
return
|
|
elif 'm5' in test:
|
|
msg0 = _('M5 commands are not allowed in MDI mode')
|
|
notifications.add('error', f"{msg0}\n")
|
|
return
|
|
vars.mdi_command.set("")
|
|
ensure_mode(linuxcnc.MODE_MDI)
|
|
widgets.mdi_history.selection_clear(0, "end")
|
|
## check if input is already in list. If so, then delete old element
|
|
#idx = 0
|
|
#for ele in widgets.mdi_history.get(0, "end"):
|
|
# if ele == command:
|
|
# widgets.mdi_history.delete(idx)
|
|
# break
|
|
# idx += 1
|
|
history_size = widgets.mdi_history.size()
|
|
new_entry = 1
|
|
if history_size > 1 and widgets.mdi_history.get(history_size - 2) == command:
|
|
new_entry = 0
|
|
if new_entry != 0:
|
|
# if command is already at end of list, don't add it again
|
|
widgets.mdi_history.insert(history_size - 1, f"{command}")
|
|
history_size += 1
|
|
widgets.mdi_history.see(history_size - 1)
|
|
if history_size > (mdi_history_max_entries + 1):
|
|
widgets.mdi_history.delete(0, 0)
|
|
history_size= (mdi_history_max_entries + 1)
|
|
# pdb.set_trace()
|
|
mdi_history_index = widgets.mdi_history.index("end") - 1
|
|
c.mdi(command)
|
|
o.tkRedraw()
|
|
commands.mdi_history_write_to_file(mdi_history_save_filename, history_size)
|
|
if 'G10' in command.upper().replace(' ',''):
|
|
reload_file()
|
|
|
|
|
|
##############################################################################
|
|
# TCL FUNCTIONS HIJACKED FROM AXIS.TCL #
|
|
##############################################################################
|
|
def update_title(*args):
|
|
''' add plasmac to the title '''
|
|
if vars.taskfile.get() == '':
|
|
file = 'no file loaded'
|
|
name = 'AXIS'
|
|
else:
|
|
file = name = os.path.basename(vars.taskfile.get())
|
|
base = f"{vars.machine.get()} plasmac2 v{VER} + AXIS {linuxcnc.version}"
|
|
rE(f"wm title {root_window} {{{base} ({file})}}")
|
|
rE(f"wm iconname {root_window} {{{name}}}")
|
|
|
|
def update_jog_slider_vel(value):
|
|
''' inhibit slider update if manual cut is active
|
|
use a linear response for jog slider '''
|
|
if not manualCut['state']:
|
|
rE(f"set jog_speed {int(float(value) * vars.max_speed.get() * 60)}")
|
|
|
|
def set_pane_minsize():
|
|
'''we set our own min sizes dependent on font size '''
|
|
pass
|
|
|
|
|
|
##############################################################################
|
|
# PYTHON FUNCTIONS HIJACKED FROM AXIS.PY #
|
|
##############################################################################
|
|
def vupdate(var, val):
|
|
''' pretend no file is loaded if program is cleared '''
|
|
if var == vars.taskfile and 'clear.ngc' in val:
|
|
val = ''
|
|
try:
|
|
if var.get() == val: return
|
|
except ValueError:
|
|
pass
|
|
var.set(val)
|
|
|
|
def get_coordinate_font(large):
|
|
''' remove selectable large font'''
|
|
global coordinate_font
|
|
global coordinate_linespace
|
|
global coordinate_charwidth
|
|
global fontbase
|
|
coordinate_font = f"monospace {pVars.fontSize.get()}"
|
|
if coordinate_font not in font_cache:
|
|
font_cache[coordinate_font] = \
|
|
glnav.use_pango_font(coordinate_font, 0, 128)
|
|
fontbase, coordinate_charwidth, coordinate_linespace = \
|
|
font_cache[coordinate_font]
|
|
|
|
def install_help(app):
|
|
''' we use install_kb_text and install_kp_text instead
|
|
so we don't need to do anything here '''
|
|
return
|
|
|
|
def prompt_touchoff(title, text, default, tool_only, system=None):
|
|
''' use our own prompt
|
|
allow use of virtual keyboard'''
|
|
title = _('TOUCH OFF')
|
|
text = text.replace(':', '') % _('workpiece')
|
|
valid, value, system = plasmacPopUp('touch', title, text, 'numpad', system).reply
|
|
vkbData['required'] = False
|
|
try:
|
|
v = float(value)
|
|
except:
|
|
msg0 = _('Touch off entry is invalid')
|
|
plasmacPopUp('error', title, f"{msg0[:16]}{value} {msg0[16:]}")
|
|
value = 0.0
|
|
if valid:
|
|
return(value, system)
|
|
else:
|
|
return(None, None)
|
|
|
|
|
|
##############################################################################
|
|
# USER BUTTON FUNCTIONS #
|
|
##############################################################################
|
|
def critical_button_check():
|
|
valid = True
|
|
if hal.get_value('plasmac.torch-enable'):
|
|
buttons = ''
|
|
btnText = _('button is')
|
|
for button in criticalButtons:
|
|
if togglePins[str(button)]['runcritical'] and not togglePins[str(button)]['state']:
|
|
if buttons:
|
|
buttons += ', '
|
|
btnText = _('buttons are')
|
|
buttons += rE(f"{fbuttons}.button{str(button)} cget -text")
|
|
valid = False
|
|
if not valid:
|
|
msg0 = _('not activated')
|
|
msg1 = _('Continue the cut?')
|
|
valid = plasmacPopUp('yesno', _('CRITICAL BUTTON'), f'{buttons} {btnText} {msg0}\n\n{msg1}').reply
|
|
return valid
|
|
|
|
def validate_hal_pin(halpin, button, usage):
|
|
valid = pBit = False
|
|
for pin in halPinList:
|
|
if halpin in pin['NAME']:
|
|
pBit = isinstance(pin['VALUE'], bool)
|
|
valid = True
|
|
break
|
|
if not valid:
|
|
msg0 = _('does not exist for user button')
|
|
notifications.add('error', f"{halpin} {msg0} #{button}")
|
|
elif not pBit:
|
|
msg0 = _('must be a bit pin for user button')
|
|
notifications.add('error', f"{usage} {msg0} #{button}")
|
|
valid = False
|
|
return valid
|
|
|
|
def get_parameter_value(code, button):
|
|
param, start, mid, end = '', '', '', ''
|
|
error = False
|
|
while '{' in code or '#<_ini[' in code:
|
|
if '{' in code:
|
|
if not '}' in code:
|
|
msg0 = _('is missing for user button')
|
|
notifications.add('error', f"'}}' {msg0} #{button}")
|
|
code = ''
|
|
error = True
|
|
break
|
|
param = code.split('{', 1)[1].split('}', 1)[0]
|
|
start = '{'
|
|
mid = ' '
|
|
end = '}'
|
|
else:
|
|
if not '>' in code:
|
|
msg0 = _('is missing for user button')
|
|
notifications.add('error', f"'>' {msg0} #{button}")
|
|
code = ''
|
|
error = True
|
|
break
|
|
param = code.split('#<_ini[', 1)[1].split('>', 1)[0].replace(']', ' ')
|
|
start = '#<_ini['
|
|
mid = ']'
|
|
end = '>'
|
|
if param:
|
|
section, option = param.split(' ', 1)
|
|
if PREF.has_option(section, option):
|
|
value = getPrefs(PREF, section.upper(), option, '', str)
|
|
elif inifile.find(section.upper(), option.upper()):
|
|
value = inifile.find(section.upper(), option.upper())
|
|
else:
|
|
msg0 = _('is invalid parameter for user button')
|
|
notifications.add('error', f"'{section} {option}' {msg0} #{button}")
|
|
code = ''
|
|
error = True
|
|
break
|
|
code = code.replace(f"{start}{section}{mid}{option}{end}", value)
|
|
param, start, mid, end = '', '', '', ''
|
|
return(error, code)
|
|
|
|
def button_action(button, pressed):
|
|
if int(pressed):
|
|
user_button_pressed(button, buttonCodes[int(button)])
|
|
else:
|
|
user_button_released(button, buttonCodes[int(button)])
|
|
|
|
def user_button_setup():
|
|
global buttonNames, buttonCodes, togglePins, pulsePins, machineBounds, criticalButtons
|
|
global probeButton, probeText, torchButton, torchText, cChangeButton, invalidButtons
|
|
singleCodes = ['ohmic-test','cut-type','single-cut','manual-cut','probe-test', \
|
|
'torch-pulse','change-consumables','framing','latest-file']
|
|
buttonNames = {0:{'name':None}}
|
|
buttonCodes = {0:{'code':None}}
|
|
invalidButtons = []
|
|
criticalButtons = []
|
|
row = 1
|
|
for n in range(1, maxUserButtons + 1):
|
|
bLabel = None
|
|
bName = getPrefs(PREF, 'BUTTONS', f"{n} Name", '', str)
|
|
bCode = getPrefs(PREF, 'BUTTONS', f"{n} Code", '', str)
|
|
outCode = {'code':None}
|
|
parmError = False
|
|
if '{' in bCode or '#<_ini[' in bCode:
|
|
parmError, bCode = get_parameter_value(bCode, n)
|
|
if bCode.strip() == 'ohmic-test' and not 'ohmic-test' in [(v['code']) for k, v in buttonCodes.items()]:
|
|
outCode['code'] = 'ohmic-test'
|
|
elif bCode.strip() == 'cut-type' and not 'cut-type' in buttonCodes:
|
|
bName = bName.split(',')
|
|
if len(bName) == 1:
|
|
text = _('Pierce\Only') if '\\' in bName[0] else _('Pierce Only')
|
|
bName.append(text)
|
|
outCode = {'code':'cut-type', 'text':bName}
|
|
elif bCode.strip() == 'single-cut' and not 'single-cut' in buttonCodes:
|
|
outCode['code'] = 'single-cut'
|
|
elif bCode.strip() == 'manual-cut' and not 'manual-cut' in buttonCodes:
|
|
outCode['code'] = 'manual-cut'
|
|
elif bCode.startswith('probe-test') and not 'probe-test' in [(v['code']) for k, v in buttonCodes.items()]:
|
|
codes = bCode.lower().strip().replace(' ','').replace('probe-test','probe-test ').split()
|
|
if len(codes) < 3:
|
|
outCode = {'code':'probe-test', 'time':10}
|
|
probeButton = str(n)
|
|
probeText = bName.replace('\\', '\n')
|
|
if len(codes) == 2:
|
|
try:
|
|
value = int(float(codes[1]))
|
|
outCode['time'] = value
|
|
except:
|
|
outCode['code'] = None
|
|
elif bCode.startswith('torch-pulse') and not 'torch-pulse' in [(v['code']) for k, v in buttonCodes.items()]:
|
|
codes = bCode.lower().strip().replace(' ','').replace('torch-pulse','torch-pulse ').split()
|
|
if len(codes) < 3:
|
|
outCode = {'code':'torch-pulse', 'time':1.0}
|
|
torchButton = str(n)
|
|
torchText = bName.replace('\\', '\n')
|
|
if len(codes) == 2:
|
|
try:
|
|
value = round(float(codes[1]), 1)
|
|
outCode['time'] = value
|
|
except:
|
|
outCode['code'] = None
|
|
elif bCode.startswith('change-consumables') and not 'change-consumables' in [(v['code']) for k, v in buttonCodes.items()]:
|
|
codes = bCode.lower().strip().replace('x',' x').replace('y',' y').replace('f',' f').split()
|
|
if len(codes) > 1 and len(codes) < 5:
|
|
outCode = {'code':'change-consumables', 'X':None, 'Y':None, 'F':None}
|
|
for l in 'xyf':
|
|
for c in range(1, len(codes)):
|
|
if codes[c].startswith(l):
|
|
try:
|
|
value = round(float(codes[c].replace(l,'')), 3)
|
|
outCode['XYF'['xyf'.index(l)]] = value
|
|
except:
|
|
outCode['code'] = None
|
|
if outCode['X'] is None and outCode['Y'] is None:
|
|
outCode['code'] = None
|
|
else:
|
|
buff = 10 * unitsPerMm # keep 10mm away from machine limits
|
|
for axis in 'XY':
|
|
if outCode[axis]:
|
|
if outCode[f"{axis}"] < machineBounds[f"{axis}-"] + buff:
|
|
outCode[f"{axis}"] = machineBounds[f"{axis}-"] + buff
|
|
elif outCode[f"{axis}"] > machineBounds[f"{axis}+"] - buff:
|
|
outCode[f"{axis}"] = machineBounds[f"{axis}+"] - buff
|
|
if outCode['code']:
|
|
cChangeButton = str(n)
|
|
elif bCode.startswith('framing') and not 'framing' in [(v['code']) for k, v in buttonCodes.items()]:
|
|
codes = bCode.lower().strip().replace(' ','').replace('fra','ra').replace('f',' f') \
|
|
.replace('us',' us').replace('ra','fra').split()
|
|
if codes[0] == 'framing' and len(codes) < 4:
|
|
outCode = {'code':'framing', 'F':False, 'Z':False}
|
|
for c in range(1, len(codes)):
|
|
if codes[c].startswith('f'):
|
|
try:
|
|
value = round(float(codes[c].replace('f','')), 3)
|
|
outCode['F'] = value
|
|
except:
|
|
outCode['code'] = None
|
|
elif codes[c] == 'usecurrentzheight':
|
|
outCode['Z'] = True
|
|
else:
|
|
outCode['code'] = None
|
|
elif bCode.startswith('load'):
|
|
codes = bCode.strip().replace(' ','').replace('load','load ').split()
|
|
if len(codes) > 1 and len(codes) < 3:
|
|
if os.path.isfile(os.path.join(open_directory, codes[1])):
|
|
outCode = {'code':'load', 'file':os.path.join(open_directory, codes[1])}
|
|
elif bCode.startswith('latest-file') and not 'latest-file' in [(v['code']) for k, v in buttonCodes.items()]:
|
|
codes = bCode.strip().replace(' ','').replace('latest-file','latest-file ').split()
|
|
if len(codes) < 3:
|
|
outCode = {'code':'latest-file', 'dir':None}
|
|
if len(codes) == 1:
|
|
outCode['dir'] = open_directory
|
|
elif len(codes) == 2 and os.path.isdir(codes[1]):
|
|
outCode['dir'] = codes[1]
|
|
else:
|
|
outCode['code'] = None
|
|
elif bCode.startswith('pulse-halpin '):
|
|
if len(bCode.split()) > 1 and len(bCode.split()) < 4:
|
|
codes = bCode.strip().split()
|
|
if validate_hal_pin(codes[1], n, 'pulse-halpin'):
|
|
try:
|
|
value = round(float(codes[2]), 1)
|
|
outCode = {'code':'pulse-halpin', 'pin':codes[1], 'time':value}
|
|
pulsePins[str(n)] = {'pin':codes[1], 'text':None, 'pulse':0, 'state':False}
|
|
except:
|
|
outCode = {'code':None}
|
|
else:
|
|
parmError = True
|
|
elif bCode.startswith('toggle-halpin '):
|
|
if len(bCode.split()) > 1:
|
|
ontext = bName
|
|
if ';;' in bCode:
|
|
ontext = bCode.split(';;')[1] if ';;' in bCode else ''
|
|
bCode = bCode[:bCode.index(';;')].strip()
|
|
codes = bCode.strip().split()
|
|
if validate_hal_pin(codes[1], n, 'toggle-halpin'):
|
|
outCode = {'code':'toggle-halpin', 'pin':codes[1], 'critical':False, 'ontext':ontext}
|
|
outCode['pin'] = codes[1]
|
|
if len(codes) == 3 and (codes[2] == 'runcritical' or codes[2] == 'cutcritical'):
|
|
outCode['critical'] = True
|
|
criticalButtons.append(n)
|
|
togglePins[str(n)] = {'pin':outCode['pin'], 'state':hal.get_value(outCode['pin']), \
|
|
'runcritical':outCode['critical'], 'ontext':outCode['ontext'], \
|
|
'offtext':bName}
|
|
else:
|
|
parmError = True
|
|
elif bCode and bCode not in singleCodes:
|
|
if 'dual-code' in bCode:
|
|
# incoming code is: "dual-code" ;; code1 ;; label1 ;; code2 ;; checked (optional = true)
|
|
data = bCode.split(';;')
|
|
if len(data) not in [4, 5]:
|
|
outCode = {'code':None}
|
|
continue
|
|
else:
|
|
if len(data) == 5 and data[4].strip().lower() == 'true':
|
|
checked = True
|
|
else:
|
|
checked = False
|
|
dualCodes[str(n)] = {'ontext':data[2].strip(), 'offtext':bName.strip(), 'checked':checked}
|
|
codes = [code for code in data[1].split('\\') + ['dual-code'] + data[3].split('\\')]
|
|
else:
|
|
codes = bCode.strip().split('\\')
|
|
codes = [x.strip() for x in codes]
|
|
outCode['code'] = []
|
|
for cn in range(len(codes)):
|
|
if codes[cn][0] == '%':
|
|
if codes[cn][-3:] == '.py':
|
|
if '/' not in codes[cn]:
|
|
codes[cn] = f"%./{codes[cn].replace('%','')}"
|
|
if os.path.exists(os.path.expanduser(codes[cn][1:])):
|
|
outCode['code'].append(['python3', os.path.expanduser(codes[cn][1:])])
|
|
else:
|
|
outCode = {'code': None}
|
|
elif WHICH(codes[cn].split()[0][1:]) is not None:
|
|
outCode['code'].append(['shell', codes[cn][1:]])
|
|
else:
|
|
outCode = {'code': None}
|
|
elif codes[cn][:2].lower() == 'o<':
|
|
outCode['code'].append(['ocode', codes[cn]])
|
|
elif codes[cn][0].lower() in 'gm':
|
|
outCode['code'].append(['gcode', codes[cn]])
|
|
elif codes[cn] == 'dual-code':
|
|
outCode['code'].append(codes[cn])
|
|
else:
|
|
outCode = {'code': None}
|
|
break
|
|
if 'dual-code' in bCode:
|
|
dualCodes[str(n)]['oncode'] = outCode['code'][:outCode['code'].index('dual-code')]
|
|
dualCodes[str(n)]['offcode'] = outCode['code'][outCode['code'].index('dual-code')+1:]
|
|
outCode['code'] = 'dual-code'
|
|
else:
|
|
outCode = {'code':None}
|
|
if rE(f"winfo exists {fbuttons}.button{n}") == '0':
|
|
rE(f"button {fbuttons}.button{n} -takefocus 0 -width 10")
|
|
if bName and outCode['code']:
|
|
bHeight = 1
|
|
if type(bName) == list:
|
|
bHeight = max(len(bName[0].split('\\')), len(bName[1].split('\\')))
|
|
bName = bName[0]
|
|
else:
|
|
bHeight = len(bName.split('\\'))
|
|
bLabel = bName.replace('\\', '\n')
|
|
rE(f"{fbuttons}.button{n} configure -text {{{bLabel}}} -height {bHeight} -bg {colorBack}")
|
|
rE(f"bind {fbuttons}.button{n} <ButtonPress-1> {{button_action {n} 1}}")
|
|
rE(f"bind {fbuttons}.button{n} <ButtonRelease-1> {{button_action {n} 0}}")
|
|
row += 1
|
|
elif bName or bCode:
|
|
if not parmError:
|
|
msg0 = _('is invalid code for user button')
|
|
notifications.add('error', f"'{bCode}' {msg0} #{n}")
|
|
bName = None
|
|
outCode = {'code':None}
|
|
invalidButtons.append(n)
|
|
buttonNames[n] = {'name':bName}
|
|
buttonCodes[n] = outCode
|
|
user_button_load()
|
|
populate_user_buttons()
|
|
|
|
def user_button_pressed(button, code):
|
|
global colorBack, activeFunction
|
|
global probePressed, probeTimer, probeButton
|
|
global torchPressed, torchTimer, torchButton
|
|
if rE(f"{fbuttons}.button{button} cget -state") == 'disabled' or not code:
|
|
return
|
|
if code['code'] == 'ohmic-test':
|
|
hal.set_p('plasmac.ohmic-test','1')
|
|
# print window sizes in development mode
|
|
if comp['development']:
|
|
print(f"Width = {rE('winfo width .')} Height={rE('winfo height .')}")
|
|
elif code['code'] == 'cut-type':
|
|
pass # actioned from button_release
|
|
elif code['code'] == 'single-cut':
|
|
pass # actioned from button_release
|
|
elif code['code'] == 'manual-cut':
|
|
manual_cut(None)
|
|
elif code['code'] == 'probe-test' and not hal.get_value('halui.program.is-running'):
|
|
if probeTimer:
|
|
probeTimer = 0
|
|
probe_test_timer()
|
|
elif not hal.get_value('plasmac.z-offset-counts'):
|
|
msg = bounds_check_probe(True)
|
|
if msg:
|
|
notifications.add('error', msg)
|
|
return
|
|
activeFunction = True
|
|
probePressed = True
|
|
probeTimer = code['time'] * 1000
|
|
hal.set_p('plasmac.probe-test','1')
|
|
rE(f"{fbuttons}.button{probeButton} configure -text {str(int(probeTimer))}")
|
|
rE(f"{fbuttons}.button{probeButton} configure -bg {colorActive}")
|
|
root_window.after(100, probe_test_timer)
|
|
elif code['code'] == 'torch-pulse':
|
|
if torchTimer:
|
|
torchTimer = 0
|
|
torch_pulse_timer()
|
|
elif not hal.get_value('plasmac.z-offset-counts'):
|
|
torchPressed = True
|
|
torchTimer = code['time'] * 1000
|
|
hal.set_p('plasmac.torch-pulse-time',f"{torchTimer}")
|
|
hal.set_p('plasmac.torch-pulse-start','1')
|
|
rE(f"{fbuttons}.button{torchButton} configure -text {str(int(torchTimer))}")
|
|
rE(f"{fbuttons}.button{torchButton} configure -bg {colorActive}")
|
|
root_window.after(100, torch_pulse_timer)
|
|
elif code['code'] == 'change-consumables' and not hal.get_value('plasmac.breakaway'):
|
|
if hal.get_value('axis.x.eoffset-counts') or hal.get_value('axis.y.eoffset-counts'):
|
|
hal.set_p('plasmac.consumable-change', '0')
|
|
hal.set_p('plasmac.x-offset', '0')
|
|
hal.set_p('plasmac.y-offset', '0')
|
|
rE(f"{fbuttons}.button{button} configure -bg {colorBack}")
|
|
activeFunction = False
|
|
else:
|
|
activeFunction = True
|
|
xPos = s.position[0] if code['X'] is None else code['X']
|
|
yPos = s.position[1] if code['Y'] is None else code['Y']
|
|
if not code['F']:
|
|
code['F'] = rE(f"{fruns}.material.cut-feed-rate get")
|
|
hal.set_p('plasmac.xy-feed-rate', str(code['F']))
|
|
hal.set_p('plasmac.x-offset', f"{(xPos - s.position[0]) / hal.get_value('plasmac.offset-scale'):.0f}")
|
|
hal.set_p('plasmac.y-offset', f"{(yPos - s.position[1]) / hal.get_value('plasmac.offset-scale'):.0f}")
|
|
hal.set_p('plasmac.consumable-change', '1')
|
|
rE(f"{fbuttons}.button{button} configure -bg {colorActive}")
|
|
elif code['code'] == 'framing':
|
|
pass # actioned from button_release
|
|
elif code['code'] == 'load':
|
|
pass # actioned from button_release
|
|
elif code['code'] == 'latest-file':
|
|
pass # actioned from button_release
|
|
#FIXME - pin not turning off when button pressed and pin is on
|
|
elif code['code'] == 'pulse-halpin' and hal.get_value('halui.machine.is-on'):
|
|
if code['pin'].startswith('axisui.ext.out_'):
|
|
comp[code['pin'].replace('axisui.','')] = not hal.get_value(code['pin'])
|
|
else:
|
|
hal.set_p(code['pin'], str(not hal.get_value(code['pin'])))
|
|
if pulsePins[button]['pulse']:
|
|
pulsePins[button]['pulse'] = 0
|
|
rE(f"{fbuttons}.button{button} configure -text {{{pulsePins[button]['text']}}}")
|
|
else:
|
|
pulsePins[button]['pulse'] = code['time'] * 1000
|
|
pulsePins[button]['text'] = rE(f"{fbuttons}.button{button} cget -text")
|
|
root_window.after(100, pulse_halpin_off, button)
|
|
elif code['code'] == 'toggle-halpin' and hal.get_value('halui.machine.is-on'):
|
|
if code['pin'].startswith('axisui.ext.out_'):
|
|
comp[code['pin'].replace('axisui.','')] = not hal.get_value(code['pin'])
|
|
else:
|
|
hal.set_p(code['pin'], str(not hal.get_value(code['pin'])))
|
|
else:
|
|
if button in dualCodes:
|
|
if rE(f"{fbuttons}.button{button} cget -text") == dualCodes[button]['offtext']:
|
|
rE(f"{fbuttons}.button{button} configure -text {{{dualCodes[button]['ontext']}}}")
|
|
code['code'] = dualCodes[button]['oncode']
|
|
if dualCodes[button]['checked']:
|
|
rE(f"{fbuttons}.button{button} configure -bg {colorActive}")
|
|
else:
|
|
rE(f"{fbuttons}.button{button} configure -text {{{dualCodes[button]['offtext']}}}")
|
|
code['code'] = dualCodes[button]['offcode']
|
|
rE(f"{fbuttons}.button{button} configure -bg {colorBack}")
|
|
for n in range(len(code['code'])):
|
|
if code['code'][n][0] == 'python3':
|
|
cmd = f"python3 {code['code'][n][1]}"
|
|
Popen(cmd, stdin = None, stdout=PIPE, stderr=PIPE, shell=True)
|
|
elif code['code'][n][0] == 'shell':
|
|
Popen(code['code'][n][1], stdout=PIPE, stderr=PIPE, shell=True)
|
|
elif code['code'][n][0] in ['gcode', 'ocode']:
|
|
if manual_ok():
|
|
ensure_mode(linuxcnc.MODE_MDI)
|
|
c.mdi(code['code'][n][1])
|
|
update_preview()
|
|
|
|
def user_button_released(button, code):
|
|
global cutType, probePressed, torchPressed
|
|
if rE(f"{fbuttons}.button{button} cget -state") == 'disabled' or not code: return
|
|
if code['code'] == 'ohmic-test':
|
|
hal.set_p('plasmac.ohmic-test','0')
|
|
elif code['code'] == 'cut-type':
|
|
if not hal.get_value('halui.program.is-running'):
|
|
cutType ^= 1
|
|
if cutType:
|
|
comp['cut-type'] = 1
|
|
text = code['text'][1].replace('\\', '\n')
|
|
color = colorActive
|
|
else:
|
|
comp['cut-type'] = 0
|
|
text = code['text'][0].replace('\\', '\n')
|
|
color = colorBack
|
|
rE(f"{fbuttons}.button{button} configure -bg {color} -text {{{text}}}")
|
|
reload_file()
|
|
elif code['code'] == 'single-cut':
|
|
single_cut()
|
|
elif code['code'] == 'manual-cut':
|
|
pass
|
|
elif code['code'] == 'probe-test':
|
|
probePressed = False
|
|
elif code['code'] == 'torch-pulse':
|
|
torchPressed = False
|
|
elif code['code'] == 'change-consumables':
|
|
pass
|
|
elif code['code'] == 'framing':
|
|
if not code['F']:
|
|
code['F'] = int(rE(f"{fruns}.material.cut-feed-rate get"))
|
|
frame_job(code['F'], code['Z'])
|
|
elif code['code'] == 'load':
|
|
commands.open_file_name(code['file'])
|
|
elif code['code'] == 'latest-file':
|
|
files = GLOB(f"{code['dir']}/*.ngc")
|
|
latest = max(files, key=os.path.getctime)
|
|
commands.open_file_name(latest)
|
|
elif code['code'] == 'pulse-halpin':
|
|
pass
|
|
elif code['code'] == 'toggle-halpin':
|
|
pass
|
|
else:
|
|
pass
|
|
|
|
def user_button_load():
|
|
rE(f"{fsetup}.r.torch.enabled delete 0 end")
|
|
rE(f"{fsetup}.r.torch.disabled delete 0 end")
|
|
rE(f"{fsetup}.r.torch.enabled insert end {{{getPrefs(PREF, 'BUTTONS', 'Torch enabled', 'Torch Enabled', str)}}}")
|
|
rE(f"{fsetup}.r.torch.disabled insert end {{{getPrefs(PREF, 'BUTTONS','Torch disabled', 'Torch Disabled', str)}}}")
|
|
for n in range(1, maxUserButtons + 1):
|
|
rE(f"{fsetup}.r.ubuttons.canvas.frame.name{n} delete 0 end")
|
|
rE(f"{fsetup}.r.ubuttons.canvas.frame.code{n} delete 0 end")
|
|
if getPrefs(PREF, 'BUTTONS', f"{n} Name", '', str) or getPrefs(PREF, 'BUTTONS', f"{n} Code", '', str):
|
|
rE(f"{fsetup}.r.ubuttons.canvas.frame.name{n} insert end {{{getPrefs(PREF, 'BUTTONS', f'{n} Name', '', str)}}}")
|
|
rE(f"{fsetup}.r.ubuttons.canvas.frame.code{n} insert end {{{getPrefs(PREF, 'BUTTONS', f'{n} Code', '', str)}}}")
|
|
color_user_buttons()
|
|
|
|
def user_button_save():
|
|
global torchEnable
|
|
putPrefs(PREF, 'BUTTONS', 'Torch enabled', rE(f"{fsetup}.r.torch.enabled get"), str)
|
|
putPrefs(PREF, 'BUTTONS', 'Torch disabled', rE(f"{fsetup}.r.torch.disabled get"), str)
|
|
torchEnable['enabled'] = getPrefs(PREF, 'BUTTONS', 'Torch enabled', 'Torch Enabled', str)
|
|
torchEnable['disabled'] = getPrefs(PREF, 'BUTTONS','Torch disabled', 'Torch Disabled', str)
|
|
if '\\' in torchEnable['enabled'] or '\\' in torchEnable['disabled']:
|
|
rE(f"{fbuttons}.torch-enable configure -height 2")
|
|
else:
|
|
rE(f"{fbuttons}.torch-enable configure -height 1")
|
|
color_torch()
|
|
for n in range(1, maxUserButtons + 1):
|
|
putPrefs(PREF, 'BUTTONS', f"{n} Name", rE(f"{fsetup}.r.ubuttons.canvas.frame.name{n} get"), str)
|
|
putPrefs(PREF, 'BUTTONS', f"{n} Code", rE(f"{fsetup}.r.ubuttons.canvas.frame.code{n} get"), str)
|
|
rE(f"{fsetup}.r.ubuttons.canvas.frame.name{n} delete 0 end")
|
|
rE(f"{fsetup}.r.ubuttons.canvas.frame.code{n} delete 0 end")
|
|
user_button_setup()
|
|
|
|
def probe_test_timer():
|
|
global probeTimer, activeFunction
|
|
if probeTimer > 0:
|
|
probeTimer -= 100
|
|
if hal.get_value('plasmac.probe-test-error') and not probePressed:
|
|
probeTimer = 0
|
|
if probeTimer > 0:
|
|
rE(f"{fbuttons}.button{probeButton} configure -text {{{round(probeTimer / 1000, 1)}}}")
|
|
root_window.after(100, probe_test_timer)
|
|
if probeTimer <= 0:
|
|
if probePressed:
|
|
root_window.after(100, probe_test_timer)
|
|
else:
|
|
hal.set_p('plasmac.probe-test','0')
|
|
rE(f"{fbuttons}.button{probeButton} configure -text {{{probeText}}}")
|
|
rE(f"{fbuttons}.button{probeButton} configure -bg {colorBack}")
|
|
probeTimer = 0
|
|
activeFunction = False
|
|
|
|
def torch_pulse_timer():
|
|
global torchTimer
|
|
if torchTimer > 0:
|
|
torchTimer -= 100
|
|
if torchTimer > 0:
|
|
rE(f"{fbuttons}.button{torchButton} configure -text {{{round(torchTimer / 1000, 1)}}}")
|
|
root_window.after(100, torch_pulse_timer)
|
|
if torchTimer <= 0:
|
|
if torchPressed:
|
|
root_window.after(100, torch_pulse_timer)
|
|
else:
|
|
hal.set_p('plasmac.torch-pulse-start','0')
|
|
hal.set_p('plasmac.torch-pulse-time', '0')
|
|
rE(f"{fbuttons}.button{torchButton} configure -text {{{torchText}}}")
|
|
rE(f"{fbuttons}.button{torchButton} configure -bg {colorBack}")
|
|
torchTimer = 0
|
|
|
|
def pulse_halpin_off(button):
|
|
if pulsePins[button]['pulse'] > 0:
|
|
pulsePins[button]['pulse'] -= 100
|
|
if pulsePins[button]['pulse'] > 0:
|
|
rE(f"{fbuttons}.button{button} configure -text {round(pulsePins[button]['pulse'] / 1000, 1)}")
|
|
root_window.after(100, pulse_halpin_off, button)
|
|
if pulsePins[button]['pulse'] <= 0:
|
|
rE(f"{fbuttons}.button{button} configure -text {{{pulsePins[button]['text']}}}")
|
|
if pulsePins[button]['pin'].startswith('axisui.ext.out_'):
|
|
comp[pulsePins[button]['pin'].replace('axisui.','')] = not hal.get_value(pulsePins[button]['pin'])
|
|
else:
|
|
hal.set_p(pulsePins[button]['pin'], str(not hal.get_value(pulsePins[button]['pin'])))
|
|
pulsePins[button]['pulse'] = 0
|
|
|
|
|
|
##############################################################################
|
|
# MATERIAL HANDLING FUNCTIONS #
|
|
##############################################################################
|
|
def get_displayed_material():
|
|
try:
|
|
return int(rE(f"{fruns}.material.materials get").split(":")[0])
|
|
except:
|
|
return -1
|
|
|
|
def save_material_clicked():
|
|
matNum = get_displayed_material()
|
|
save_one_material(matNum)
|
|
load_materials(matNum, True)
|
|
|
|
def reload_material_clicked():
|
|
MATS.clear()
|
|
MATS.read(MATS.fn)
|
|
load_materials(get_displayed_material(), True)
|
|
|
|
def new_material_clicked():
|
|
global materialNumList
|
|
for n in range(1, 1000000):
|
|
if n not in materialNumList:
|
|
new = n
|
|
break
|
|
title = _('ADD MATERIAL')
|
|
msg1 = _('Enter New Material Number')
|
|
msgs = msg1
|
|
while(1):
|
|
valid, num = plasmacPopUp('entry', title, f"{msgs}:", 'numpad', new).reply
|
|
if not valid:
|
|
return
|
|
if not num:
|
|
msg0 = _('A material number is required')
|
|
msgs = f"{msg0}.\n\n{msg1}:"
|
|
continue
|
|
try:
|
|
num = int(num)
|
|
except:
|
|
msg0 = _('is not a valid number')
|
|
msgs = f"{num} {msg0}.\n\n{msg1}:"
|
|
continue
|
|
if num == 0 or num in materialNumList:
|
|
msg0 = _('Material')
|
|
msg2 = _('is in use')
|
|
msgs = f"{msg0} #{num} {msg2}.\n\n{msg1}:"
|
|
elif num >= 1000000:
|
|
msg0 = _('Material numbers need to be less than 1000000')
|
|
msgs = f"{msg0}.\n\n{msg1}:"
|
|
else:
|
|
break
|
|
msg1 = _('Enter New Material Name')
|
|
msgs = msg1
|
|
while(1):
|
|
valid, nam = plasmacPopUp('entry', title, f"{msgs}:", 'keyboard').reply
|
|
if not valid:
|
|
return
|
|
if not nam:
|
|
msg0 = _('Material name is required')
|
|
msgs = f"{msg0}.\n\n{msg1}:"
|
|
else:
|
|
break
|
|
putPrefs(MATS,f"MATERIAL_NUMBER_{num}",'NAME', nam, str)
|
|
save_one_material(num)
|
|
sortPrefs(MATS)
|
|
load_materials(num, True)
|
|
|
|
def delete_material_clicked():
|
|
title = _('DELETE MATERIAL')
|
|
msg0 = _('Default material cannot be deleted')
|
|
material = int(rE(f"{fruns}.material.materials get").split(':')[0])
|
|
if material == getPrefs(PREF, 'GUI_OPTIONS', 'Default material', 0, int):
|
|
reply = plasmacPopUp('warn', title, msg0).reply
|
|
return
|
|
msg0 = _('Do you wish to delete material')
|
|
reply = plasmacPopUp('yesno', title, f"{msg0} #{material}?").reply
|
|
if not reply:
|
|
return
|
|
removePrefsSect(MATS,f"MATERIAL_NUMBER_{get_displayed_material()}")
|
|
load_materials(-1, True)
|
|
|
|
def material_changed():
|
|
global getMaterialBusy, materialAutoChange
|
|
if rE(f"{fruns}.material.materials get"):
|
|
if getMaterialBusy:
|
|
comp['material-change'] = 0
|
|
materialAutoChange = False
|
|
return
|
|
matnum = int(rE(f"{fruns}.material.materials get").split(': ', 1)[0])
|
|
if matnum >= 1000000:
|
|
rE(f"{toolmat}.save configure -state disabled")
|
|
else:
|
|
rE(f"{toolmat}.save configure -state normal")
|
|
if materialAutoChange:
|
|
hal.set_p('motion.digital-in-03','0')
|
|
display_selected_material(matnum)
|
|
comp['material-change'] = 2
|
|
hal.set_p('motion.digital-in-03','1')
|
|
else:
|
|
display_selected_material(matnum)
|
|
materialAutoChange = False
|
|
|
|
def material_change_pin_changed(halpin):
|
|
if halpin == 0:
|
|
hal.set_p('motion.digital-in-03','0')
|
|
elif halpin == 3:
|
|
hal.set_p('motion.digital-in-03','1')
|
|
comp['material-change'] = 0
|
|
|
|
def material_change_number_pin_changed(halpin):
|
|
global getMaterialBusy, materialAutoChange
|
|
if getMaterialBusy:
|
|
return
|
|
if comp['material-change'] == 1:
|
|
materialAutoChange = True
|
|
if halpin == -1:
|
|
halpin = pVars.matDefault.get()
|
|
if not material_exists(halpin):
|
|
materialAutoChange = False
|
|
return
|
|
index = f"@{materialNumList.index(halpin)}"
|
|
rE(f"{fruns}.material.materials setvalue {index}")
|
|
display_selected_material(halpin)
|
|
|
|
def material_change_timeout_pin_changed(halpin):
|
|
if halpin:
|
|
material = rE(f"{fruns}.material.materials get").split(': ', 1)[0]
|
|
msg0 = _('Material change timeout occurred for material')
|
|
notifications.add('error', f"{msg0} #{material}\n")
|
|
comp['material-change-number'] = material
|
|
comp['material-change-timeout'] = 0
|
|
hal.set_p('motion.digital-in-03','0')
|
|
|
|
def material_temp_pin_changed(halpin):
|
|
if halpin:
|
|
TEMP.read(TEMP.fn)
|
|
material = get_one_material(TEMP, f"MATERIAL_NUMBER_{halpin}", halpin)
|
|
if not material['valid']:
|
|
msg0 = _('Temporary material')
|
|
msg1 = _('is invalid')
|
|
notifications.add('error', f"{msg0} #{halpin} {msg1}\n")
|
|
return
|
|
materialFileDict[halpin] = { \
|
|
'name': material['name'], \
|
|
'kerf_width': material['kerf_width'], \
|
|
'pierce_height': material['pierce_height'], \
|
|
'pierce_delay': material['pierce_delay'], \
|
|
'puddle_jump_height': material['puddle_jump_height'], \
|
|
'puddle_jump_delay': material['puddle_jump_delay'], \
|
|
'cut_height': material['cut_height'], \
|
|
'cut_speed': material['cut_speed'], \
|
|
'cut_amps': material['cut_amps'], \
|
|
'cut_volts': material['cut_volts'], \
|
|
'pause_at_end': material['pause_at_end'], \
|
|
'gas_pressure': material['gas_pressure'], \
|
|
'cut_mode': material['cut_mode']}
|
|
insert_materials()
|
|
comp['material-temp'] = 0
|
|
|
|
def insert_materials():
|
|
global materialNumList, materialFileDict, matNames
|
|
mats = ''
|
|
matDefaults = ''
|
|
materialNumList = []
|
|
for matnum in sorted(materialFileDict):
|
|
mats += f" {{{matnum}: {materialFileDict[matnum]['name']}}}"
|
|
materialNumList.append(matnum)
|
|
if matnum < 1000000:
|
|
matDefaults += f" {{{matnum}}}"
|
|
rE(f"{fruns}.material.materials configure -values {{{mats}}}")
|
|
rE(f"{fsetup}.l.gui.matdefault configure -values {{{matDefaults}}}")
|
|
matNames = mats
|
|
|
|
def display_selected_material(matnum, reload=False):
|
|
rE(f"{fruns}.material.kerf-width set {materialFileDict[matnum]['kerf_width']}")
|
|
rE(f"{fruns}.material.pierce-height set {materialFileDict[matnum]['pierce_height']}")
|
|
rE(f"{fruns}.material.pierce-delay set {materialFileDict[matnum]['pierce_delay']}")
|
|
rE(f"{fruns}.material.puddle-jump-height set {materialFileDict[matnum]['puddle_jump_height']}")
|
|
rE(f"{fruns}.material.puddle-jump-delay set {materialFileDict[matnum]['puddle_jump_delay']}")
|
|
rE(f"{fruns}.material.cut-height set {materialFileDict[matnum]['cut_height']}")
|
|
rE(f"{fruns}.material.cut-feed-rate set {materialFileDict[matnum]['cut_speed']}")
|
|
rE(f"{fruns}.material.cut-amps set {materialFileDict[matnum]['cut_amps']}")
|
|
rE(f"{fruns}.material.cut-volts set {materialFileDict[matnum]['cut_volts']}")
|
|
rE(f"{fruns}.material.pause-at-end set {materialFileDict[matnum]['pause_at_end']}")
|
|
rE(f"{fruns}.material.gas-pressure set {materialFileDict[matnum]['gas_pressure']}")
|
|
rE(f"{fruns}.material.cut-mode set {materialFileDict[matnum]['cut_mode']}")
|
|
if not reload:
|
|
comp['material-change-number'] = matnum
|
|
|
|
def save_one_material(num):
|
|
section = f"MATERIAL_NUMBER_{num}"
|
|
putPrefs(MATS,section, 'KERF_WIDTH', rE(f"{fruns}.material.kerf-width get"), float)
|
|
putPrefs(MATS,section, 'PIERCE_HEIGHT', rE(f"{fruns}.material.pierce-height get"), float)
|
|
putPrefs(MATS,section, 'PIERCE_DELAY', rE(f"{fruns}.material.pierce-delay get"), float)
|
|
putPrefs(MATS,section, 'PUDDLE_JUMP_HEIGHT', rE(f"{fruns}.material.puddle-jump-height get"), int)
|
|
putPrefs(MATS,section, 'PUDDLE_JUMP_DELAY',rE(f"{fruns}.material.puddle-jump-delay get"), float)
|
|
putPrefs(MATS,section, 'CUT_HEIGHT', rE(f"{fruns}.material.cut-height get"), float)
|
|
putPrefs(MATS,section, 'CUT_SPEED', rE(f"{fruns}.material.cut-feed-rate get"), int)
|
|
putPrefs(MATS,section, 'CUT_AMPS', rE(f"{fruns}.material.cut-amps get"), int)
|
|
putPrefs(MATS,section, 'CUT_VOLTS', rE(f"{fruns}.material.cut-volts get"), int)
|
|
putPrefs(MATS,section, 'PAUSE_AT_END', rE(f"{fruns}.material.pause-at-end get"), float)
|
|
putPrefs(MATS,section, 'GAS_PRESSURE', rE(f"{fruns}.material.gas-pressure get"), float)
|
|
putPrefs(MATS,section, 'CUT_MODE', rE(f"{fruns}.material.cut-mode get"), int)
|
|
|
|
def set_saved_material():
|
|
matnum = int(rE(f"{fruns}.material.materials get").split(':')[0])
|
|
materialFileDict[matnum] = { \
|
|
'name': rE(f"{fruns}.material.materials get").split(':')[1], \
|
|
'kerf_width': rE(f"{fruns}.material.kerf-width get"), \
|
|
'pierce_height': rE(f"{fruns}.material.pierce-height get"), \
|
|
'pierce_delay': rE(f"{fruns}.material.pierce-delay get"), \
|
|
'puddle_jump_height': rE(f"{fruns}.material.puddle-jump-height get"), \
|
|
'puddle_jump_delay': rE(f"{fruns}.material.puddle-jump-delay get"), \
|
|
'cut_height': rE(f"{fruns}.material.cut-height get"), \
|
|
'cut_speed': rE(f"{fruns}.material.cut-feed-rate get"), \
|
|
'cut_amps': rE(f"{fruns}.material.cut-amps get"), \
|
|
'cut_volts': rE(f"{fruns}.material.cut-volts get"), \
|
|
'pause_at_end': rE(f"{fruns}.material.pause-at-end get"), \
|
|
'gas_pressure': rE(f"{fruns}.material.gas-pressure get"), \
|
|
'cut_mode': rE(f"{fruns}.material.cut-mode get")}
|
|
|
|
def get_one_material(prefs, section, matnum):
|
|
global notifications
|
|
material = {}
|
|
# we bring in some ints as floats so we can read QtPlasmaC material files
|
|
material['name'] = getPrefs(prefs, section, 'NAME', 'Material', str)
|
|
material['kerf_width'] = getPrefs(prefs, section, 'KERF_WIDTH', round(1 * unitsPerMm, 2), float)
|
|
material['pierce_height'] = getPrefs(prefs, section, 'PIERCE_HEIGHT', round(3.0 * unitsPerMm, 2), float)
|
|
material['pierce_delay'] = getPrefs(prefs, section, 'PIERCE_DELAY', 0, float)
|
|
material['puddle_jump_height'] = int(getPrefs(prefs, section, 'PUDDLE_JUMP_HEIGHT', 0, float))
|
|
material['puddle_jump_delay'] = getPrefs(prefs, section, 'PUDDLE_JUMP_DELAY', 0, float)
|
|
material['cut_height'] = getPrefs(prefs, section, 'CUT_HEIGHT', round(1.0 * unitsPerMm, 2), float)
|
|
material['cut_speed'] = int(getPrefs(prefs, section, 'CUT_SPEED', round(2540 * unitsPerMm, 0), float))
|
|
material['cut_amps'] = int(getPrefs(prefs, section, 'CUT_AMPS', 45, float))
|
|
material['cut_volts'] = int(getPrefs(prefs, section, 'CUT_VOLTS', 100, float))
|
|
material['pause_at_end'] = getPrefs(prefs, section, 'PAUSE_AT_END', 0, float)
|
|
material['gas_pressure'] = getPrefs(prefs, section, 'GAS_PRESSURE', 0, float)
|
|
material['cut_mode'] = int(getPrefs(prefs, section, 'CUT_MODE', 1, float))
|
|
material['valid'] = True
|
|
required = {'pierce_height':material['pierce_height'],'cut_height':material['cut_height'],'cut_speed':material['cut_speed']}
|
|
for item in required:
|
|
if not required[item]:
|
|
material['valid'] = False
|
|
msg0 = _('is missing from Material')
|
|
notifications.add('error',f"{item} {msg0} #{matnum}\n")
|
|
return material
|
|
|
|
def set_material_dict(materialFileDict, matnum, material):
|
|
materialFileDict[matnum] = { \
|
|
'name': material['name'], \
|
|
'kerf_width': material['kerf_width'], \
|
|
'pierce_height': material['pierce_height'], \
|
|
'pierce_delay': material['pierce_delay'], \
|
|
'puddle_jump_height': material['puddle_jump_height'], \
|
|
'puddle_jump_delay': material['puddle_jump_delay'], \
|
|
'cut_height': material['cut_height'], \
|
|
'cut_speed': material['cut_speed'], \
|
|
'cut_amps': material['cut_amps'], \
|
|
'cut_volts': material['cut_volts'], \
|
|
'pause_at_end': material['pause_at_end'], \
|
|
'gas_pressure': material['gas_pressure'], \
|
|
'cut_mode': material['cut_mode']}
|
|
|
|
def load_materials(display, keepTemp):
|
|
global getMaterialBusy, materialFileDict
|
|
if keepTemp:
|
|
pop = [key for key in materialFileDict if key < 1000000]
|
|
for e in pop:
|
|
materialFileDict.pop(e)
|
|
else:
|
|
materialFileDict = {}
|
|
getMaterialBusy = True
|
|
if not MATS.sections():
|
|
msg0 = _('Creating new materials file')
|
|
notifications.add('error', f"{msg0}\n")
|
|
material = get_one_material(MATS, 'MATERIAL_NUMBER_0', 0)
|
|
set_material_dict(materialFileDict, 0, material)
|
|
else:
|
|
for section in MATS.sections():
|
|
matnum = int(section.rsplit('_', 1)[1].strip().strip(']'))
|
|
if matnum >= 1000000:
|
|
msg0 = _('Material number')
|
|
msg1 = _('is invalid')
|
|
msg2 = _('Material numbers need to be less than 1000000')
|
|
notifications.add('error', f"{msg0} {matnum} {msg1}\n{msg2}\n")
|
|
continue
|
|
material = get_one_material(MATS, section, matnum)
|
|
if not material['valid']:
|
|
continue
|
|
set_material_dict(materialFileDict, matnum, material)
|
|
if not materialFileDict:
|
|
msg0 = _('Materials file is empty or corrupt')
|
|
notifications.add('error', f"{msg0}\n")
|
|
return
|
|
insert_materials()
|
|
value = getPrefs(PREF, 'GUI_OPTIONS', 'Default material', materialNumList[0], int)
|
|
pVars.matDefault.set(value)
|
|
restoreSetup['matDefault'] = value
|
|
if pVars.matDefault.get() not in materialNumList:
|
|
mat = sorted(materialNumList)[0]
|
|
msg0 = _('Default material')
|
|
msg1 = _('was not found')
|
|
msg2 = _('Changing default material to')
|
|
notifications.add('info', f"{msg0} #{pVars.matDefault.get()} {msg1}\n{msg2} #{mat}\n")
|
|
pVars.matDefault.set(mat)
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Default material', pVars.matDefault.get(), int)
|
|
if display == -1 or get_displayed_material() not in materialNumList:
|
|
display = pVars.matDefault.get()
|
|
index = f"@{materialNumList.index(display)}"
|
|
rE(f"{fruns}.material.materials setvalue {index}")
|
|
display_selected_material(display)
|
|
material_list_width()
|
|
getMaterialBusy = False
|
|
|
|
def change_default_material():
|
|
display_selected_material(pVars.matDefault.get())
|
|
|
|
def material_exists(material):
|
|
global materialNumList, materialAutoChange
|
|
if int(material) in materialNumList:
|
|
return True
|
|
else:
|
|
if materialAutoChange:
|
|
comp['material-change'] = -1
|
|
comp['material-change-number'] = rE(f"{fruns}.material.materials get").split(':')[0]
|
|
msg0 = _('Material')
|
|
msg1 = _('not in material list')
|
|
notifications.add('error', f"{msg0} #{int(material)} {msg1}\n")
|
|
return False
|
|
|
|
|
|
##############################################################################
|
|
# POWERMAX COMMUNICATIONS FUNCTIONS #
|
|
##############################################################################
|
|
def pmx485_check(port, periodic=False):
|
|
if not comPorts:
|
|
return False
|
|
msg1 = _('Powermax communications is disabled')
|
|
ports = []
|
|
for p in comPorts.comports():
|
|
ports.append(p[0])
|
|
if port in ports:
|
|
try:
|
|
sPort = serial.Serial(port, 19200)
|
|
sPort.close()
|
|
except Exception as err:
|
|
if not periodic:
|
|
notifications.add('error', f"{err}\n{msg1}")
|
|
return False
|
|
else:
|
|
if not periodic:
|
|
msg0 = _('cannot be found')
|
|
notifications.add('error', f"{port} {msg0}\n{msg1}")
|
|
return False
|
|
return True
|
|
|
|
def pmx485_startup(port):
|
|
global pmx485
|
|
if pmx485_load(port):
|
|
return
|
|
pmx485['exists'] = True
|
|
pVars.pmx485Enable.set(True)
|
|
pmx485_enable_toggled()
|
|
|
|
def pmx485_load(port):
|
|
import subprocess
|
|
msg0 = _('PMX485 component is not able to be loaded,')
|
|
msg1 = _('Powermax communications are not available')
|
|
count = 0
|
|
while not hal.component_exists('pmx485'):
|
|
if count >= 3:
|
|
notifications.add('error', f"{msg0}\n{msg1}\n")
|
|
rE(f"{fruns}.pmx.info configure -text {{{_('Comms Error')}}} -bg red")
|
|
return 1
|
|
subprocess.run(['halcmd', 'loadusr', '-Wn', 'pmx485', 'pmx485', f"{port}"])
|
|
count += 1
|
|
return 0
|
|
|
|
def pmx485_enable_toggled():
|
|
global pmx485
|
|
if pVars.pmx485Enable.get():
|
|
pmx485['commsError'] = False
|
|
pmx485['retryTimer'] = 0
|
|
if pmx485_load(pmPort):
|
|
return
|
|
# ensure valid parameters before trying to connect
|
|
if pVars.cutMode.get() == 0 or pVars.cutAmps.get() == 0:
|
|
msg0 = _('Invalid Cut Mode or Cut Amps')
|
|
msg1 = _('cannot connect to Powermax')
|
|
notifications.add('error', f"{msg0}\n{msg1}\n")
|
|
pVars.pmx485Enable.set(False)
|
|
return
|
|
# good to go
|
|
else:
|
|
hal.set_p('pmx485.pressure_set', str(pVars.gasPressure.get()))
|
|
hal.set_p('pmx485.current_set', str(pVars.cutAmps.get()))
|
|
hal.set_p('pmx485.mode_set', str(pVars.cutMode.get()))
|
|
hal.set_p('pmx485.enable', '1')
|
|
rE(f"{fruns}.pmx.info configure -text {{{_('Connecting')}}} -bg {colorBack}")
|
|
pmx485['commsTimer'] = 3
|
|
else:
|
|
if hal.component_exists('pmx485'):
|
|
hal.set_p('pmx485.enable', '0')
|
|
pmx485['connected'] = False
|
|
pmx485['commsError'] = False
|
|
pmx485['commsTimer'] == 0
|
|
pmx485['retryTimer'] == 0
|
|
blank = ''
|
|
rE(f"{fruns}.pmx.info configure -text {blank} -bg {colorBack}")
|
|
|
|
def pmx485_current_changed(value):
|
|
hal.set_p('pmx485.current_set', str(value))
|
|
|
|
def pmx485_mode_changed(value):
|
|
pVars.gasPressure.set(0)
|
|
hal.set_p('pmx485.pressure_set', '0')
|
|
hal.set_p('pmx485.mode_set', str(value))
|
|
|
|
def pmx485_pressure_changed(value):
|
|
if value > 0 and value < int(hal.get_value('pmx485.pressure_min') / 2):
|
|
pVars.gasPressure.set(int(hal.get_value('pmx485.pressure_min')))
|
|
elif value > int(hal.get_value('pmx485.pressure_min') / 2) and value < hal.get_value('pmx485.pressure_min'):
|
|
pVars.gasPressure.set(0)
|
|
else:
|
|
pVars.gasPressure.set(float(value))
|
|
hal.set_p('pmx485.pressure_set', str(pVars.gasPressure.get()))
|
|
|
|
def pmx485_min_current_changed():
|
|
rE(f"{fruns}.material.cut-amps configure -from hal.get_value('pmx485.current_min')")
|
|
|
|
def pmx485_max_current_changed():
|
|
rE(f"{fruns}.material.cut-amps configure -to hal.get_value('pmx485.current_max')")
|
|
|
|
def pmx485_max_pressure_changed():
|
|
rE(f"{fruns}.material.gas-pressure configure -to hal.get_value('pmx485.pressure_max')")
|
|
if float(hal.get_value('pmx485.pressure_max')) > 15:
|
|
rE(f"{fruns}.material.gas-pressureL configure -text {{{_('Gas Pressure psi')}}}")
|
|
rE(f"{fruns}.material.gas-pressure configure -increment 1 -format %0.0f")
|
|
else:
|
|
rE(f"{fruns}.material.gas-pressureL configure -text _('Gas Pressure bar')")
|
|
rE(f"{fruns}.material.gas-pressure configure -increment 0.1 -format %0.1f")
|
|
|
|
def pmx485_status_changed(state):
|
|
global pmx485
|
|
if state != pmx485['connected']:
|
|
if state:
|
|
pmx485['commsError'] = False
|
|
rE(f"{fruns}.pmx.info configure -text {{{_('Connected')}}} -bg green")
|
|
pmx485['connected'] = True
|
|
# probably not required as we change the text directly in periodic
|
|
#if pmx485['compArcTime']:
|
|
# pmx485_arc_time_changed(pmx485['compArcTime'])
|
|
# probably not required as we check the fault in periodic
|
|
#if hal.get_value('pmx485.fault'):
|
|
# pmx485_fault_changed(hal.get_value('pmx485.fault'))
|
|
pmx485['commsTimer'] = 0
|
|
pmx485['retryTimer'] = 0
|
|
else:
|
|
rE(f"{fruns}.pmx.info configure -text {{{_('Comms Error')}}} -bg red")
|
|
pmx485['commsError'] = True
|
|
pmx485['connected'] = False
|
|
pmx485['retryTimer'] = 3
|
|
|
|
def pmx485_fault_changed(fault):
|
|
global pmx485
|
|
if pmx485['connected']:
|
|
faultRaw = f"{fault:04.0f}"
|
|
pmx485['compFaultCode'] = f"{faultRaw[0]}-{faultRaw[1:3]}-{faultRaw[3]}"
|
|
code = _('Fault Code')
|
|
if faultRaw == '0000':
|
|
rE(f"{fruns}.pmx.info configure -text {{{_('Connected')}}} -bg green")
|
|
elif faultRaw in pmx485FaultName.keys():
|
|
if faultRaw == '0210' and hal.get_value('pmx485.current_max') > 110:
|
|
faultMsg = pmx485FaultName[faultRaw][1]
|
|
elif faultRaw == '0210':
|
|
faultMsg = pmx485FaultName[faultRaw][0]
|
|
else:
|
|
faultMsg = pmx485FaultName[faultRaw]
|
|
rE(f"{fruns}.pmx.info configure -text {{{code}: {pmx485['compFaultCode']}}} -bg red")
|
|
msg0 = _('Code')
|
|
notifications.add('error', f"{msg0}: {pmx485['compFaultCode']}\n{faultMsg}\n")
|
|
else:
|
|
rE(f"{fruns}.pmx.info configure -text {{{code}: {pmx485['compFaultCode']}}} -bg red")
|
|
pmx485['labelState'] = None
|
|
msg0 = _('Unknown Powermax fault code')
|
|
notifications.add('error', f"{msg0}: {faultRaw}\n")
|
|
|
|
def pmx485_mesh_enable_toggled():
|
|
global pmx485
|
|
if pVars.meshEnable.get() and not pmx485['meshMode']:
|
|
pmx485['oldMode'] = pVars.cutMode.get()
|
|
pVars.cutMode.set(2)
|
|
rE(f"{fruns}.material.cut-mode configure -state disabled")
|
|
pmx485['meshMode'] = True
|
|
hal.set_p('plasmac.mesh-enable', '1')
|
|
elif hal.get_value('plasmac.mesh-enable') and pmx485['meshMode']:
|
|
pVars.cutMode.set(pmx485['oldMode'])
|
|
rE(f"{fruns}.material.cut-mode configure -state normal")
|
|
pmx485['meshMode'] = False
|
|
hal.set_p('plasmac.mesh-enable', '0')
|
|
|
|
def pmx485_comms_timeout():
|
|
global pmx485
|
|
rE(f"{fruns}.pmx.info configure -text {{{_('Comms Error')}}} -bg red")
|
|
pmx485['commsError'] = True
|
|
pmx485['connected'] = False
|
|
pmx485['retryTimer'] = 3
|
|
|
|
def pmx485_retry_timeout():
|
|
pmx485_enable_toggled()
|
|
|
|
pmx485FaultName = {
|
|
'0110': _('Remote controller mode invalid'),
|
|
'0111': _('Remote controller current invalid'),
|
|
'0112': _('Remote controller pressure invalid'),
|
|
'0120': _('Low input gas pressure'),
|
|
'0121': _('Output gas pressure low'),
|
|
'0122': _('Output gas pressure high'),
|
|
'0123': _('Output gas pressure unstable'),
|
|
'0130': _('AC input power unstable'),
|
|
'0199': _('Power board hardware protection'),
|
|
'0200': _('Low gas pressure'),
|
|
'0210': (_('Gas flow lost while cutting'), _('Excessive arc voltage')),
|
|
'0220': _('No gas input'),
|
|
'0300': _('Torch stuck open'),
|
|
'0301': _('Torch stuck closed'),
|
|
'0320': _('End of consumable life'),
|
|
'0400': _('PFC/Boost IGBT module under temperature'),
|
|
'0401': _('PFC/Boost IGBT module over temperature'),
|
|
'0402': _('Inverter IGBT module under temperature'),
|
|
'0403': _('Inverter IGBT module over temperature'),
|
|
'0500': _('Retaining cap off'),
|
|
'0510': _('Start/trigger signal on at power up'),
|
|
'0520': _('Torch not connected'),
|
|
'0600': _('AC input voltage phase loss'),
|
|
'0601': _('AC input voltage too low'),
|
|
'0602': _('AC input voltage too high'),
|
|
'0610': _('AC input unstable'),
|
|
'0980': _('Internal communication failure'),
|
|
'0990': _('System hardware fault'),
|
|
'1000': _('Digital signal processor fault'),
|
|
'1100': _('A/D converter fault'),
|
|
'1200': _('I/O fault'),
|
|
'2000': _('A/D converter value out of range'),
|
|
'2010': _('Auxiliary switch disconnected'),
|
|
'2100': _('Inverter module temp sensor open'),
|
|
'2101': _('Inverter module temp sensor shorted'),
|
|
'2110': _('Pressure sensor is open'),
|
|
'2111': _('Pressure sensor is shorted'),
|
|
'2200': _('DSP does not recognize the torch'),
|
|
'3000': _('Bus voltage fault'),
|
|
'3100': _('Fan speed fault'),
|
|
'3101': _('Fan fault'),
|
|
'3110': _('PFC module temperature sensor open'),
|
|
'3111': _('PFC module temperature sensor shorted'),
|
|
'3112': _('PFC module temperature sensor circuit fault'),
|
|
'3200': _('Fill valve'),
|
|
'3201': _('Dump valve'),
|
|
'3201': _('Valve ID'),
|
|
'3203': _('Electronic regulator is disconnected'),
|
|
'3410': _('Drive fault'),
|
|
'3420': _('5 or 24 VDC fault'),
|
|
'3421': _('18 VDC fault'),
|
|
'3430': _('Inverter capacitors unbalanced'),
|
|
'3441': _('PFC over current'),
|
|
'3511': _('Inverter saturation fault'),
|
|
'3520': _('Inverter shoot-through fault'),
|
|
'3600': _('Power board fault'),
|
|
'3700': _('Internal serial communications fault'),
|
|
}
|
|
|
|
|
|
##############################################################################
|
|
# EXTERNAL HAL PINS #
|
|
##############################################################################
|
|
# called during setup
|
|
def ext_hal_create():
|
|
global extHalPins
|
|
for pin in ['abort', 'power', 'run', 'pause', 'run-pause', 'touchoff',
|
|
'probe','pulse', 'frame-job']:
|
|
comp.newpin(f"ext.{pin}", hal.HAL_BIT, hal.HAL_IN)
|
|
extHalPins[pin] = {'state': False, 'last': False}
|
|
# external pins for user button toggle and pulse
|
|
for pin in range(3):
|
|
comp.newpin(f"ext.out_{pin}", hal.HAL_BIT, hal.HAL_OUT)
|
|
# pins for pierce only offsets
|
|
for pin in 'xy':
|
|
comp.newpin(f"{pin}-pierce-offset", hal.HAL_FLOAT, hal.HAL_OUT)
|
|
# pins for pierce coordinate extents
|
|
for pin in ['x_min', 'y_min', 'x_max', 'y_max']:
|
|
comp.newpin(f"{pin}_pierce_extent", hal.HAL_FLOAT, hal.HAL_IN)
|
|
|
|
# called every cycle by user_live_update
|
|
def ext_hal_watch():
|
|
global extHalPins, isIdle, isIdleHomed, isPaused, isRunning, probePressed, torchPressed
|
|
for pin in extHalPins:
|
|
state = comp[f"ext.{pin}"]
|
|
if state != extHalPins[pin]['last']:
|
|
extHalPins[pin]['last'] = state
|
|
# pressed commands
|
|
if state:
|
|
if pin == 'abort':
|
|
commands.task_stop()
|
|
elif pin == 'power':
|
|
commands.onoff_clicked()
|
|
elif pin == 'run' and isIdleHomed:
|
|
commands.task_run()
|
|
elif pin == 'pause':
|
|
if isRunning:
|
|
commands.task_pause()
|
|
elif isPaused:
|
|
commands.task_resume()
|
|
elif pin == 'run-pause':
|
|
if isIdleHomed:
|
|
commands.task_run()
|
|
elif isRunning:
|
|
commands.task_pause()
|
|
elif isPaused:
|
|
commands.task_resume()
|
|
elif pin == 'touchoff':
|
|
touch_off_xy('1', '0', '0')
|
|
elif pin == 'probe' and probeButton:
|
|
user_button_pressed(probeButton, buttonCodes[int(probeButton)])
|
|
elif pin == 'pulse' and torchButton:
|
|
user_button_pressed(torchButton, buttonCodes[int(torchButton)])
|
|
# released commands
|
|
else:
|
|
if pin == 'touchoff':
|
|
touch_off_xy('0', '0', '0')
|
|
elif pin == 'probe' and probeButton:
|
|
user_button_released(probeButton, buttonCodes[int(probeButton)])
|
|
elif pin == 'pulse' and torchButton:
|
|
user_button_released(torchButton, buttonCodes[int(torchButton)])
|
|
elif pin == 'frame-job':
|
|
num = get_button_num('framing')
|
|
if num:
|
|
user_button_released(str(num), buttonCodes[num])
|
|
|
|
def get_button_num(name):
|
|
num = None
|
|
for num in buttonCodes:
|
|
if buttonCodes[num]['code'] == name:
|
|
break
|
|
return num
|
|
|
|
|
|
##############################################################################
|
|
# HELP TEXT #
|
|
##############################################################################
|
|
def help_text():
|
|
global kb_text_1, kb_text_2, kp_text_1
|
|
kb_text_1 = [
|
|
('ESC', _('Abort')),
|
|
('', ''),
|
|
('F1', _('Emergency stop')),
|
|
('F2', _('Machine on/off')),
|
|
('F3', _('Manual tab')),
|
|
('F4', _('Cycle through right side tabs')),
|
|
('F5', _('MDI tab')),
|
|
('F9', _('Manual cut start/stop')),
|
|
('', ''),
|
|
('X', _('Activate first axis')),
|
|
('Y', _('Activate second axis')),
|
|
('Z', _('Activate third axis')),
|
|
('A', _('Activate fourth axis')),
|
|
('B', _('Activate fifth axis')),
|
|
('', ''),
|
|
('C', _('Select continuous jog')),
|
|
(_('I or Shift-I'), _('Select jog increment')),
|
|
(_('Left or Right'), _('Jog first axis or joint')),
|
|
(_('Up or Down'), _('Jog second axis or joint')),
|
|
(_('PgUp or PgDn'), _('Jog third axis or joint')),
|
|
('[ or ]', _('Jog fourth axis or joint')),
|
|
('; or \'', _('Jog fifth axis or joint')),
|
|
(_('Shift+ above jog'), _('Jog at traverse speed')),
|
|
]
|
|
kb_text_2 = [
|
|
(_('Ctrl-Home'), _('Emulate GUI home button')),
|
|
(_('Shift-Home'), _('Home active joint')),
|
|
(_('End'), _('Touchoff X and Y to zero')),
|
|
(_('Ctrl-End'), _('Touchoff active axis to zero')),
|
|
(_('Shift-End'), _('Set touchoff for current axis')),
|
|
(_('Del'), _('Emulate GUI laser button')),
|
|
('', ''),
|
|
('O', _('Open program')),
|
|
('R', _('Run program')),
|
|
('T', _('Step program')),
|
|
('P or Space', _('Pause program')),
|
|
('S', _('Resume program')),
|
|
(_('Ctrl-R'), _('Reload program')),
|
|
(_('Ctrl-S'), _('Save G-code as')),
|
|
('', ''),
|
|
(_('Ctrl-K'), _('Clear live plot')),
|
|
(_('Ctrl-Space'), _('Clear notifications')),
|
|
('', ''),
|
|
('World Mode:', ''),
|
|
('` or 1~0', _('Feed override from 0% to 100%')),
|
|
('Ctrl+ ` or 1~0', _('Rapid Override from 0% to 100%')),
|
|
('Alt+ ` or 1~0', _('Jog speed from 0% to 100%')),
|
|
('Joint Mode:', ''),
|
|
('` or 0~8', _('Activate joints 1 thru 9')),
|
|
]
|
|
kp_text_1 = [
|
|
(_('Left'), _('Jog first axis or joint negative')),
|
|
(_('Right'), _('Jog first axis or joint positive')),
|
|
(_('Up'), _('Jog second axis or joint positive')),
|
|
(_('Down'), _('Jog second axis or joint negative')),
|
|
(_('PgUp'), _('Jog third axis or joint positive')),
|
|
(_('PgDn'), _('Jog third axis or joint negative')),
|
|
('', ''),
|
|
(_('Minus+ above jog'), _('Jog speed x 0.1')),
|
|
(_('Plus+ above jog'), _('Jog speed x 10')),
|
|
('', ''),
|
|
(_('Home'), _('Emulate GUI home button')),
|
|
(_('End'), _('Touchoff X and Y to zero')),
|
|
(_('Del'), _('Emulate GUI laser button')),
|
|
]
|
|
|
|
def install_kb_text(app):
|
|
keys = nf.makewidget(app, Frame, '.keys.text')
|
|
fixed = app.tk.call("linuxcnc::standard_fixed_font")
|
|
for i in range(len(kb_text_1)):
|
|
a, b = kb_text_1[i]
|
|
Label(keys, text=a, font=fixed, padx=4, pady=0, highlightthickness=0).grid(row=i, column=0, sticky="w")
|
|
Label(keys, text=b, padx=4, pady=0, highlightthickness=0).grid(row=i, column=1, sticky="w")
|
|
for i in range(len(kb_text_2)):
|
|
a, b = kb_text_2[i]
|
|
Label(keys, text=a, font=fixed, padx=4, pady=0, highlightthickness=0).grid(row=i, column=3, sticky="w")
|
|
Label(keys, text=b, padx=4, pady=0, highlightthickness=0).grid(row=i, column=4, sticky="w")
|
|
Label(keys, text=" ").grid(row=0, column=2)
|
|
|
|
def install_kp_text(app):
|
|
keyp = nf.makewidget(app, Frame, '.keyp.text')
|
|
fixed = app.tk.call("linuxcnc::standard_fixed_font")
|
|
for i in range(len(kp_text_1)):
|
|
a, b = kp_text_1[i]
|
|
Label(keyp, text=a, font=fixed, padx=4, pady=0, highlightthickness=0).grid(row=i, column=0, sticky="w")
|
|
Label(keyp, text=b, padx=4, pady=0, highlightthickness=0).grid(row=i, column=1, sticky="w")
|
|
|
|
|
|
##############################################################################
|
|
# KEYBOARD BINDINGS #
|
|
##############################################################################
|
|
def key_pressed(key):
|
|
global keyDelay
|
|
if key not in keyDelay:
|
|
keyDelay[key] = None
|
|
if keyDelay[key]:
|
|
root_window.after_cancel(keyDelay[key])
|
|
keyDelay[key] = None
|
|
return
|
|
if key == 'Delete':
|
|
laser_button_toggled('1', 1)
|
|
if key == 'End':
|
|
touch_off_xy('1', 0, 0)
|
|
if key == 'Home':
|
|
if homing_order_defined:
|
|
commands.home_all_joints()
|
|
else:
|
|
commands.home_joint()
|
|
elif key == 'jogfast':
|
|
pVars.jogMultiplier.set(10)
|
|
elif key == 'jogslow':
|
|
pVars.jogMultiplier.set(0.1)
|
|
|
|
def key_off(key):
|
|
global keyDelay
|
|
keyDelay[key] = None
|
|
if key == 'Delete':
|
|
laser_button_toggled('0', 1)
|
|
if key == 'End':
|
|
touch_off_xy('0', 0, 0)
|
|
elif key in ['jogfast', 'jogslow']:
|
|
pVars.jogMultiplier.set(1)
|
|
|
|
def key_released(key):
|
|
global keyDelay
|
|
if key not in keyDelay:
|
|
keyDelay[key] = None
|
|
if keyDelay[key]:
|
|
return
|
|
keyDelay[key] = root_window.after_idle(lambda: key_off(key))
|
|
|
|
def kb_shortcuts_changed():
|
|
keyboard_bindings(pVars.kbShortcuts.get())
|
|
|
|
def virtual_kb_changed():
|
|
if pVars.useVirtKB.get():
|
|
if not WHICH('onboard'):
|
|
rE(f"{fsetup}.l.gui.useVirtKB deselect")
|
|
msg0 = _('a valid "onboard" virtual keyboard is not installed')
|
|
notifications.add('error', f"{msg0}\n")
|
|
return
|
|
pVars.kbShortcuts.set(0)
|
|
rE(f"{fsetup}.l.gui.kbShortcutsL configure -state disabled")
|
|
rE(f"{fsetup}.l.gui.kbShortcuts configure -state disabled")
|
|
if rE('winfo ismapped .fconv'):
|
|
vkb_show('numpad')
|
|
elif rE(f"winfo ismapped {fparam}"):
|
|
vkb_show('numpad')
|
|
elif rE(f"winfo ismapped {fsetup}"):
|
|
vkb_show('keyboard')
|
|
else:
|
|
rE(f"{fsetup}.l.gui.kbShortcutsL configure -state normal")
|
|
rE(f"{fsetup}.l.gui.kbShortcuts configure -state normal")
|
|
vkb_hide()
|
|
|
|
def make_lambda(func, value, state=None):
|
|
if state is not None:
|
|
return lambda event:func(value, state)
|
|
else:
|
|
return lambda event:func(value)
|
|
|
|
def keyboard_bindings(state):
|
|
if firstRun:
|
|
help_text()
|
|
# delete kb shortcuts from help menu
|
|
rE('.menu.help delete 3 5')
|
|
# remove current bindings
|
|
for key in root_window.bind():
|
|
root_window.unbind(key)
|
|
# create new key bindings if enabled
|
|
if state:
|
|
# Escape
|
|
root_window.bind('<Escape>', commands.task_stop)
|
|
# F keys
|
|
root_window.bind_class('all', '<Key-F1>', commands.estop_clicked)
|
|
root_window.bind('<Key-F2>', commands.onoff_clicked)
|
|
root_window.bind('<Key-F3>', f"{pane_top}.tabs raise manual")
|
|
root_window.bind('<Key-F4>', commands.next_tab)
|
|
root_window.bind('<Key-F5>', f"{pane_top}.tabs raise mdi")
|
|
#FIXME - ???
|
|
# root_window.bind('<Key-F5>', f"+{tabs_mdi}.command selection range 0 end")
|
|
root_window.bind('<Key-F9>', commands.manual_cut)
|
|
# axis selection
|
|
root_window.bind('x', lambda event: activate_ja_widget('x'))
|
|
root_window.bind('y', lambda event: activate_ja_widget('y'))
|
|
root_window.bind('z', lambda event: activate_ja_widget('z'))
|
|
root_window.bind('a', lambda event: activate_ja_widget('a'))
|
|
root_window.bind('b', lambda event: activate_ja_widget('b'))
|
|
#jogging
|
|
root_window.bind('c', lambda event: jogspeed_continuous())
|
|
root_window.bind('i', lambda event: jogspeed_incremental())
|
|
root_window.bind('I', lambda event: jogspeed_incremental(-1))
|
|
bind_axis('Left', 'Right', 0)
|
|
bind_axis('Down', 'Up', 1)
|
|
bind_axis('Next', 'Prior', 2)
|
|
bind_axis('KP_Left', 'KP_Right', 0)
|
|
bind_axis('KP_Down', 'KP_Up', 1)
|
|
bind_axis('KP_Next', 'KP_Prior', 2)
|
|
# bind_axis('KP_4', 'KP_6', 0)
|
|
# bind_axis('KP_2', 'KP_8', 1)
|
|
# bind_axis('KP_3', 'KP_9', 2)
|
|
bind_axis('bracketleft', 'bracketright', 3)
|
|
bind_axis('semicolon', 'quoteright', 4)
|
|
root_window.bind('<Key-KP_Add>', lambda event: commands.key_pressed('jogfast'))
|
|
root_window.bind('<KeyRelease-KP_Add>', lambda event: commands.key_released('jogfast'))
|
|
root_window.bind('<Key-KP_Subtract>', lambda event: commands.key_pressed('jogslow'))
|
|
root_window.bind('<KeyRelease-KP_Subtract>', lambda event: commands.key_released('jogslow'))
|
|
# sliders
|
|
root_window.bind('`', lambda event: activate_ja_widget_or_set_feedrate(0))
|
|
root_window.bind('<Control-Key-quoteleft>',lambda event: set_rapidrate(0))
|
|
root_window.bind('<Alt-Key-quoteleft>',lambda event: set_jog_slider(0.0))
|
|
for n in range(10):
|
|
rate = n if n > 0 else 10
|
|
root_window.bind(f"{n}", make_lambda(activate_ja_widget_or_set_feedrate, rate))
|
|
root_window.bind(f"<Control-Key-{n}>", make_lambda(set_rapidrate, rate * 10))
|
|
root_window.bind(f"<Alt-Key-{n}>", make_lambda(set_jog_slider, rate * 0.1))
|
|
# homing
|
|
if homing_order_defined:
|
|
root_window.bind('<Control-Home>', commands.home_all_joints)
|
|
else:
|
|
root_window.bind('<Control-Home>', commands.home_joint)
|
|
root_window.bind('<Shift-Home>', commands.home_joint)
|
|
# touchoff
|
|
root_window.bind('<Key-End>', lambda event: commands.touch_off_xy('1', 0, 0))
|
|
root_window.bind('<KeyRelease-End>', lambda event: commands.touch_off_xy('0', 0, 0))
|
|
root_window.bind('<Control-End>', commands.set_axis_offset)
|
|
root_window.bind('<Shift-End>', commands.touch_off_system)
|
|
root_window.bind('<Key-Delete>', lambda event: commands.key_pressed('Delete'))
|
|
root_window.bind('<KeyRelease-Delete>', lambda event: commands.key_released('Delete'))
|
|
# program
|
|
root_window.bind('o', commands.open_file)
|
|
root_window.bind('r', commands.task_run)
|
|
root_window.bind('p', commands.task_pause)
|
|
root_window.bind('<space>', commands.task_pause)
|
|
root_window.bind('s', commands.task_resume)
|
|
root_window.bind('<Control-r>', commands.reload_file)
|
|
root_window.bind('<Control-s>', commands.save_gcode)
|
|
# clearing
|
|
root_window.bind('<Control-k>', commands.clear_live_plot)
|
|
root_window.bind('<Control-space>', lambda event: notifications.clear())
|
|
# whacky keypad stuff
|
|
keys1 = ['Decimal', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
|
|
# Down, Next, Left, Right, Up, and Prior are done in the jogging section above
|
|
keys2 = ['Delete', 'Insert', 'End', None, None, None, 'Begin', None, 'Home', None, None]
|
|
for k in range(len(keys2)):
|
|
if keys2[k]:
|
|
root_window.bind(f"<Key-KP_{keys2[k]}>", make_lambda(key_pressed, keys2[k]))
|
|
root_window.bind(f"<KeyRelease-KP_{keys2[k]}>", make_lambda(key_released, keys2[k]))
|
|
root_window.bind(f"<Mod2-KeyRelease-KP_{keys2[k]}>", make_lambda(key_released, keys1[k]))
|
|
# add kb shortcuts to help menu
|
|
rE('.menu.help add separator')
|
|
rE('.menu.help add command -command {wm transient .keys .;wm deiconify .keys; focus .keys.ok}')
|
|
rE(f"setup_menu_accel .menu.help end {{{_('Keyboard Shortcuts')}}}")
|
|
rE('.menu.help add command -command {wm transient .keyp .;wm deiconify .keyp; focus .keyp.ok}')
|
|
rE(f"setup_menu_accel .menu.help end {{{_('Keypad Shortcuts')}}}")
|
|
# use arrow keys for spinboxes
|
|
for item in rpList + cpList:
|
|
widget = f"{item[0]}.{item[1]}"
|
|
rE(f"bind {widget} <Up> {{%W invoke buttonup}}")
|
|
rE(f"bind {widget} <Down> {{%W invoke buttondown}}")
|
|
rE(f"bind {widget} <Left> {{::tk::EntrySetCursor %W [expr [%W index insert] - 1]}}")
|
|
rE(f"bind {widget} <Right> {{::tk::EntrySetCursor %W [expr [%W index insert] + 1]}}")
|
|
|
|
|
|
##############################################################################
|
|
# ONBOARD VIRTUAL KEYBOARD #
|
|
##############################################################################
|
|
def vkb_validate():
|
|
global vkbData
|
|
vkbData = {'valid':False, 'visible':False, 'required':False, 'layout':None, 'width':0, 'height':0}
|
|
if WHICH('onboard'):
|
|
try:
|
|
cmd = 'gsettings get org.onboard layout'
|
|
vkbData['layout'] = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate()[0].decode().strip()
|
|
cmd = 'gsettings get org.onboard.window.landscape width'
|
|
vkbData['width'] = int(Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate()[0].decode().strip())
|
|
cmd = 'gsettings get org.onboard.window.landscape height'
|
|
vkbData['height'] = int(Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True).communicate()[0].decode().strip())
|
|
vkbData['valid'] = True
|
|
except:
|
|
pass
|
|
|
|
def vkb_show(layout):
|
|
global vkbData
|
|
if firstRun: return
|
|
if not pVars.useVirtKB.get(): return
|
|
w = 240 if layout == 'numpad' else 740
|
|
vkbData['visible'] = True
|
|
vkb_settings(os.path.join(libPath, layout), w, 240)
|
|
time.sleep(0.1)
|
|
cmd = 'dbus-send'
|
|
cmd += ' --type=method_call'
|
|
cmd += ' --dest=org.onboard.Onboard'
|
|
cmd += ' /org/onboard/Onboard/Keyboard'
|
|
cmd += ' org.onboard.Onboard.Keyboard.Show'
|
|
Popen(cmd, stdout=PIPE, shell=True)
|
|
|
|
def vkb_hide(custom=False):
|
|
vkbData['visible'] = False
|
|
cmd = 'dbus-send'
|
|
cmd += ' --type=method_call'
|
|
cmd += ' --dest=org.onboard.Onboard'
|
|
cmd += ' /org/onboard/Onboard/Keyboard'
|
|
cmd += ' org.onboard.Onboard.Keyboard.Hide'
|
|
Popen(cmd, stdout=PIPE, shell=True)
|
|
vkb_settings(vkbData['layout'], vkbData['width'], vkbData['height'])
|
|
|
|
def vkb_settings(layout, width, height):
|
|
Popen(f"gsettings set org.onboard layout {layout}", stdout=PIPE, shell=True)
|
|
Popen(f"gsettings set org.onboard.window.landscape width {width - 1}", stdout=PIPE, shell=True)
|
|
Popen(f"gsettings set org.onboard.window.landscape height {height - 1}", stdout=PIPE, shell=True)
|
|
time.sleep(0.1)
|
|
Popen(f"gsettings set org.onboard.window.landscape width {width}", stdout=PIPE, shell=True)
|
|
Popen(f"gsettings set org.onboard.window.landscape height {height}", stdout=PIPE, shell=True)
|
|
|
|
##############################################################################
|
|
# COLOR CHANGE #
|
|
##############################################################################
|
|
def read_colors():
|
|
global colorFore, colorBack, colorDisable, colorActive, colorWarn
|
|
global colorVolt, colorArc, colorLed, colorTrough
|
|
colorFore = getPrefs(PREF, 'GUI_OPTIONS','Foreground color', '#000000', str)
|
|
colorBack = getPrefs(PREF, 'GUI_OPTIONS','Background color', '#808080', str)
|
|
colorDisable = getPrefs(PREF, 'GUI_OPTIONS','Disabled color', '#a0a0a0', str)
|
|
colorActive = getPrefs(PREF, 'GUI_OPTIONS','Active color', '#00cc00', str)
|
|
colorWarn = getPrefs(PREF, 'GUI_OPTIONS','Warning color', '#dd0000', str)
|
|
colorVolt = getPrefs(PREF, 'GUI_OPTIONS','Voltage color', '#ff8800', str)
|
|
colorArc = getPrefs(PREF, 'GUI_OPTIONS','Arc OK color', '#ff8800', str)
|
|
colorLed = getPrefs(PREF, 'GUI_OPTIONS','LED color', '#eeff00', str)
|
|
colorTrough = getPrefs(PREF, 'GUI_OPTIONS','Trough color', '#505050', str)
|
|
|
|
def color_user_buttons(fgc='#000000',bgc='#d9d9d9'):
|
|
for b in criticalButtons:
|
|
rE(f"{fbuttons}.button{b} configure -bg {colorWarn}")
|
|
# user button entries in setup frame
|
|
for n in range(1, maxUserButtons + 1):
|
|
if n in invalidButtons:
|
|
rE(f"{fsetup}.r.ubuttons.canvas.frame.name{n} configure -fg {colorWarn}")
|
|
rE(f"{fsetup}.r.ubuttons.canvas.frame.code{n} configure -fg {colorWarn}")
|
|
else:
|
|
rE(f"{fsetup}.r.ubuttons.canvas.frame.name{n} configure -fg {colorFore}")
|
|
rE(f"{fsetup}.r.ubuttons.canvas.frame.code{n} configure -fg {colorFore}")
|
|
|
|
def color_torch():
|
|
if hal.get_value('plasmac.torch-enable'):
|
|
txt = torchEnable['enabled'].replace('\\','\n')
|
|
rE(f"{fbuttons}.torch-enable configure -fg {colorFore} -bg {colorActive} \
|
|
-activebackground {colorActive} -text {{{txt}}}")
|
|
else:
|
|
txt = torchEnable['disabled'].replace('\\','\n')
|
|
rE(f"{fbuttons}.torch-enable configure -fg {colorFore} -bg {colorWarn} \
|
|
-activebackground {colorWarn} -text {{{txt}}}")
|
|
|
|
def get_all_children(parent):
|
|
raw = rE(f"winfo children {parent}")
|
|
children = raw.split()
|
|
for item in children:
|
|
if rE(f"winfo children {item}"):
|
|
raw = (rE(f"winfo children {item}"))
|
|
for item in raw.split():
|
|
children.append(item)
|
|
return(children)
|
|
|
|
def color_change():
|
|
# menu colors
|
|
rE(f"option add *Menu.Background {colorBack}")
|
|
rE(f"option add *Menu.Foreground {colorFore}")
|
|
widgetTypes = []
|
|
for child in get_all_children('.'):
|
|
if child in [f"{fbuttons}.torch-enable"]:
|
|
continue
|
|
w = rE(f"winfo class {child}")
|
|
# root window
|
|
rE(f". configure -bg {colorBack}")
|
|
# all widgets
|
|
try:
|
|
rE(f"{child} configure -fg {colorFore}")
|
|
except:
|
|
pass
|
|
try:
|
|
rE(f"{child} configure -bg {colorBack}")
|
|
except:
|
|
pass
|
|
try:
|
|
rE(f"{child} configure -disabledforeground {colorDisable}")
|
|
except:
|
|
pass
|
|
try:
|
|
rE(f"{child} configure -activebackground {colorBack}")
|
|
except:
|
|
pass
|
|
try:
|
|
rE(f"{child} configure -buttonbackground {colorBack}")
|
|
except:
|
|
pass
|
|
try:
|
|
rE(f"{child} configure -highlightthickness 0")
|
|
except:
|
|
pass
|
|
try:
|
|
rE(f"{child} configure -highlightbackground {colorBack}")
|
|
except:
|
|
pass
|
|
try:
|
|
if w == 'Menu':
|
|
rE(f"{child} configure -selectcolor {colorFore}")
|
|
else:
|
|
rE(f"{child} configure -selectcolor {colorActive}")
|
|
except:
|
|
pass
|
|
try:
|
|
# color the trough of override scales and user button scrollbars
|
|
rE(f"{child} configure -troughcolor {colorTrough}")
|
|
# color the trough of combobox lists
|
|
rE(f"option add *Scrollbar.troughColor {colorTrough}")
|
|
rE(f"option add *Scrollbar.background {colorBack}")
|
|
rE(f"option add *Scrollbar.activeBackground {colorBack}")
|
|
except:
|
|
pass
|
|
# all comboboxes except for the jog increment Combobox
|
|
if w == 'ComboBox':
|
|
rE(f"{child} configure -background {colorBack}")
|
|
rE(f"{child} configure -selectbackground {colorBack}")
|
|
rE(f"{child} configure -selectforeground {colorFore}")
|
|
# lose the arrow
|
|
rE(f"pack forget {child}.a")
|
|
# the entry of the jog increment combobox
|
|
elif '.jogincr' in child and w == 'Entry':
|
|
rE(f"{child} configure -disabledforeground {colorFore}")
|
|
# the listbox of the jog increment combobox
|
|
elif '.jogincr' in child and w == 'Listbox':
|
|
rE(f"{child} configure -selectforeground {colorFore}")
|
|
rE(f"{child} configure -selectbackground {colorBack}")
|
|
# all checkbuttons
|
|
elif w in ['Checkbutton']:
|
|
rE(f"{child} configure -relief raised -overrelief raised -bd 1")
|
|
# notebook tabs - cutrecs is also done each time it is raised
|
|
for nbook in [ftabs, fright]:
|
|
pages = rE(f"{nbook} pages").split()
|
|
for page in pages:
|
|
rE(f"{nbook} itemconfigure {page} -foreground {colorFore} -background {colorBack}")
|
|
# leds
|
|
for led in ['arc-ok','torch','breakaway','thc-enabled','thc-active','ohmic','float','up','down','corner-locked','void-locked']:
|
|
rE(f"{fleds}.led-{led} itemconfigure all -disabledfill {colorBack}")
|
|
for led in ['breakaway','void-locked','corner-locked']:
|
|
rE(f"{fleds}.led-{led} itemconfigure all -fill {colorWarn}")
|
|
for led in ['thc-enabled','thc-active']:
|
|
rE(f"{fleds}.led-{led} itemconfigure all -fill {colorActive}")
|
|
for led in ['ohmic','float','up','down']:
|
|
rE(f"{fleds}.led-{led} itemconfigure all -fill {colorLed}")
|
|
rE(f"{fleds}.led-arc-ok itemconfigure all -fill {colorArc}")
|
|
rE(f"{fleds}.led-torch itemconfigure all -fill {colorLed}")
|
|
# arc voltage
|
|
rE(f"{fplasma}.arc-voltage configure -fg {colorVolt}")
|
|
color_user_buttons()
|
|
color_torch()
|
|
# the color setup buttons
|
|
rE(f"{fsetup}.m.colors.fore configure -bg {colorFore} -activebackground {colorFore}")
|
|
rE(f"{fsetup}.m.colors.back configure -bg {colorBack} -activebackground {colorBack}")
|
|
rE(f"{fsetup}.m.colors.disable configure -bg {colorDisable} -activebackground {colorDisable}")
|
|
rE(f"{fsetup}.m.colors.active configure -bg {colorActive} -activebackground {colorActive}")
|
|
rE(f"{fsetup}.m.colors.warn configure -bg {colorWarn} -activebackground {colorWarn}")
|
|
rE(f"{fsetup}.m.colors.volt configure -bg {colorVolt} -activebackground {colorVolt}")
|
|
rE(f"{fsetup}.m.colors.arc configure -bg {colorArc} -activebackground {colorArc}")
|
|
rE(f"{fsetup}.m.colors.led configure -bg {colorLed} -activebackground {colorLed}")
|
|
rE(f"{fsetup}.m.colors.trough configure -bg {colorTrough} -activebackground {colorTrough}")
|
|
# notifications
|
|
rE(f"option add *!notification2.Frame.Background {colorBack}")
|
|
rE(f"option add *!notification2.Frame.Label.Foreground {colorFore}")
|
|
rE(f"option add *!notification2.Frame.Label.Background {colorBack}")
|
|
rE(f"option add *!notification2.Frame.Button.Background {colorBack}")
|
|
rE(f"option add *!notification2.Frame.Button.activeBackground {colorBack}")
|
|
rE(f"option add *!notification2.Frame.Button.highlightThickness 0")
|
|
# tags in gcode text
|
|
t.tag_configure('ignored', background='#ffffff', foreground='#808080')
|
|
t.tag_configure('lineno', foreground=colorTrough)
|
|
t.tag_configure('executing', background=colorTrough)
|
|
t.tag_configure('sel', background='red', foreground='blue')
|
|
|
|
def color_set(option):
|
|
global colorFore, colorBack, colorDisable, colorActive, colorWarn, colorVolt, colorArc, colorLed, colorTrough
|
|
if option == 'fore':
|
|
color = colorFore
|
|
elif option == 'back':
|
|
color = colorBack
|
|
elif option == 'disable':
|
|
color = colorDisable
|
|
elif option == 'active':
|
|
color = colorActive
|
|
elif option == 'warn':
|
|
color = colorWarn
|
|
elif option == 'volt':
|
|
color = colorVolt
|
|
elif option == 'arc':
|
|
color = colorArc
|
|
elif option == 'led':
|
|
color = colorLed
|
|
elif option == 'trough':
|
|
color = colorTrough
|
|
else:
|
|
color = '#000000'
|
|
colors = askcolor(color, title=_('plasmac2 Color Selector'))
|
|
if colors[1]:
|
|
if option == 'fore':
|
|
colorFore = colors[1]
|
|
elif option == 'back':
|
|
colorBack = colors[1]
|
|
elif option == 'disable':
|
|
colorDisable = colors[1]
|
|
elif option == 'active':
|
|
colorActive = colors[1]
|
|
elif option == 'warn':
|
|
colorWarn = colors[1]
|
|
elif option == 'volt':
|
|
colorVolt = colors[1]
|
|
elif option == 'arc':
|
|
colorArc = colors[1]
|
|
elif option == 'led':
|
|
colorLed = colors[1]
|
|
elif option == 'trough':
|
|
colorTrough = colors[1]
|
|
color_change()
|
|
|
|
##############################################################################
|
|
# ORIENTATION FUNCTIONS #
|
|
##############################################################################
|
|
def set_orientation():
|
|
global orientStart
|
|
orientStart = True
|
|
matNum = int(rE(f"{fruns}.material.materials get").split(': ', 1)[0])
|
|
pmxText = rE(f"{fruns}.pmx.info cget -text")
|
|
set_orient_frames()
|
|
recreate_widget_list()
|
|
user_button_setup()
|
|
populate_settings_frame()
|
|
for box in rSpinBoxes:
|
|
rE(f"{box} configure -font fontGui")
|
|
color_change()
|
|
set_window_size()
|
|
load_materials(get_displayed_material(), keepTemp=True)
|
|
index = f"@{materialNumList.index(matNum)}"
|
|
rE(f"{fruns}.material.materials setvalue {index}")
|
|
display_selected_material(matNum)
|
|
rE(f"{fruns}.pmx.info configure -text {{{pmxText}}}")
|
|
orientStart = False
|
|
|
|
def set_orient_frames():
|
|
global fportrait, fruns, fbuttons, toolmat
|
|
if not firstRun:
|
|
rE(f"destroy {toolmat}")
|
|
rE(f"destroy {fruns}")
|
|
rE(f"destroy {fbuttons}")
|
|
rE(f"destroy {fportrait}")
|
|
rE(f"destroy {fruns}.material.materials")
|
|
fportrait = '.fportrait'
|
|
if pVars.orient.get() == 'portrait':
|
|
fruns = '.fportrait.fruns'
|
|
fbuttons = '.fportrait.fbuttons'
|
|
toolmat = f"{fruns}.toolmat"
|
|
rE(f"frame {fportrait} -relief raised -borderwidth 2")
|
|
else:
|
|
fruns = '.fruns'
|
|
fbuttons = '.fbuttons'
|
|
toolmat = '.toolmat'
|
|
rE(f"frame {fbuttons} -relief flat")
|
|
rE(f"frame {fruns} -relief flat")
|
|
make_torch_button()
|
|
make_dry_run_button()
|
|
make_toolmat_frame()
|
|
make_run_panel()
|
|
|
|
def make_torch_button():
|
|
rE(f"button {fbuttons}.torch-enable -takefocus 0 -width 10 -highlightthickness 0")
|
|
if '\\' in torchEnable['enabled'] or '\\' in torchEnable['disabled']:
|
|
rE(f"{fbuttons}.torch-enable configure -height 2")
|
|
else:
|
|
rE(f"{fbuttons}.torch-enable configure -height 1")
|
|
rE(f"grid {fbuttons}.torch-enable -column 0 -row 0 -sticky new -padx {{2 0}} -pady {{2 0}}")
|
|
rE(f"bind {fbuttons}.torch-enable <ButtonPress-1> torch_enable")
|
|
|
|
def make_dry_run_button():
|
|
if pVars.orient.get() == 'portrait':
|
|
col = 1
|
|
row = 0
|
|
else:
|
|
col = 0
|
|
row = 1
|
|
rE(f"button {fbuttons}.dry-run -takefocus 0 -width 10 -highlightthickness 0 -text {{Dry Run}} -command {{task_run dry-run}}")
|
|
rE(f"grid {fbuttons}.dry-run -column {col} -row {row} -sticky new -padx {{2 0}} -pady {{2 0}}")
|
|
|
|
def make_toolmat_frame():
|
|
rE(f"frame {toolmat} -borderwidth 1 -relief raised")
|
|
rE(f"Button {toolmat}.delete -command {{delete_material_clicked}} -relief link -takefocus 0")
|
|
rE(f"Button {toolmat}.new -command {{new_material_clicked}} -relief link -takefocus 0")
|
|
rE(f"Button {toolmat}.reload -command {{reload_material_clicked}} -relief link -takefocus 0")
|
|
rE(f"Button {toolmat}.save -command {{save_material_clicked}} -relief link -takefocus 0")
|
|
rE(f"{toolmat}.delete configure -image {rE(f'load_image {imageAxis}/tool_zoomout')}")
|
|
rE(f"{toolmat}.new configure -image {rE(f'load_image {imageAxis}/tool_zoomin')}")
|
|
rE(f"{toolmat}.reload configure -image {rE(f'load_image {imageAxis}/tool_reload')}")
|
|
rE(f"{toolmat}.save configure -image {rE(f'load_image {imagePath}/save')}")
|
|
rE(f"pack {toolmat}.save -side left -padx {{0 4}}")
|
|
rE(f"pack {toolmat}.reload -side left")
|
|
rE(f"pack {toolmat}.delete -side right -padx {{4 0}}")
|
|
rE(f"pack {toolmat}.new -side right")
|
|
|
|
def make_run_panel():
|
|
global rpList, rSpinBoxes
|
|
rSpinBoxes = []
|
|
rE(f"labelframe {fruns}.material -text {{{_('Material')}}} -relief groove")
|
|
rE(f"ComboBox {fruns}.material.materials -modifycmd {{material_changed}} -textvariable matCurrent -width 10 -editable 0")
|
|
rE(f"grid {fruns}.material.materials -column 0 -row 0 -columnspan 2 -sticky ew -padx 2 -pady 2")
|
|
# spinboxes [parent, name, decimals, value, min, max, increment, label text]
|
|
rpList = [[f"{fruns}.material",'kerf-width',2,0.5,0,5,0.01,'Kerf Width'], \
|
|
[f"{fruns}.material",'pierce-height',2,4,0,25,0.01,'Pierce Height'], \
|
|
[f"{fruns}.material",'pierce-delay',1,0.0,0,10,0.1,'Pierce Delay'], \
|
|
[f"{fruns}.material",'cut-height',2,1,0,25,0.01,'Cut Height'], \
|
|
[f"{fruns}.material",'cut-feed-rate',0,4000,0,19999,1,'Feed Rate'], \
|
|
[f"{fruns}.material",'cut-amps',0,45,0,999,1,'Cut Amps'], \
|
|
[f"{fruns}.material",'cut-volts',0,122,50,300,1,'Cut Volts'], \
|
|
[f"{fruns}.material",'puddle-jump-height',0,0,0,200,1,'P-Jump Height'], \
|
|
[f"{fruns}.material",'puddle-jump-delay',2,0,0,9,0.01,'P-Jump Delay'], \
|
|
[f"{fruns}.material",'pause-at-end',1,0,0,9,0.1,'Pause At End'], \
|
|
[f"{fruns}.material",'cut-mode',0,1,1,3,1,'Cut Mode'], \
|
|
[f"{fruns}.material",'gas-pressure',1,0,0,150,0.1,'Gas Pressure'], \
|
|
]
|
|
rpRow = 1
|
|
for rpItem in rpList:
|
|
if s.linear_units != 1:
|
|
if rpItem[1] == 'kerf-width':
|
|
rpItem[2:7] = [4,0.02,0,1,0.0001]
|
|
elif rpItem[1] == 'pierce-height':
|
|
rpItem[2:7] = [3,0.16,0,1,0.001]
|
|
elif rpItem[1] == 'cut-height':
|
|
rpItem[2:7] = [3,0.04,0,1,0.001]
|
|
elif rpItem[1] == 'cut-feed-rate':
|
|
rpItem[2:7] = [0,160,0,999,0.1]
|
|
rpName = f"{rpItem[0]}.{rpItem[1]}"
|
|
rpType = 'flt' if rpItem[2] > 0 else 'int'
|
|
rE(f"spinbox {rpName} -width 9 -justify right -wrap true")
|
|
rSpinBoxes.append(rpName)
|
|
rE(f"{rpName} configure -from {rpItem[4]} -to {rpItem[5]}")
|
|
if rpItem[1] == 'kerf-width':
|
|
rE(f"{rpName} configure -textvariable kerfWidth")
|
|
elif rpItem[1] == 'cut-amps':
|
|
rE(f"{rpName} configure -textvariable cutAmps")
|
|
elif rpItem[1] == 'cut-mode':
|
|
rE(f"{rpName} configure -textvariable cutMode")
|
|
elif rpItem[1] == 'gas-pressure':
|
|
rE(f"{rpName} configure -textvariable gasPressure")
|
|
rE(f"{rpName} configure -increment {rpItem[6]} -format %0.{rpItem[2]}f")
|
|
rE(f"{rpName} configure -validate key -vcmd {{{valspin} %W {rpType} {rpItem[2]} %P %s}}")
|
|
rE(f"label {rpName}L -text {{{rpItem[7]}}}")
|
|
if rpItem[1] not in ['cut-mode', 'gas-pressure']:
|
|
rE(f"grid {rpName} -column 0 -row {rpRow} -padx {{2 0}} -pady {{0 2}}")
|
|
rE(f"grid {rpName}L -column 1 -row {rpRow} -sticky W -pady {{0 2}}")
|
|
rpRow += 1
|
|
# checkbox frame
|
|
rE(f"labelframe {fruns}.check -text {{{_('Cut')}}} -relief groove")
|
|
rE(f"checkbutton {fruns}.check.av -variable autoVolts -command auto_volts_toggled -width 2 -anchor w -indicatoron 0")
|
|
rE(f"label {fruns}.check.avL -text {{{_('Use Auto Volts')}}}")
|
|
rE(f"checkbutton {fruns}.check.ohmic -variable ohmicEnable -command ohmic_enable_toggled -width 2 -anchor w -indicatoron 0")
|
|
rE(f"label {fruns}.check.ohmicL -text {{{_('Ohmic Probe Enable')}}}")
|
|
rE(f"checkbutton {fruns}.check.mesh -variable meshEnable -command pmx485_mesh_enable_toggled -width 2 -anchor w -indicatoron 0")
|
|
rE(f"label {fruns}.check.meshL -text {{{_('Mesh Mode')}}}")
|
|
rE(f"checkbutton {fruns}.check.ignoreok -variable ignorArcOk -command ignore_arc_ok_toggled -width 2 -anchor w -indicatoron 0")
|
|
rE(f"label {fruns}.check.ignoreokL -text {{{_('Ignore Arc OK')}}}")
|
|
rE(f"grid {fruns}.check.av -column 0 -row 0 -sticky w -padx {{2 0}} -pady {{0 2}}")
|
|
rE(f"grid {fruns}.check.avL -column 1 -row 0 -sticky w -pady {{0 2}}")
|
|
rE(f"grid {fruns}.check.ohmic -column 0 -row 1 -sticky w -padx {{2 0}} -pady {{0 2}}")
|
|
rE(f"grid {fruns}.check.ohmicL -column 1 -row 1 -sticky w -pady {{0 2}}")
|
|
rE(f"grid {fruns}.check.mesh -column 0 -row 2 -sticky w -padx {{2 0}} -pady {{0 2}}")
|
|
rE(f"grid {fruns}.check.meshL -column 1 -row 2 -sticky w -pady {{0 2}}")
|
|
rE(f"grid {fruns}.check.ignoreok -column 0 -row 3 -sticky w -padx {{2 0}} -pady {{0 2}}")
|
|
rE(f"grid {fruns}.check.ignoreokL -column 1 -row 3 -sticky w -pady {{0 2}}")
|
|
# pmx frame
|
|
rE(f"labelframe {fruns}.pmx -text {{{_('Powermax')}}} -relief groove")
|
|
rE(f"checkbutton {fruns}.pmx.enable -text {{{_('Powermax Comms')}}} -variable pmx485Enable -command pmx485_enable_toggled -width 2 -anchor w -indicatoron 0")
|
|
rE(f"label {fruns}.pmx.info -anchor w")
|
|
rE(f"pack {fruns}.pmx.enable -expand 1 -fill x")
|
|
rE(f"pack {fruns}.pmx.info -expand 1 -fill x")
|
|
|
|
def populate_run_panel():
|
|
if pVars.orient.get() == 'portrait':
|
|
rE(f"grid {fportrait} -column 1 -row 3 -sticky nsew -padx 2 -pady {{0 2}}")
|
|
rE(f"grid {fbuttons} -column 0 -row 0 -sticky nsew -padx 0 -pady 0")
|
|
rE(f"grid {fruns} -column 2 -row 0 -sticky nsew -padx 1 -pady 1")
|
|
rE(f"grid {fruns}.check -column 0 -row 1 -sticky new -padx 2 -pady {{0 2}}")
|
|
if pmPort:
|
|
rE(f"grid {fruns}.pmx -column 0 -row 2 -sticky new -padx 2 -pady {{0 2}}")
|
|
rE(f"grid toolmat -column 2 -row 0 -sticky new -padx 2 -pady 2")
|
|
rE(f"grid {fruns}.material -column 2 -row 1 -rowspan 99 -sticky new -padx 2 -pady {{0 2}}")
|
|
rE(f"grid columnconfigure {fruns} 1 -weight 1")
|
|
rE(f"grid columnconfigure {fportrait} 1 -weight 1")
|
|
rE(f"grid columnconfigure {fportrait} 2 -weight 1")
|
|
else:
|
|
rE(f"grid {fbuttons} -column 0 -row 1 -rowspan 2 -sticky nsew -padx 0 -pady 0")
|
|
rE(f"grid {toolmat} -column 3 -row 0 -sticky nesw")
|
|
rE(f"grid {fruns}.material -column 0 -row 1 -sticky new -padx 2 -pady {{0 2}}")
|
|
rE(f"grid {fruns}.check -column 0 -row 2 -sticky new -padx 2 -pady {{0 2}}")
|
|
if pmPort:
|
|
rE(f"grid {fruns}.pmx -column 0 -row 3 -sticky new -padx 2 -pady {{0 2}}")
|
|
rE(f"grid {fruns} -column 3 -row 1 -rowspan 2 -sticky nsew -padx 1 -pady 1")
|
|
if pmPort:
|
|
rE(f"grid {fruns}.material.cut-mode -column 0 -row 20 -padx {{2 0}} -pady {{0 2}}")
|
|
rE(f"grid {fruns}.material.cut-modeL -column 1 -row 20 -sticky W -pady {{0 2}}")
|
|
rE(f"grid {fruns}.material.gas-pressure -column 0 -row 21 -padx {{2 0}} -pady {{0 2}}")
|
|
rE(f"grid {fruns}.material.gas-pressureL -column 1 -row 21 -sticky W -pady {{0 2}}")
|
|
|
|
def populate_settings_frame():
|
|
rE(f"grid forget {fsetup}.l")
|
|
rE(f"grid forget {fsetup}.m")
|
|
rE(f"grid forget {fsetup}.r")
|
|
if pVars.orient.get() == 'portrait':
|
|
rE(f"grid {fsetup}.l -column 0 -row 0 -sticky nw -padx {{4 0}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m -column 2 -row 0 -sticky nw -padx {{4 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.r -column 0 -row 1 -columnspan 3 -sticky nsew -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid columnconfigure {fsetup} 0 -weight 0")
|
|
rE(f"grid columnconfigure {fsetup} 1 -weight 1")
|
|
rE(f"grid columnconfigure {fsetup} 2 -weight 0")
|
|
rE(f"grid columnconfigure {fsetup} 3 -weight 0")
|
|
rE(f"grid columnconfigure {fsetup} 4 -weight 0")
|
|
rE(f"grid rowconfigure {fsetup} 0 -weight 0")
|
|
rE(f"grid rowconfigure {fsetup} 1 -weight 1")
|
|
else:
|
|
rE(f"grid {fsetup}.l -column 0 -row 0 -sticky nw -padx {{4 0}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m -column 2 -row 0 -sticky nw -padx {{4 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.r -column 4 -row 0 -sticky nsew -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid columnconfigure {fsetup} 0 -weight 0")
|
|
rE(f"grid columnconfigure {fsetup} 1 -weight 1")
|
|
rE(f"grid columnconfigure {fsetup} 2 -weight 0")
|
|
rE(f"grid columnconfigure {fsetup} 3 -weight 1")
|
|
rE(f"grid columnconfigure {fsetup} 4 -weight 9")
|
|
rE(f"grid rowconfigure {fsetup} 0 -weight 1")
|
|
rE(f"grid rowconfigure {fsetup} 1 -weight 0")
|
|
|
|
def populate_user_buttons():
|
|
if pVars.orient.get() == 'portrait':
|
|
col = 0
|
|
row = 1
|
|
else:
|
|
col = 0
|
|
row = 2
|
|
width = 0
|
|
for n in range(1, maxUserButtons + 1):
|
|
rE(f"grid forget {fbuttons}.button{n}")
|
|
if buttonNames[n]['name'] or buttonCodes[n]['code']:
|
|
rE(f"grid {fbuttons}.button{n} -column {col} -row {row} -sticky new -padx {{2 0}} -pady {{2 0}}")
|
|
if pVars.orient.get() == 'portrait':
|
|
col += 1
|
|
if col == 2:
|
|
col = 0
|
|
row += 1
|
|
else:
|
|
row += 1
|
|
if len(buttonNames[n]['name']) > width:
|
|
width = len(buttonNames[n]['name'])
|
|
width = width if width > 10 else 10
|
|
for n in range(1, maxUserButtons + 1):
|
|
rE(f"{fbuttons}.button{n} configure -width {int(width)}")
|
|
rE(f"{fsetup}.r.ubuttons.canvas.frame.name{n} configure -width {width + 2}")
|
|
|
|
def recreate_widget_list():
|
|
global widgets
|
|
# recreate widget list to move active gcodes and add new widgets
|
|
widget_list_new = []
|
|
for l in widget_list:
|
|
if '.gcodes' in l[2]:
|
|
l = ('code_text', Text, '.info.gcodef.gcodes')
|
|
widget_list_new.append(l)
|
|
widget_list_new.append(('buttonFrame', Frame, fbuttons))
|
|
widget_list_new.append(('convFrame', Frame, '.fconv'))
|
|
widget_list_new.append(('toolFrame', Frame, '.toolconv'))
|
|
widget_list_new.append(('materials', bwidget.ComboBox, f"{fruns}.material.materials"))
|
|
widget_list_new.append(('kerfWidth', Spinbox, f"{fruns}.material.kerf-width"))
|
|
widget_list_new.append(('view_t', Button, '.toolbar.view_t'))
|
|
widgets = nf.Widgets(root_window, *widget_list_new)
|
|
|
|
|
|
##############################################################################
|
|
# SETUP #
|
|
##############################################################################
|
|
firstRun = 'valid'
|
|
orientStart = False
|
|
configPath = os.getcwd()
|
|
p2Path = os.path.join(configPath, 'plasmac2')
|
|
if os.path.isdir(os.path.join(p2Path, 'lib')):
|
|
extHalPins = {}
|
|
import sys
|
|
libPath = os.path.join(p2Path, 'lib')
|
|
sys.path.append(libPath)
|
|
import tarfile
|
|
from tkinter.colorchooser import askcolor
|
|
from collections import OrderedDict
|
|
from glob import glob as GLOB
|
|
from shutil import copy as COPY
|
|
from shutil import which as WHICH
|
|
from subprocess import Popen, PIPE
|
|
from importlib import reload
|
|
from plasmac import run_from_line as RFL
|
|
''' comment after next line:
|
|
suppresses unresolved module error in VSCode '''
|
|
import conversational # type: ignore
|
|
import webbrowser
|
|
imagePath = os.path.join(libPath, 'images') # our own images
|
|
imageAxis = os.path.join(BASE, 'share', 'axis', 'images') # images pinched from Axis
|
|
if not os.path.isdir('/tmp/plasmac'):
|
|
os.mkdir('/tmp/plasmac')
|
|
tmpPath = '/tmp/plasmac'
|
|
installType = 'pkg' if os.path.dirname(__file__) == '/bin' else 'rip'
|
|
PREF = plasmacPreferences()
|
|
MATS = plasmacMaterials()
|
|
TEMP = plasmacTempMaterial()
|
|
# for calling tcl code
|
|
rE = root_window.tk.eval
|
|
# set the app icon
|
|
icon = PhotoImage(file=f"{imagePath}/chips_plasma.png")
|
|
rE(f"wm iconphoto . {icon}")
|
|
# set the version
|
|
try:
|
|
with open(os.path.join(p2Path, 'versions.html'), 'r') as inFile:
|
|
for line in inFile:
|
|
if 'v2.' in line:
|
|
VER = line.split('v')[1].split('<')[0]
|
|
break
|
|
except:
|
|
VER = '0'
|
|
putPrefs(PREF, 'GUI_OPTIONS', 'Version', VER, str)
|
|
# tk widget variables
|
|
pVars = nf.Variables(root_window,
|
|
('plasmatool', StringVar),('thcAuto', BooleanVar), ('thcEnable', BooleanVar),
|
|
('cornerEnable', BooleanVar), ('voidEnable', BooleanVar), ('autoVolts', BooleanVar),
|
|
('ohmicEnable', BooleanVar), ('meshEnable', BooleanVar), ('ignorArcOk', BooleanVar),
|
|
('closeText', StringVar), ('closeDialog', BooleanVar), ('kbShortcuts', BooleanVar),
|
|
('useVirtKB', BooleanVar), ('winSize', StringVar), ('orient', StringVar),
|
|
('startLine', IntVar), ('rflActive', BooleanVar), ('preRflFile', StringVar),
|
|
('laserText', StringVar), ('crSpeed', IntVar), ('previewLarge', BooleanVar),
|
|
('jogSpeed', DoubleVar), ('plasmacMode', IntVar), ('fontSize', StringVar),
|
|
('guiFont', StringVar), ('codeFont', StringVar), ('coneSize', DoubleVar),
|
|
('popLocation', StringVar), ('kerfWidth', DoubleVar), ('cutAmps', IntVar),
|
|
('cutMode', IntVar), ('gasPressure', DoubleVar), ('pmx485Enable', BooleanVar),
|
|
('preConvFile', IntVar),('matDefault', IntVar), ('jogInhibitOvr', IntVar),
|
|
('lengthJ', StringVar), ('lengthT', StringVar), ('lengthS', DoubleVar), ('runJ', StringVar),
|
|
('pierceJ', StringVar), ('pierceT', StringVar), ('pierceS', IntVar), ('cutS', IntVar),
|
|
('rapidJ', StringVar), ('rapidT', StringVar), ('rapidS', IntVar), ('probeJ', StringVar),
|
|
('probeT', StringVar),('probeS', IntVar), ('torchJ', StringVar), ('torchT', StringVar),
|
|
('torchS', IntVar), ('cutJ', StringVar),('cutT', StringVar), ('pausedJ', StringVar),
|
|
('pausedT', StringVar), ('pausedS', IntVar), ('runT', StringVar), ('runS', IntVar),
|
|
('probeJ', StringVar), ('probeT', StringVar), ('probeS', IntVar), ('arcT', StringVar),
|
|
('jogMultiplier', DoubleVar))
|
|
restoreSetup = {}
|
|
pVars.plasmacMode.set(getPrefs(PREF, 'GUI_OPTIONS', 'Mode', 0, int))
|
|
restoreSetup['plasmacMode'] = pVars.plasmacMode.get()
|
|
pVars.winSize.set(getPrefs(PREF, 'GUI_OPTIONS', 'Window size', 'default', str).lower().replace(' ',''))
|
|
restoreSetup['winSize'] = pVars.winSize.get()
|
|
restoreSetup['winLast'] = getPrefs(PREF, 'GUI_OPTIONS', 'Window last', '932x562', str).split('+', 1)[0]
|
|
pVars.orient.set(getPrefs(PREF, 'GUI_OPTIONS', 'Orientation', 'landscape', str).lower().replace(' ',''))
|
|
restoreSetup['orient'] = pVars.orient.get()
|
|
pVars.fontSize.set(getPrefs(PREF, 'GUI_OPTIONS','Font size', '10', str))
|
|
restoreSetup['fontSize'] = pVars.fontSize.get()
|
|
pVars.guiFont.set(getPrefs(PREF, 'GUI_OPTIONS','GUI font', 'Sans', str))
|
|
restoreSetup['guiFont'] = pVars.guiFont.get()
|
|
pVars.codeFont.set(getPrefs(PREF, 'GUI_OPTIONS','Gcode font', 'Sans', str))
|
|
restoreSetup['codeFont'] = pVars.codeFont.get()
|
|
# make some widget names to save typing
|
|
ftop = '.pane.top'
|
|
ftabs = f"{ftop}.tabs"
|
|
fright = f"{ftop}.right"
|
|
stats = f"{fright}.fstats.statistics"
|
|
fmanual = f"{ftabs}.fmanual"
|
|
faxes = f"{fmanual}.axes"
|
|
fjoints = f"{fmanual}.joints"
|
|
fjogf = f"{fmanual}.jogf"
|
|
foverride = f"{fmanual}.override"
|
|
flimitovr = f"{fmanual}.jogf.limitovr"
|
|
fjogiovr = f"{fmanual}.jogf.inhibitovr"
|
|
fplasma = f"{fmanual}.plasma"
|
|
farcv = f"{fplasma}.arcv"
|
|
fthc = f"{fplasma}.thc"
|
|
fmdi = f"{ftabs}.fmdi"
|
|
ft = '.pane.bottom.t'
|
|
fleds = '.pane.bottom.leds'
|
|
fcutrecs = f"{ftabs}.fcutrecs"
|
|
fcrspeed = f"{fcutrecs}.pm"
|
|
fcrbuttons = f"{fcutrecs}.buttons"
|
|
fcrleadin = f"{fcutrecs}.leadins"
|
|
fparam = '.param'
|
|
fsetup = '.setup'
|
|
# spinbox validator
|
|
valspin = root_window.register(validate_spinbox)
|
|
torchEnable = {}
|
|
torchEnable['enabled'] = getPrefs(PREF, 'BUTTONS', 'Torch enabled', 'Torch Enabled', str)
|
|
torchEnable['disabled'] = getPrefs(PREF, 'BUTTONS','Torch disabled', 'Torch Disabled', str)
|
|
pmPort = getPrefs(PREF, 'POWERMAX', 'Port', '', str)
|
|
set_orient_frames()
|
|
recreate_widget_list()
|
|
wLeds = {f"{fleds}.led-arc-ok": [_('Arc OK'), 8], \
|
|
f"{fleds}.led-torch": [_('Torch On'), 8], \
|
|
f"{fleds}.led-breakaway": [_('Break'), 8], \
|
|
f"{fleds}.led-thc-enabled": [_('THC Enabled'), 11], \
|
|
f"{fleds}.led-thc-active": [_('THC Active'), 11], \
|
|
f"{fleds}.led-ohmic": [_('Ohmic Probe'), 11], \
|
|
f"{fleds}.led-float": [_('Float Switch'), 11], \
|
|
f"{fleds}.led-up": [_('Up'), 8], \
|
|
f"{fleds}.led-down": [_('Down'), 8], \
|
|
f"{fleds}.led-corner-locked": [_('Vel Lock'), 8], \
|
|
f"{fleds}.led-void-locked": [_('Void Lock'), 8], \
|
|
}
|
|
read_colors()
|
|
thcFeedRate = round((float(inifile.find('AXIS_Z', 'MAX_VELOCITY')) * float(inifile.find('AXIS_Z', 'OFFSET_AV_RATIO'))) * 60, 3)
|
|
offsetFeedRate = min(float(inifile.find('AXIS_X', 'MAX_VELOCITY')) * 30, \
|
|
float(inifile.find('AXIS_Y', 'MAX_VELOCITY')) * 30, \
|
|
float(inifile.find('TRAJ', 'MAX_LINEAR_VELOCITYs') or 100000))
|
|
maxHeight = round(hal.get_value('ini.z.max_limit') - hal.get_value('ini.z.min_limit'), 3)
|
|
unitsPerMm = hal.get_value('halui.machine.units-per-mm')
|
|
isIdle = False
|
|
isIdleHomed = False
|
|
isPaused = False
|
|
isRunning = False
|
|
homeInProgress = False
|
|
getMaterialBusy = False
|
|
materialFileDict = {}
|
|
materialNumList = []
|
|
materialAutoChange = False
|
|
probePressed = False
|
|
probeTimer = 0
|
|
probeButton = ''
|
|
torchPressed = False
|
|
torchTimer = 0
|
|
torchButton = ''
|
|
torchHeight = 0
|
|
cChangeButton = ''
|
|
cutType = 0
|
|
togglePins = {}
|
|
pulsePins = {}
|
|
dualCodes = {}
|
|
currentTool = None
|
|
manualCut = {'state':False, 'feed':vars.jog_speed.get()}
|
|
singleCut = {'state':False, 'G91':False}
|
|
framingState = False
|
|
runState = False
|
|
dryRun = None
|
|
lastMotionMode = None
|
|
laserTimer = 0.0
|
|
laserButtonState = 'laser'
|
|
laserOffsets = {}
|
|
laserOffsets['X'] = getPrefs(PREF, 'LASER_OFFSET', 'X axis', 0, float)
|
|
laserOffsets['Y'] = getPrefs(PREF, 'LASER_OFFSET', 'Y axis', 0, float)
|
|
probeOffsets = {}
|
|
probeOffsets['X'] = getPrefs(PREF, 'OFFSET_PROBING', 'X axis', 0, float)
|
|
probeOffsets['Y'] = getPrefs(PREF, 'OFFSET_PROBING', 'Y axis', 0, float)
|
|
probeOffsets['Delay'] = getPrefs(PREF, 'OFFSET_PROBING', 'Delay', 0, float)
|
|
machineBounds = {}
|
|
machineBounds['X-'] = round(float(inifile.find('AXIS_X', 'MIN_LIMIT')), 6)
|
|
machineBounds['X+'] = round(float(inifile.find('AXIS_X', 'MAX_LIMIT')), 6)
|
|
machineBounds['Y-'] = round(float(inifile.find('AXIS_Y', 'MIN_LIMIT')), 6)
|
|
machineBounds['Y+'] = round(float(inifile.find('AXIS_Y', 'MAX_LIMIT')), 6)
|
|
machineBounds['Z-'] = round(float(inifile.find('AXIS_Z', 'MIN_LIMIT')), 6)
|
|
machineBounds['Z+'] = round(float(inifile.find('AXIS_Z', 'MAX_LIMIT')), 6)
|
|
machineBounds['xLen'] = machineBounds['X+'] - machineBounds['X-']
|
|
machineBounds['yLen'] = machineBounds['Y+'] - machineBounds['Y-']
|
|
machineBounds['zLen'] = machineBounds['Z+'] - machineBounds['Z-']
|
|
startAlignPos = {X:0, Y:0}
|
|
relPos = {X:0, Y:0}
|
|
activeFunction = False
|
|
pausedState = False
|
|
convFirstRun = True
|
|
convViewOptions = {}
|
|
lastViewType = None
|
|
preConvFile = os.path.join(tmpPath, 'pre_conv.ngc')
|
|
keyDelay = {}
|
|
pmx485 = {'exists':False, 'meshMode':False}
|
|
spinBoxes = []
|
|
widgetValues = {}
|
|
statValues = {'length':0, 'pierce':0, 'rapid':0, 'probe':0, 'torch':0, 'cut':0, 'paused':0, 'run':0}
|
|
toolButtons = ['machine_estop','machine_power','file_open','reload','program_run',
|
|
'program_step','program_pause','program_stop','program_blockdelete',
|
|
'program_optpause','view_zoomin','view_zoomout','view_z','view_z2',
|
|
'view_x','view_y','view_y2','view_p','view_t','rotate','clear_plot']
|
|
matButtons = ['delete','new','reload','save']
|
|
maxUserButtons = 20
|
|
# allow right-click to select start from line
|
|
o.bind('<Button-3>', rClicker, '+')
|
|
# hijacked functions from axis.py
|
|
# vupdate
|
|
# get_coordinate_font
|
|
# install_help
|
|
# prompt_touchoff
|
|
# monkeypatched functions from axis.py
|
|
o.get_view = get_view
|
|
filter_program_old = filter_program
|
|
filter_program = filter_program_new
|
|
# monkeypatched functions from glcanon.py
|
|
o.draw_grid = draw_grid
|
|
o.posstrs = posstrs
|
|
# tcl called python functions hijacked from axis.py
|
|
TclCommands.reload_file = reload_file
|
|
TclCommands.task_run = task_run
|
|
TclCommands.task_run_line = task_run_line
|
|
TclCommands.open_file_name = open_file_name
|
|
TclCommands.set_view_p = set_view_p
|
|
TclCommands.set_view_z = set_view_z
|
|
TclCommands.get_jog_speed = get_jog_speed
|
|
TclCommands.send_mdi_command = send_mdi_command
|
|
# tcl functions hijacked from axis.tcl
|
|
TclCommands.update_title = update_title
|
|
TclCommands.update_jog_slider_vel = update_jog_slider_vel
|
|
TclCommands.set_pane_minsize = set_pane_minsize
|
|
# new functions
|
|
TclCommands.set_view_t = set_view_t
|
|
TclCommands.param_changed = param_changed
|
|
TclCommands.material_changed = material_changed
|
|
TclCommands.save_material_clicked = save_material_clicked
|
|
TclCommands.reload_material_clicked = reload_material_clicked
|
|
TclCommands.new_material_clicked = new_material_clicked
|
|
TclCommands.delete_material_clicked = delete_material_clicked
|
|
TclCommands.change_default_material = change_default_material
|
|
TclCommands.save_param_clicked = save_param_clicked
|
|
TclCommands.load_param_clicked = load_param_clicked
|
|
TclCommands.backup_clicked = backup_clicked
|
|
TclCommands.save_setup_clicked = save_setup_clicked
|
|
TclCommands.load_setup_clicked = load_setup_clicked
|
|
TclCommands.clear_program = clear_program
|
|
TclCommands.preview_toggle = preview_toggle
|
|
TclCommands.setup_toggle = setup_toggle
|
|
TclCommands.param_toggle = param_toggle
|
|
TclCommands.conv_toggle = conv_toggle
|
|
TclCommands.thc_enable_toggled = thc_enable_toggled
|
|
TclCommands.corner_enable_toggled = corner_enable_toggled
|
|
TclCommands.void_enable_toggled = void_enable_toggled
|
|
TclCommands.auto_volts_toggled = auto_volts_toggled
|
|
TclCommands.ohmic_enable_toggled = ohmic_enable_toggled
|
|
TclCommands.ignore_arc_ok_toggled = ignore_arc_ok_toggled
|
|
TclCommands.close_window = close_window
|
|
TclCommands.set_window_size = set_window_size
|
|
TclCommands.set_orientation = set_orientation
|
|
TclCommands.button_action = button_action
|
|
TclCommands.mode_changed = mode_changed
|
|
TclCommands.font_changed = font_changed
|
|
TclCommands.cone_size_changed = cone_size_changed
|
|
TclCommands.height_raise = height_raise
|
|
TclCommands.height_lower = height_lower
|
|
TclCommands.height_reset = height_reset
|
|
TclCommands.torch_enable = torch_enable
|
|
TclCommands.joint_mode_switch = joint_mode_switch
|
|
TclCommands.ja_button_activated = ja_button_activated
|
|
TclCommands.manual_cut = manual_cut
|
|
TclCommands.touch_off_xy = touch_off_xy
|
|
TclCommands.laser_button_toggled = laser_button_toggled
|
|
TclCommands.cut_rec_motion = cut_rec_motion
|
|
TclCommands.cut_rec_default_changed = cut_rec_default_changed
|
|
TclCommands.cut_rec_slider_changed = cut_rec_slider_changed
|
|
TclCommands.cut_rec_move = cut_rec_move
|
|
TclCommands.cut_rec_cancel = cut_rec_cancel
|
|
TclCommands.pmx485_mode_changed = pmx485_mode_changed
|
|
TclCommands.pmx485_pressure_changed = pmx485_pressure_changed
|
|
TclCommands.pmx485_enable_toggled = pmx485_enable_toggled
|
|
TclCommands.pmx485_mesh_enable_toggled = pmx485_mesh_enable_toggled
|
|
TclCommands.reset_all_stats = reset_all_stats
|
|
TclCommands.set_peripheral_offsets = set_peripheral_offsets
|
|
TclCommands.kb_shortcuts_changed = kb_shortcuts_changed
|
|
TclCommands.virtual_kb_changed = virtual_kb_changed
|
|
TclCommands.key_pressed = key_pressed
|
|
TclCommands.key_released = key_released
|
|
TclCommands.color_set = color_set
|
|
TclCommands.user_manual = user_manual
|
|
commands = TclCommands(root_window)
|
|
# set up the fonts
|
|
lastFontSize = pVars.fontSize.get()
|
|
fontsCode = []
|
|
fontsGui = []
|
|
for font in tuple_from_tcl_string(rE('font families')):
|
|
if 'caps' in font.lower() or 'slanted' in font.lower() or 'light' in font.lower() \
|
|
or 'dingbat' in font.lower() or 'symbols' in font.lower():
|
|
pass
|
|
else:
|
|
if 'mono' in font.lower() or 'courier' in font.lower():
|
|
if font not in fontsCode:
|
|
fontsCode.append(font)
|
|
else:
|
|
if font not in fontsGui:
|
|
fontsGui.append(font)
|
|
if pVars.guiFont.get() not in fontsCode:
|
|
fontsCode.append(pVars.guiFont.get())
|
|
if pVars.guiFont.get() not in fontsGui:
|
|
fontsGui.append(pVars.guiFont.get())
|
|
rE(f"font create fontGui -family {{{pVars.guiFont.get()}}} -size {pVars.fontSize.get()}")
|
|
rE(f"font create fontArc -family {{{pVars.guiFont.get()}}} -size {int(pVars.fontSize.get())*3}")
|
|
rE(f"font create fontCode -family {{{pVars.codeFont.get()}}} -size {pVars.fontSize.get()}")
|
|
update_check()
|
|
|
|
|
|
##############################################################################
|
|
# GUI ALTERATIONS AND ADDITIONS #
|
|
##############################################################################
|
|
# keep tab label sizes the same
|
|
rE(f"{ftabs} configure -homogeneous True")
|
|
rE(f"{fright} configure -homogeneous True")
|
|
|
|
# reduce margins on manual/mdi tabs
|
|
rE(f"{ftabs} configure -internalborderwidth 1")
|
|
rE(f"grid columnconfigure {fmanual} 0 -weight 1")
|
|
rE(f"grid columnconfigure {fmanual} 99 -weight 0")
|
|
|
|
# reduce margins on preview tabs
|
|
rE(f"{fright} configure -internalborderwidth 1")
|
|
|
|
# hide some existing widgets
|
|
rE('pack forget .toolbar.rule9')
|
|
rE('pack forget .toolbar.view_zoomin')
|
|
rE('pack forget .toolbar.view_zoomout')
|
|
rE('pack forget .toolbar.view_z')
|
|
rE('pack forget .toolbar.view_z2')
|
|
rE('pack forget .toolbar.view_x')
|
|
rE('pack forget .toolbar.view_y')
|
|
rE('pack forget .toolbar.view_y2')
|
|
rE('pack forget .toolbar.view_p')
|
|
rE('pack forget .toolbar.rotate')
|
|
rE('pack forget .toolbar.rule12')
|
|
rE('pack forget .toolbar.clear_plot')
|
|
rE(f"grid forget {fmanual}.axis")
|
|
rE(f"grid forget {fmanual}.jogf")
|
|
rE(f"grid forget {fmanual}.space1")
|
|
rE(f"grid forget {fmanual}.spindlel")
|
|
rE(f"grid forget {fmanual}.spindlef")
|
|
rE(f"grid forget {fmanual}.space2")
|
|
rE(f"grid forget {fmanual}.coolant")
|
|
rE(f"grid forget {fmanual}.mist")
|
|
rE(f"grid forget {fmanual}.flood")
|
|
rE(f"pack forget {ftop}.jogspeed.l1")
|
|
rE(f"grid forget {ftop}.spinoverride")
|
|
rE(f"grid forget {ftop}.maxvel")
|
|
|
|
# modify the toolbar
|
|
rE('vrule .toolbar.rule10')
|
|
rE('vrule .toolbar.rule11')
|
|
rE('pack .toolbar.rule9 -side left -padx {66 4} -pady 4 -fill y')
|
|
rE('pack .toolbar.clear_plot -side left')
|
|
rE('pack .toolbar.rule10 -side left -padx 4 -pady 4 -fill y')
|
|
rE('pack .toolbar.view_z -side left')
|
|
rE('pack .toolbar.view_p -side left')
|
|
rE(f".toolbar.view_p configure -image {rE(f'load_image {imagePath}/view_p')}")
|
|
rE(f".toolbar.view_z configure -image {rE(f'load_image {imagePath}/view_z')}")
|
|
rE(f"Button .toolbar.view_t -image {rE(f'load_image {imagePath}/view_t')} -command set_view_t -relief link -takefocus 0")
|
|
rE('pack .toolbar.view_t -side left')
|
|
rE('pack .toolbar.rule11 -side left -padx 4 -pady 4 -fill y')
|
|
rE('pack .toolbar.view_zoomout -side left')
|
|
rE('pack .toolbar.view_zoomin -side left')
|
|
rE('pack .toolbar.rule12 -side left -padx 4 -pady 4 -fill y')
|
|
rE('pack .toolbar.rotate -side left')
|
|
rE('.toolbar.rotate configure -takefocus 0')
|
|
|
|
# new setup toolbar
|
|
# create widgets
|
|
rE('frame .toolsetup -borderwidth 1 -relief raised')
|
|
rE(f"Button .toolsetup.save -command save_setup_clicked -width 8 -takefocus 0 -text {{{_('Save All')}}} -padx 0")
|
|
rE(f"Button .toolsetup.reload -command load_setup_clicked -width 8 -takefocus 0 -text {{{_('Reload')}}} -padx 0")
|
|
rE(f"Button .toolsetup.bkp -command backup_clicked -width 8 -takefocus 0 -text {{{_('Backup')}}} -padx 0")
|
|
rE(f"Button .toolsetup.close -command {{setup_toggle 0}} -width 8 -takefocus 0 -text {{{_('Close')}}} -padx 0")
|
|
# populate the tool bar
|
|
rE('pack .toolsetup.save -side left')
|
|
rE('pack .toolsetup.reload -side left -padx {8 0}')
|
|
rE('pack .toolsetup.bkp -side left -padx {8 0}')
|
|
rE('pack .toolsetup.close -side left -padx {16 0}')
|
|
rE('grid forget .toolsetup')
|
|
|
|
# new parameters toolbar
|
|
# create widgets
|
|
rE('frame .toolparam -borderwidth 1 -relief raised')
|
|
rE(f"Button .toolparam.save -command save_param_clicked -width 8 -takefocus 0 -text {{{_('Save All')}}} -padx 0")
|
|
rE(f"Button .toolparam.reload -command load_param_clicked -width 8 -takefocus 0 -text {{{_('Reload')}}} -padx 0")
|
|
rE(f"Button .toolparam.close -command {{param_toggle 0}} -width 8 -takefocus 0 -text {{{_('Close')}}} -padx 0")
|
|
# populate the tool bar
|
|
rE('pack .toolparam.save -side left')
|
|
rE('pack .toolparam.reload -side left -padx {8 0}')
|
|
rE('pack .toolparam.close -side left -padx {16 0}')
|
|
rE('grid forget .toolparam')
|
|
|
|
# new statistics page
|
|
rE(f"{fright} insert end stats -text {{{_('Statistics')}}}")
|
|
rE(f"{fright}.fstats configure -bd 2")
|
|
rE(f"labelframe {stats} -relief groove")
|
|
rE(f"label {stats}.itemL -text {{{_('Item')}}} -width 13 -anchor e")
|
|
rE(f"label {stats}.jobL -text {{{_('Job')}}} -width 9 -anchor e")
|
|
rE(f"label {stats}.totalL -text {{{_('Total')}}} -width 9 -anchor e")
|
|
rE(f"label {stats}.lengthL -text {{{_('Cut Length')}}} -width 13 -anchor e")
|
|
rE(f"label {stats}.lengthJ -textvariable lengthJ -width 9 -anchor e")
|
|
rE(f"label {stats}.lengthT -textvariable lengthT -width 9 -anchor e")
|
|
rE(f"button {stats}.lengthB -command {{reset_all_stats length}} -text {{{_('Reset')}}} -pady 0")
|
|
rE(f"label {stats}.pierceL -text {{{_('Torch Starts')}}} -width 13 -anchor e")
|
|
rE(f"label {stats}.pierceJ -textvariable pierceJ -width 9 -anchor e")
|
|
rE(f"label {stats}.pierceT -textvariable pierceT -width 9 -anchor e")
|
|
rE(f"button {stats}.pierceB -command {{reset_all_stats pierce}} -text {{{_('Reset')}}} -pady 0")
|
|
rE(f"label {stats}.rapidL -text {{{_('Rapid Time')}}} -width 13 -anchor e")
|
|
rE(f"label {stats}.rapidJ -textvariable rapidJ -width 9 -anchor e")
|
|
rE(f"label {stats}.rapidT -textvariable rapidT -width 9 -anchor e")
|
|
rE(f"button {stats}.rapidB -command {{reset_all_stats rapid}} -text {{{_('Reset')}}} -pady 0")
|
|
rE(f"label {stats}.probeL -text {{{_('Probe Time')}}} -width 13 -anchor e")
|
|
rE(f"label {stats}.probeJ -textvariable probeJ -width 9 -anchor e")
|
|
rE(f"label {stats}.probeT -textvariable probeT -width 9 -anchor e")
|
|
rE(f"button {stats}.probeB -command {{reset_all_stats probe}} -text {{{_('Reset')}}} -pady 0")
|
|
rE(f"label {stats}.torchL -text {{{_('Torch On Time')}}} -width 13 -anchor e")
|
|
rE(f"label {stats}.torchJ -textvariable torchJ -width 9 -anchor e")
|
|
rE(f"label {stats}.torchT -textvariable torchT -width 9 -anchor e")
|
|
rE(f"button {stats}.torchB -command {{reset_all_stats torch}} -text {{{_('Reset')}}} -pady 0")
|
|
rE(f"label {stats}.cutL -text {{{_('Cutting Time')}}} -width 13 -anchor e")
|
|
rE(f"label {stats}.cutJ -textvariable cutJ -width 9 -anchor e")
|
|
rE(f"label {stats}.cutT -textvariable cutT -width 9 -anchor e")
|
|
rE(f"button {stats}.cutB -command {{reset_all_stats cut}} -text {{{_('Reset')}}} -pady 0")
|
|
rE(f"label {stats}.pausedL -text {{{_('Paused Time')}}} -width 13 -anchor e")
|
|
rE(f"label {stats}.pausedJ -textvariable pausedJ -width 9 -anchor e")
|
|
rE(f"label {stats}.pausedT -textvariable pausedT -width 9 -anchor e")
|
|
rE(f"button {stats}.pausedB -command {{reset_all_stats paused}} -text {{{_('Reset')}}} -pady 0")
|
|
rE(f"label {stats}.runL -text {{{_('Total Run Time')}}} -width 13 -anchor e")
|
|
rE(f"label {stats}.runJ -textvariable runJ -width 9 -anchor e")
|
|
rE(f"label {stats}.runT -textvariable runT -width 9 -anchor e")
|
|
rE(f"button {stats}.runB -command {{reset_all_stats run}} -text {{{_('Reset')}}} -pady 0")
|
|
rE(f"label {stats}.arcL -text {{{_('Arc On Time')}}} -width 13 -anchor e")
|
|
rE(f"label {stats}.arcT -textvariable arcT -width 10 -anchor e")
|
|
rE(f"grid {stats}.itemL -column 0 -row 0")
|
|
rE(f"grid {stats}.jobL -column 1 -row 0")
|
|
rE(f"grid {stats}.totalL -column 2 -row 0")
|
|
rE(f"grid {stats}.lengthL -column 0 -row 1 -pady {{8 0}}")
|
|
rE(f"grid {stats}.lengthJ -column 1 -row 1 -pady {{8 0}}")
|
|
rE(f"grid {stats}.lengthT -column 2 -row 1 -pady {{8 0}}")
|
|
rE(f"grid {stats}.lengthB -column 3 -row 1 -padx {{16 0}} -pady {{8 0}}")
|
|
rE(f"grid {stats}.pierceL -column 0 -row 2 -pady {{8 0}}")
|
|
rE(f"grid {stats}.pierceJ -column 1 -row 2 -pady {{8 0}}")
|
|
rE(f"grid {stats}.pierceT -column 2 -row 2 -pady {{8 0}}")
|
|
rE(f"grid {stats}.pierceB -column 3 -row 2 -padx {{16 0}} -pady {{8 0}}")
|
|
rE(f"grid {stats}.rapidL -column 0 -row 3 -pady {{8 0}}")
|
|
rE(f"grid {stats}.rapidJ -column 1 -row 3 -pady {{8 0}}")
|
|
rE(f"grid {stats}.rapidT -column 2 -row 3 -pady {{8 0}}")
|
|
rE(f"grid {stats}.rapidB -column 3 -row 3 -padx {{16 0}} -pady {{8 0}}")
|
|
rE(f"grid {stats}.probeL -column 0 -row 4 -pady {{8 0}}")
|
|
rE(f"grid {stats}.probeJ -column 1 -row 4 -pady {{8 0}}")
|
|
rE(f"grid {stats}.probeT -column 2 -row 4 -pady {{8 0}}")
|
|
rE(f"grid {stats}.probeB -column 3 -row 4 -padx {{16 0}} -pady {{8 0}}")
|
|
rE(f"grid {stats}.torchL -column 0 -row 5 -pady {{8 0}}")
|
|
rE(f"grid {stats}.torchJ -column 1 -row 5 -pady {{8 0}}")
|
|
rE(f"grid {stats}.torchT -column 2 -row 5 -pady {{8 0}}")
|
|
rE(f"grid {stats}.torchB -column 3 -row 5 -padx {{16 0}} -pady {{8 0}}")
|
|
rE(f"grid {stats}.cutL -column 0 -row 6 -pady {{8 0}}")
|
|
rE(f"grid {stats}.cutJ -column 1 -row 6 -pady {{8 0}}")
|
|
rE(f"grid {stats}.cutT -column 2 -row 6 -pady {{8 0}}")
|
|
rE(f"grid {stats}.cutB -column 3 -row 6 -padx {{16 0}} -pady {{8 0}}")
|
|
rE(f"grid {stats}.pausedL -column 0 -row 7 -pady {{8 0}}")
|
|
rE(f"grid {stats}.pausedJ -column 1 -row 7 -pady {{8 0}}")
|
|
rE(f"grid {stats}.pausedT -column 2 -row 7 -pady {{8 0}}")
|
|
rE(f"grid {stats}.pausedB -column 3 -row 7 -padx {{16 0}} -pady {{8 0}}")
|
|
rE(f"grid {stats}.runL -column 0 -row 8 -pady {{8 0}}")
|
|
rE(f"grid {stats}.runJ -column 1 -row 8 -pady {{8 0}}")
|
|
rE(f"grid {stats}.runT -column 2 -row 8 -pady {{8 0}}")
|
|
rE(f"grid {stats}.runB -column 3 -row 8 -padx {{16 0}} -pady {{8 0}}")
|
|
if pmPort:
|
|
rE(f"grid {stats}.arcL -column 0 -row 9 -pady {{8 0}}")
|
|
rE(f"grid {stats}.arcT -column 2 -row 9 -pady {{8 0}}")
|
|
rE(f"pack {stats} -fill both -expand True -padx 2 -pady 2")
|
|
|
|
# destroy existing axes and joints
|
|
rE(f"destroy {faxes}")
|
|
rE(f"destroy {fjoints}")
|
|
# create widgets
|
|
rE(f"labelframe {faxes} -text {{{_('Axis:')}}} -relief flat -bd 0")
|
|
rE(f"labelframe {fjoints} -text {{{_('Joint:')}}} -relief flat -bd 0")
|
|
# make joints radiobuttons
|
|
for number in range(0,linuxcnc.MAX_JOINTS):
|
|
ja_button_setup(f"{fjoints}.joint{number}", number, number)
|
|
# populate joints frame
|
|
count = 0
|
|
for row in range(0,2):
|
|
for column in range(0,5):
|
|
if count == jointcount: break
|
|
pad = '{0 0}' if column == 0 else '{8 0}'
|
|
rE(f"grid {fjoints}.joint{count} -row {row} -column {column} -padx {pad}")
|
|
count += 1
|
|
# make axis radiobuttons
|
|
for letter in 'xyzabcuvw':
|
|
ja_button_setup(f"{faxes}.axis{letter}", letter, letter.upper())
|
|
# populate the axes frame
|
|
count = 0
|
|
letters = 'xyzabcuvw'
|
|
first_axis = ''
|
|
for row in range(0,2):
|
|
for column in range(0,5):
|
|
if letters[count] in trajcoordinates:
|
|
if first_axis == '':
|
|
first_axis = letters[count]
|
|
pad = '{0 0}' if column == 0 else '{8 0}'
|
|
rE(f"grid {faxes}.axis{letters[count]} -row {row} -column {column} -padx {pad}")
|
|
count += 1
|
|
if count == 9: break
|
|
|
|
# rework the jogf frame
|
|
rE(f"destroy {fjogf}")
|
|
# create the widgets
|
|
rE(f"frame {fjogf}")
|
|
rE(f"labelframe {fjogf}.jog -text {{{_('Jog:')}}} -relief flat -bd 0")
|
|
rE(f"button {fjogf}.jog.jogminus -command {{if ![is_continuous] {{jog_minus 1}}}} -height 1 -width 1 -text -")
|
|
rE(f"button {fjogf}.jog.jogplus -command {{if ![is_continuous] {{jog_plus 1}}}} -height 1 -width 1 -text +")
|
|
rE(f"combobox {fjogf}.jog.jogincr -editable 0 -textvariable jogincrement -value {{{_('Continuous')}}} -width 10")
|
|
rE(f"{fjogf}.jog.jogincr list insert end {{{_('Continuous')}}}")
|
|
if increments:
|
|
for inc in increments:
|
|
rE(f"{fjogf}.jog.jogincr list insert end {inc}")
|
|
rE(f"labelframe {fjogf}.zerohome -text {{{_('Zero:')}}} -relief flat -bd 0")
|
|
rE(f"button {fjogf}.zerohome.home -command home_joint -height 1 -width 8 -padx 0")
|
|
rE(f"setup_widget_accel {fjogf}.zerohome.home {{{_('Home Axis')}}}")
|
|
rE(f"button {fjogf}.zerohome.zero -command touch_off_system -height 1 -width 5 -padx 0")
|
|
rE(f"setup_widget_accel {fjogf}.zerohome.zero X0")
|
|
rE(f"button {fjogf}.zerohome.zeroxy -height 1 -width 5 -text {{{_('X0Y0')}}} -padx 0")
|
|
rE(f"button {fjogf}.zerohome.laser -height 1 -width 5 -textvariable laserText -padx 0")
|
|
rE(f"button {fjogf}.zerohome.tooltouch") # unused... kept for tk hierarchy
|
|
# widget bindings
|
|
rE(f"bind {fjogf}.jog.jogminus <Button-1> {{if [is_continuous] {{jog_minus}}}}")
|
|
rE(f"bind {fjogf}.jog.jogminus <ButtonRelease-1> {{if [is_continuous] {{jog_stop}}}}")
|
|
rE(f"bind {fjogf}.jog.jogplus <Button-1> {{if [is_continuous] {{jog_plus}}}}")
|
|
rE(f"bind {fjogf}.jog.jogplus <ButtonRelease-1> {{if [is_continuous] {{jog_stop}}}}")
|
|
rE(f"bind {fjogf}.zerohome.zeroxy <Button-1> {{touch_off_xy 1 0 0}}")
|
|
rE(f"bind {fjogf}.zerohome.zeroxy <ButtonRelease-1> {{touch_off_xy 0 0 0}}")
|
|
rE(f"bind {fjogf}.zerohome.laser <Button-1> {{laser_button_toggled 1 1}}")
|
|
rE(f"bind {fjogf}.zerohome.laser <ButtonRelease-1> {{laser_button_toggled 0 1}}")
|
|
# populate the frame
|
|
rE(f"grid {fjogf}.jog.jogminus -row 0 -column 0 -sticky nsew")
|
|
rE(f"grid {fjogf}.jog.jogincr -row 0 -column 1 -sticky nsew -padx 8")
|
|
rE(f"grid {fjogf}.jog.jogplus -row 0 -column 2 -sticky nsew")
|
|
rE(f"grid {fjogf}.jog -row 0 -column 0 -sticky ew")
|
|
rE(f"grid {fjogf}.zerohome.home -row 0 -column 0 -padx {{0 4}}")
|
|
rE(f"grid {fjogf}.zerohome.zero -row 0 -column 1 -padx {{0 4}}")
|
|
rE(f"grid {fjogf}.zerohome.zeroxy -row 0 -column 2 -padx {{0 4}}")
|
|
rE(f"grid {fjogf}.zerohome -row 1 -column 0 -pady {{2 0}} -sticky w")
|
|
rE(f"grid {fjogf} -column 0 -row 1 -padx 2 -pady {{0 0}} -sticky w")
|
|
|
|
# make home button a home all button if required
|
|
if homing_order_defined:
|
|
if ja_name.startswith('A'):
|
|
hbName = 'axes'
|
|
else:
|
|
hbName ='joints'
|
|
widgets.homebutton.configure(text = _('Home All'), command = 'home_all_joints')
|
|
else:
|
|
pre = _('Home')
|
|
widgets.homebutton.configure(text = f"{pre} X")
|
|
|
|
# add a spacer to keep the plasma widgets at the bottom
|
|
rE(f"vspace {fmanual}.vspace -height 1")
|
|
rE(f"grid {fmanual}.vspace -column 0 -row 2 -pady 0 -sticky nsew")
|
|
rE(f"grid rowconfigure {fmanual} 2 -weight 99")
|
|
|
|
# new limit switch override frame
|
|
rE(f"frame {flimitovr} -bd 0")
|
|
rE(f"button {fjogf}.override") # dummy button to placate original axis code
|
|
rE(f"checkbutton {flimitovr}.button -command toggle_override_limits -width 2 -anchor w -indicatoron 0")
|
|
rE(f"label {flimitovr}.label -text {{{_('Override Limits')}}} -anchor center")
|
|
# populate the frame
|
|
rE(f"grid {flimitovr}.button -column 0 -row 1 -sticky nsw")
|
|
rE(f"grid {flimitovr}.label -column 1 -row 1 -sticky w -padx {{4 0}}")
|
|
rE(f"grid rowconfigure {flimitovr} 0 -weight 1")
|
|
rE(f"grid rowconfigure {flimitovr} 1 -weight 0")
|
|
rE(f"grid rowconfigure {flimitovr} 2 -weight 1")
|
|
|
|
# new jog inhibit override frame
|
|
rE(f"frame {fjogiovr} -bd 0")
|
|
rE(f"checkbutton {fjogiovr}.button -variable jogInhibitOvr -width 2 -anchor w -indicatoron 0")
|
|
rE(f"label {fjogiovr}.label -text {{{_('Jog Inhibit Override')}}} -anchor center")
|
|
# populate the frame
|
|
rE(f"grid {fjogiovr}.button -column 0 -row 1 -sticky nsw")
|
|
rE(f"grid {fjogiovr}.label -column 1 -row 1 -sticky w -padx {{4 0}}")
|
|
rE(f"grid rowconfigure {fjogiovr} 0 -weight 1")
|
|
rE(f"grid rowconfigure {fjogiovr} 1 -weight 0")
|
|
rE(f"grid rowconfigure {fjogiovr} 2 -weight 1")
|
|
|
|
# new height override frame
|
|
# create the widgets
|
|
rE(f"labelframe {foverride} -text {{{_('THC Height Override:')}}} -relief flat -bd 0")
|
|
rE(f"Button {foverride}.lower -text - -width 1 -takefocus 0")
|
|
rE(f"Button {foverride}.raise -text + -width 1 -takefocus 0")
|
|
rE(f"label {foverride}.height-override -text {torchHeight:.1f}V -width 20")
|
|
rE(f"Button {foverride}.reset -text {{{_('Reset')}}} -width 1 -takefocus 0 -width 3")
|
|
# populate the frame
|
|
rE(f"grid {foverride}.lower -column 0 -row 0")
|
|
rE(f"grid {foverride}.raise -column 1 -row 0 -padx {{4 0}}")
|
|
rE(f"grid {foverride}.height-override -column 2 -row 0 -sticky ew")
|
|
rE(f"grid {foverride}.reset -column 3 -row 0")
|
|
rE(f"grid {foverride} -column 0 -row 3 -padx 2 -pady {{0 4}} -sticky ew")
|
|
rE(f"grid columnconfigure {foverride} 2 -weight 1")
|
|
# widget bindings
|
|
rE(f"bind {foverride}.lower <ButtonPress-1> height_lower")
|
|
rE(f"bind {foverride}.raise <ButtonPress-1> height_raise")
|
|
rE(f"bind {foverride}.reset <ButtonPress-1> height_reset")
|
|
|
|
# new plasma frame
|
|
# create the widgets
|
|
rE(f"frame {fplasma} -bd 0")
|
|
rE(f"label {fplasma}.arcvl -anchor nw -text {{{_('Arc Voltage:')}}}")
|
|
rE(f"label {fplasma}.arc-voltage -anchor se -width 4")
|
|
rE(f"checkbutton {fplasma}.thc -variable thcEnable -command thc_enable_toggled -width 2 -anchor w -indicatoron 0")
|
|
rE(f"label {fplasma}.thcL -anchor nw -text {{{_('THC Enable')}}} -width 11")
|
|
rE(f"checkbutton {fplasma}.vel -variable cornerEnable -command corner_enable_toggled -width 2 -anchor w -indicatoron 0")
|
|
rE(f"label {fplasma}.velL -anchor nw -text {{{_('Velocity Lock')}}} -width 11")
|
|
rE(f"checkbutton {fplasma}.void -variable voidEnable -command void_enable_toggled -width 2 -anchor w -indicatoron 0")
|
|
rE(f"label {fplasma}.voidL -anchor nw -text {{{_('Void Lock')}}} -width 11")
|
|
# populate the frame
|
|
rE(f"grid {fplasma}.thc -column 2 -row 0 -sticky e -pady {{0 2}}")
|
|
rE(f"grid {fplasma}.thcL -column 3 -row 0 -sticky e -pady {{0 2}}")
|
|
rE(f"grid {fplasma}.vel -column 2 -row 1 -sticky e -pady {{0 2}}")
|
|
rE(f"grid {fplasma}.velL -column 3 -row 1 -sticky e -pady {{0 2}}")
|
|
rE(f"grid {fplasma}.void -column 2 -row 2 -sticky e -pady {{0 2}}")
|
|
rE(f"grid {fplasma}.voidL -column 3 -row 2 -sticky e -pady {{0 2}}")
|
|
rE(f"grid {fplasma} -column 0 -row 4 -padx 2 -pady {{0 0}} -sticky ew")
|
|
rE(f"grid columnconfigure {fplasma} 1 -weight 1")
|
|
# shorten some text for nicer layout.
|
|
rE(f".pane.top.rapidoverride.l configure -text {{{_('Rapid Ovr:')}}}")
|
|
rE(f".pane.top.feedoverride.l configure -text {{{_('Feed Ovr:')}}}")
|
|
|
|
# hide bottom pane until modified
|
|
rE('pack forget .pane.bottom.t.text')
|
|
rE('pack forget .pane.bottom.t.sb')
|
|
|
|
# new led frame
|
|
# create the widgets
|
|
rE(f"frame {fleds} -relief flat -bd 0")
|
|
for led in wLeds:
|
|
# leds
|
|
rE(f"canvas {led} -width 20 -height 20 -bd 2 -relief ridge")
|
|
rE(f"{led} create rectangle {{1 1 22 22}} -width 0")
|
|
# labels
|
|
rE(f"label {led}L -text {{{wLeds[led][0]}}} -anchor w -width {wLeds[led][1]}")
|
|
# populate the frame
|
|
rE(f"grid {fleds}.led-arc-ok -column 0 -row 0 -padx {{4 0}} -pady {{4 0}} -sticky EW")
|
|
rE(f"grid {fleds}.led-arc-okL -column 1 -row 0 -padx {{0 0}} -pady {{4 0}} -sticky W")
|
|
rE(f"grid {fleds}.led-torch -column 0 -row 1 -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fleds}.led-torchL -column 1 -row 1 -padx {{0 0}} -pady {{4 0}} -sticky W")
|
|
rE(f"grid {fleds}.led-breakaway -column 0 -row 3 -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fleds}.led-breakawayL -column 1 -row 3 -padx {{0 0}} -pady {{4 0}} -sticky W")
|
|
rE(f"grid {fleds}.led-thc-enabled -column 2 -row 0 -padx {{0 0}} -pady {{4 0}}")
|
|
rE(f"grid {fleds}.led-thc-enabledL -column 3 -row 0 -padx {{0 0}} -pady {{4 0}} -sticky W")
|
|
rE(f"grid {fleds}.led-thc-active -column 2 -row 1 -padx {{0 0}} -pady {{4 0}}")
|
|
rE(f"grid {fleds}.led-thc-activeL -column 3 -row 1 -padx {{0 0}} -pady {{4 0}} -sticky W")
|
|
rE(f"grid {fleds}.led-ohmic -column 2 -row 2 -padx {{0 0}} -pady {{4 0}}")
|
|
rE(f"grid {fleds}.led-ohmicL -column 3 -row 2 -padx {{0 0}} -pady {{4 0}} -sticky W")
|
|
rE(f"grid {fleds}.led-float -column 2 -row 3 -padx {{0 0}} -pady {{4 0}}")
|
|
rE(f"grid {fleds}.led-floatL -column 3 -row 3 -padx {{0 0}} -pady {{4 0}} -sticky W")
|
|
rE(f"grid {fleds}.led-up -column 4 -row 0 -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fleds}.led-upL -column 5 -row 0 -padx {{0 0}} -pady {{4 0}} -sticky W")
|
|
rE(f"grid {fleds}.led-down -column 4 -row 1 -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fleds}.led-downL -column 5 -row 1 -padx {{0 0}} -pady {{4 0}} -sticky W")
|
|
rE(f"grid {fleds}.led-corner-locked -column 4 -row 2 -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fleds}.led-corner-lockedL -column 5 -row 2 -padx {{0 0}} -pady {{4 0}} -sticky W")
|
|
|
|
# rename keyboard shortcut window
|
|
rE('wm title .keys {plasmac2 Keyboard Shortcuts}')
|
|
# new keypad shortcut window
|
|
rE('toplevel .keyp')
|
|
rE('bind .keyp <Key-Return> {wm withdraw .keyp}')
|
|
rE('bind .keyp <Key-Escape> {wm withdraw .keyp}')
|
|
rE('frame .keyp.text')
|
|
rE('button .keyp.ok -command {wm wi .keyp} -default active -padx 0 -pady 0 -width 10')
|
|
rE('setup_widget_accel .keyp.ok OK')
|
|
rE('pack .keyp.text -expand 1 -fill y')
|
|
rE('pack .keyp.ok')
|
|
rE('wm title .keyp {plasmac2 Keypad Shortcuts}')
|
|
rE('wm iconname .keyp ')
|
|
rE('wm resiz .keyp 0 0')
|
|
rE('wm minsize .keyp 1 1')
|
|
rE('wm protocol .keyp WM_DELETE_WINDOW {wm wi .keys}')
|
|
rE('wm withdraw .keyp')
|
|
|
|
# menu alterations
|
|
# remove tearoffs
|
|
rE('.menu.machine configure -tearoff 0')
|
|
rE('.menu.machine.home configure -tearoff 0')
|
|
rE('.menu.machine.unhome configure -tearoff 0')
|
|
# delete some existing
|
|
rE('.menu.file delete last')
|
|
rE('.menu.machine delete last')
|
|
rE('.menu.machine delete last')
|
|
rE('.menu.machine delete last')
|
|
rE('.menu.view delete 20')
|
|
rE('.menu.view delete 8')
|
|
rE('.menu.view delete 7')
|
|
rE('.menu.view delete 6')
|
|
rE('.menu delete last')
|
|
# add new menu items
|
|
rE('.menu.file insert 2 command -command clear_program')
|
|
rE(f"setup_menu_accel .menu.file 2 {{{_('_Clear')}}}")
|
|
rE('.menu.file add command -command close_window')
|
|
rE(f"setup_menu_accel .menu.file end {{{_('_Quit')}}}")
|
|
rE('.menu.view insert 0 checkbutton -variable previewLarge -command preview_toggle')
|
|
rE(f"setup_menu_accel .menu.view 0 {{{_('Large Pre_view')}}}")
|
|
rE('.menu.view insert 1 separator')
|
|
rE('.menu add command -command {conv_toggle 1}')
|
|
rE(f"setup_menu_accel .menu end {{{_('_Conversational')}}}")
|
|
rE('.menu add command -command {param_toggle 1}')
|
|
rE(f"setup_menu_accel .menu end {{{_('_Parameters')}}}")
|
|
rE('.menu add command -command {setup_toggle 1}')
|
|
rE(f"setup_menu_accel .menu end {{{_('_Setup')}}}")
|
|
rE('.menu add cascade -menu .menu.help')
|
|
rE(f"setup_menu_accel .menu end {{{_('_Help')}}}")
|
|
rE('.menu.help delete 0 1')
|
|
rE('.menu.help add command -command {wm transient .about .;wm deiconify .about;show_all .about.message;focus .about.ok}')
|
|
rE(f"setup_menu_accel .menu.help end {{{_('About AXIS')}}}")
|
|
rE('.menu.help add separator')
|
|
rE('.menu.help add command -command user_manual')
|
|
rE(f"setup_menu_accel .menu.help end {{{_('User Manual')}}}")
|
|
|
|
# rework the status bar
|
|
rE(f"grid forget {ftop}.gcodel")
|
|
rE(f"grid forget {ftop}.gcodes")
|
|
rE('pack forget .info.tool')
|
|
rE('.info.task_state configure -width 6')
|
|
rE('.info.tool configure -width 10 -textvariable plasmatool')
|
|
rE('.info.position configure -width 25')
|
|
rE('grid .info -columnspan 4')
|
|
rE('labelframe .info.gcodef -relief sunken -bd 2')
|
|
rE('label .info.gcodef.gcodel -bd 0')
|
|
rE('setup_widget_accel .info.gcodef.gcodel {Active Codes:}')
|
|
rE('text .info.gcodef.gcodes -height 1 -width 10 -relief flat -bd 0 -pady 0')
|
|
rE('.info.gcodef.gcodes configure -undo 0 -wrap word')
|
|
rE('pack .info.tool -side left')
|
|
rE('pack .info.gcodef.gcodel -side left')
|
|
rE('pack .info.gcodef.gcodes -side left -fill x -expand 1')
|
|
rE('pack .info.gcodef -side left -fill x -expand 1')
|
|
|
|
# move existing pane to column 1
|
|
rE('grid .pane -column 1 -row 1 -rowspan 2 -sticky nsew')
|
|
# set pane column growth
|
|
rE('grid columnconfigure .pane.top 0 -weight 1')
|
|
rE('grid columnconfigure .pane.top 1 -weight 255')
|
|
# set root window column growth
|
|
rE('grid columnconfigure . 0 -weight 0')
|
|
rE('grid columnconfigure . 1 -weight 1')
|
|
rE('grid columnconfigure . 2 -weight 0')
|
|
|
|
# new cut recovery tab
|
|
# create the widgets
|
|
rE(f"{ftabs} insert end cutrecs -text {{{_('Cut Recovery')}}}")
|
|
rE(f"{fcutrecs} configure -borderwidth 2")
|
|
rE(f"{ftabs} delete cutrecs 0")
|
|
rE(f"labelframe {fcrspeed} -text {{{_('Speed:')}}} -relief flat")
|
|
rE(f"Button {fcrspeed}.reverse -text {{{_('Rev')}}} -takefocus 0 -width 3")
|
|
rE(f"bind {fcrspeed}.reverse <Button-1> {{cut_rec_motion -1}}")
|
|
rE(f"bind {fcrspeed}.reverse <ButtonRelease-1> {{cut_rec_motion 0}}")
|
|
rE(f"frame {fcrspeed}.display -relief flat")
|
|
rE(f"frame {fcrspeed}.display.top -relief flat")
|
|
rE(f"label {fcrspeed}.display.top.value -textvariable crSpeed -width 6 -anchor center")
|
|
rE(f"scale {fcrspeed}.display.cut-rec-speed -takefocus 0 -orient horizontal -showvalue 0 -command cut_rec_slider_changed")
|
|
rE(f"{fcrspeed}.display.cut-rec-speed configure -from 1 -to 100 -resolution 1")
|
|
rE(f"Button {fcrspeed}.forward -text {{{_('Fwd')}}} -takefocus 0 -width 3")
|
|
rE(f"frame {fcrbuttons} -relief flat")
|
|
rE(f"button {fcrbuttons}.laser -text {{{_('Laser')}}} -takefocus 0 -width 6")
|
|
rE(f"button {fcrbuttons}.cancel -text {{{_('Cancel')}}} -command cut_rec_cancel -takefocus 0 -width 6")
|
|
rE(f"labelframe {fcrleadin} -text {{{_('Leadins:')}}} -relief flat")
|
|
rE(f"Button {fcrleadin}.nw -takefocus 0 -image {rE(f'load_image {imagePath}/nw')}")
|
|
rE(f"Button {fcrleadin}.n -takefocus 0 -image {rE(f'load_image {imagePath}/n')}")
|
|
rE(f"Button {fcrleadin}.ne -takefocus 0 -image {rE(f'load_image {imagePath}/ne')}")
|
|
rE(f"Button {fcrleadin}.w -takefocus 0 -image {rE(f'load_image {imagePath}/w')}")
|
|
rE(f"Label {fcrleadin}.offset -textvariable kerfWidth -takefocus 0")
|
|
rE(f"Button {fcrleadin}.e -takefocus 0 -image {rE(f'load_image {imagePath}/e')}")
|
|
rE(f"Button {fcrleadin}.sw -takefocus 0 -image {rE(f'load_image {imagePath}/sw')}")
|
|
rE(f"Button {fcrleadin}.s -takefocus 0 -image {rE(f'load_image {imagePath}/s')}")
|
|
rE(f"Button {fcrleadin}.se -takefocus 0 -image {rE(f'load_image {imagePath}/se')}")
|
|
# populate the frame
|
|
rE(f"pack {fcrspeed}.reverse -side left -fill y")
|
|
rE(f"pack {fcrspeed}.display.top.value -side left -fill y")
|
|
rE(f"pack {fcrspeed}.display.top -fill y")
|
|
rE(f"pack {fcrspeed}.display.cut-rec-speed -fill y")
|
|
rE(f"pack {fcrspeed}.display -side left -fill x -expand 1")
|
|
rE(f"pack {fcrspeed}.forward -side right -fill y")
|
|
rE(f"grid {fcrbuttons}.laser -column 0 -row 0")
|
|
rE(f"grid {fcrbuttons}.cancel -column 2 -row 0")
|
|
rE(f"grid {fcrleadin}.nw -column 0 -row 0")
|
|
rE(f"grid {fcrleadin}.n -column 1 -row 0")
|
|
rE(f"grid {fcrleadin}.ne -column 2 -row 0")
|
|
rE(f"grid {fcrleadin}.w -column 0 -row 1")
|
|
rE(f"grid {fcrleadin}.offset -column 1 -row 1")
|
|
rE(f"grid {fcrleadin}.e -column 2 -row 1")
|
|
rE(f"grid {fcrleadin}.sw -column 0 -row 2")
|
|
rE(f"grid {fcrleadin}.s -column 1 -row 2")
|
|
rE(f"grid {fcrleadin}.se -column 2 -row 2")
|
|
rE(f"grid {fcrspeed} -column 0 -row 0 -sticky wne")
|
|
rE(f"grid {fcrbuttons} -column 0 -row 1 -sticky wne -pady 16")
|
|
rE(f"grid {fcrleadin} -column 0 -row 2 -sticky nsew")# -pady 12")
|
|
# set direction buttons stretch
|
|
rE(f"grid columnconfigure {fcrbuttons} 1 -weight 1")
|
|
rE(f"grid columnconfigure {fcrleadin} 0 -weight 1")
|
|
rE(f"grid columnconfigure {fcrleadin} 1 -weight 1")
|
|
rE(f"grid columnconfigure {fcrleadin} 2 -weight 1")
|
|
rE(f"grid rowconfigure {fcrleadin} 0 -weight 1")
|
|
rE(f"grid rowconfigure {fcrleadin} 1 -weight 1 -pad 20")
|
|
rE(f"grid rowconfigure {fcrleadin} 2 -weight 1")
|
|
# widget bindings
|
|
rE(f"bind {fcrspeed}.forward <Button-1> {{cut_rec_motion 1}}")
|
|
rE(f"bind {fcrspeed}.forward <ButtonRelease-1> {{cut_rec_motion 0}}")
|
|
rE(f"bind {fcrleadin}.nw <Button-1> {{cut_rec_move -1 1}}")
|
|
rE(f"bind {fcrleadin}.n <Button-1> {{cut_rec_move 0 1}}")
|
|
rE(f"bind {fcrleadin}.ne <Button-1> {{cut_rec_move 1 1}}")
|
|
rE(f"bind {fcrleadin}.w <Button-1> {{cut_rec_move -1 0}}")
|
|
rE(f"bind {fcrleadin}.e <Button-1> {{cut_rec_move 1 0}}")
|
|
rE(f"bind {fcrleadin}.sw <Button-1> {{cut_rec_move -1 -1}}")
|
|
rE(f"bind {fcrleadin}.s <Button-1> {{cut_rec_move 0 -1}}")
|
|
rE(f"bind {fcrleadin}.se <Button-1> {{cut_rec_move 1 -1}}")
|
|
rE(f"bind {fcrbuttons}.laser <Button-1> {{laser_button_toggled 1 0}}")
|
|
rE(f"bind {fcrbuttons}.laser <ButtonRelease-1> {{laser_button_toggled 0 0}}")
|
|
|
|
# new parameters frame
|
|
rE(f"frame {fparam}")
|
|
# create the widgets
|
|
rE(f"frame {fparam}.c1")
|
|
rE(f"frame {fparam}.c2")
|
|
rE(f"frame {fparam}.c3")
|
|
rE(f"labelframe {fparam}.c1.probe -text {{{_('Probing')}}} -relief groove")
|
|
rE(f"labelframe {fparam}.c1.motion -text {{{_('Motion')}}} -relief groove")
|
|
rE(f"labelframe {fparam}.c1.safety -text {{{_('Safety')}}} -relief groove")
|
|
rE(f"labelframe {fparam}.c2.thc -text {{{_('THC')}}} -relief groove")
|
|
rE(f"labelframe {fparam}.c2.scribe -text {{{_('Scribe')}}} -relief groove")
|
|
rE(f"labelframe {fparam}.c2.pierce -text {{{_('Pierce Only')}}} -relief groove")
|
|
rE(f"labelframe {fparam}.c3.arc -text {{{_('Arc')}}} -relief groove")
|
|
rE(f"labelframe {fparam}.c3.spotting -text {{{_('Spotting')}}} -relief groove")
|
|
rE(f"label {fparam}.c2.thc.thc-autoL -text {{{_('Auto')}}} -width 15 -anchor e")
|
|
rE(f"checkbutton {fparam}.c2.thc.thc-auto -width 2 -anchor w -indicatoron 0")
|
|
rE(f"{fparam}.c2.thc.thc-auto configure -variable thcAuto -command mode_changed")
|
|
# spinboxes [parent, name, decimals, value, min, max, increment, label text, prefs option]
|
|
cpList = [[f"{fparam}.c1.probe",'float-switch-travel',2,1.5,-25,25,0.01,'Float Travel','Float Switch Travel'], \
|
|
[f"{fparam}.c1.probe",'probe-feed-rate',0,300,1,thcFeedRate,1,'Probe Speed','Probe Feed Rate'], \
|
|
[f"{fparam}.c1.probe",'probe-start-height',0,38,1,maxHeight,1,'Probe Height','Probe Start Height'], \
|
|
[f"{fparam}.c1.probe",'ohmic-probe-offset',2,0,-25,+25,0.01,'Ohmic Z Offset','Ohmic Probe Offset'], \
|
|
[f"{fparam}.c1.probe",'ohmic-max-attempts',0,0,0,10,1,'Ohmic Retries','Ohmic Maximum Attempts'], \
|
|
[f"{fparam}.c1.probe",'skip-ihs-distance',0,0,0,999,1,'Skip IHS','Skip IHS Distance'], \
|
|
[f"{fparam}.c1.probe",'offset-feed-rate',0,offsetFeedRate*0.8,0,offsetFeedRate,1,'Offset Speed','Offset Feed Rate'], \
|
|
[f"{fparam}.c1.motion",'setup-feed-rate',0,int(thcFeedRate * 0.8),1000,thcFeedRate,1,'Setup Speed','Setup Feed Rate'], \
|
|
[f"{fparam}.c1.safety",'safe-height',0,20,0,maxHeight,1,'Safe Height','Safe Height'], \
|
|
[f"{fparam}.c2.thc",'thc-delay',1,0.5,0,9,0.1,'Start Delay','THC Delay'], \
|
|
[f"{fparam}.c2.thc",'thc-sample-counts',0,50,10,1000,1,'Auto Counts','THC Sample Counts'], \
|
|
[f"{fparam}.c2.thc",'thc-sample-threshold',1,1,0.1,9,0.1,'Auto Threshold (V)','THC Sample Threshold'], \
|
|
[f"{fparam}.c2.thc",'thc-threshold',2,1,0.05,9,0.01,'Cut Threshold (V)','THC Threshold'], \
|
|
[f"{fparam}.c2.thc",'pid-p-gain',0,10,0,1000,1,'PID P Gain (Speed)','Pid P Gain'], \
|
|
[f"{fparam}.c2.thc",'pid-i-gain',0,0,0,1000,1,'PID I Gain','Pid I Gain'], \
|
|
[f"{fparam}.c2.thc",'pid-d-gain',0,0,0,1000,1,'PID D Gin','Pid D Gain'], \
|
|
[f"{fparam}.c2.thc",'cornerlock-threshold',0,90,1,99,1,'VAD Threshold (%)','Velocity Anti Dive Threshold'], \
|
|
[f"{fparam}.c2.thc",'voidlock-slope',0,500,1,10000,1,'Void Slope (V/sec)','Void Sense Slope'], \
|
|
[f"{fparam}.c2.scribe",'scribe-arm-delay',1,0,0,9,0.1,'Arm Delay','Scribe Arming Delay'], \
|
|
[f"{fparam}.c2.scribe",'scribe-on-delay',1,0,0,9,0.1,'On delay','Scribe On Delay'], \
|
|
[f"{fparam}.c2.pierce",'x-pierce-offset',1,1.6,-5,5,0.1,'X Offset','X Pierce Offset'], \
|
|
[f"{fparam}.c2.pierce",'y-pierce-offset',1,0,-5,5,0.1,'Y Offset','Y Pierce Offset'], \
|
|
[f"{fparam}.c3.arc",'arc-fail-delay',1,3,0.1,60,0.1,'Fail Timeout','Arc Fail Timeout'], \
|
|
[f"{fparam}.c3.arc",'arc-max-starts',0,3,1,9,1,'Max. Attempts','Arc Maximum Starts'], \
|
|
[f"{fparam}.c3.arc",'restart-delay',0,3,1,60,1,'Retry Delay','Arc Restart Delay'], \
|
|
[f"{fparam}.c3.arc",'arc-voltage-scale',6,1,-9999,9999,0.000001,'Voltage Scale','Arc Voltage Scale'], \
|
|
[f"{fparam}.c3.arc",'arc-voltage-offset',3,0,-999999,999999,0.001,'Voltage Offset','Arc Voltage Offset'], \
|
|
[f"{fparam}.c3.arc",'arc-ok-high',0,99999,0,99999,1,'OK High Volts','Arc OK High'], \
|
|
[f"{fparam}.c3.arc",'arc-ok-low',0,60,0,100,1,'OK Low Volts','Arc OK Low'], \
|
|
[f"{fparam}.c3.arc",'height-per-volt',3,0.1,0.025,0.5,0.01,'Height Per Volt','Height Per Volt'], \
|
|
[f"{fparam}.c3.spotting",'spotting-threshold',0,1,0,199,1,'Threshold (V)','Spotting Threshold'], \
|
|
[f"{fparam}.c3.spotting",'spotting-time',0,0,0,9999,1,'On Time (mS)','Spotting Time'], \
|
|
]
|
|
cpRow = 0
|
|
cpFrame = cpList[0][0]
|
|
for cpItem in cpList:
|
|
if s.linear_units != 1:
|
|
if cpItem[1] == 'float-switch-travel':
|
|
cpItem[2:7] = [3,0.06,-1,1,0.001]
|
|
elif cpItem[1] == 'probe-feed-rate':
|
|
cpItem[2:7] = [1,12,0.1,thcFeedRate,.1]
|
|
elif cpItem[1] == 'probe-start-height':
|
|
cpItem[2:7] = [2,1.5,.1,maxHeight,0.01]
|
|
elif cpItem[1] == 'ohmic-probe-offset':
|
|
cpItem[2:7] = [3,0,-1,1,0.001]
|
|
elif cpItem[1] == 'skip-ihs-distance':
|
|
cpItem[2:7] = [1,0,0,99,.1]
|
|
elif cpItem[1] == 'offset-feed-rate':
|
|
cpItem[2:7] = [1,offsetFeedRate * 0.8,40,offsetFeedRate,.1]
|
|
elif cpItem[1] == 'setup-feed-rate':
|
|
cpItem[2:7] = [1,int(thcFeedRate * 0.8),0.1,thcFeedRate,0.1]
|
|
elif cpItem[1] == 'safe-height':
|
|
cpItem[2:7] = [2,0.75,0,maxHeight,0.01]
|
|
elif cpItem[1] == 'height-per-volt':
|
|
cpItem[2:7] = [4,0.004,0.001,0.020,0.001]
|
|
elif cpItem[1] == 'x-pierce-offset':
|
|
cpItem[2:7] = [2,0.06,-0.2,0.2,0.01]
|
|
elif cpItem[1] == 'y-pierce-offset':
|
|
cpItem[2:7] = [2,0,-0.2,0.2,0.01]
|
|
if cpItem[0] != cpFrame:
|
|
cpFrame = cpItem[0]
|
|
cpRow = 0
|
|
if cpItem[1] == 'thc-delay':
|
|
cpRow += 1
|
|
cpName = f"{cpItem[0]}.{cpItem[1]}"
|
|
cpType = 'flt' if cpItem[2] > 0 else 'int'
|
|
rE(f"label {cpName}L -text {{{cpItem[7]}}} -width 15 -anchor e")
|
|
rE(f"spinbox {cpName} -width 8 -justify right -wrap true")
|
|
spinBoxes.append(cpName)
|
|
rE(f"{cpName} configure -from {cpItem[4]} -to {cpItem[5]}")
|
|
rE(f"{cpName} configure -increment {cpItem[6]} -format %0.{cpItem[2]}f")
|
|
rE(f"{cpName} configure -validate key -vcmd {{{valspin} %W {cpType} {cpItem[2]} %P %s}}")
|
|
if cpItem[1] == 'setup-feed-rate':
|
|
rE(f"label {cpItem[0]}.maxzL -text {{{_('Max Z Speed')}}} -width 15 -anchor e")
|
|
rE(f"label {cpItem[0]}.maxz -text {int(thcFeedRate)} -width 8 -anchor e")
|
|
rE(f"grid {cpItem[0]}.maxzL -column 0 -row {cpRow} -sticky e -padx {{0 0}} -pady {{4 0}}")
|
|
rE(f"grid {cpItem[0]}.maxz -column 1 -row {cpRow} -sticky e -padx {{0 8}} -pady {{4 0}}")
|
|
cpRow += 1
|
|
rE(f"grid {cpName}L -column 0 -row {cpRow} -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {cpName} -column 1 -row {cpRow} -sticky e -padx {{0 4}} -pady {{4 0}}")
|
|
cpRow += 1
|
|
# populate parameters frame
|
|
rE(f"grid {fparam}.c1.probe -column 0 -row 0 -sticky new -padx {{4 2}} -pady {{4 0}} -ipady 4")
|
|
rE(f"grid {fparam}.c1.motion -column 0 -row 1 -sticky new -padx {{4 2}} -pady {{4 0}} -ipady 4")
|
|
rE(f"grid {fparam}.c1.safety -column 0 -row 2 -sticky new -padx {{4 2}} -pady {{4 0}} -ipady 4")
|
|
rE(f"grid {fparam}.c2.thc -column 0 -row 0 -sticky new -padx {{2 2}} -pady {{4 0}} -ipady 4")
|
|
rE(f"grid {fparam}.c2.scribe -column 0 -row 1 -sticky new -padx {{2 2}} -pady {{4 0}} -ipady 4")
|
|
rE(f"grid {fparam}.c2.pierce -column 0 -row 2 -sticky new -padx {{2 2}} -pady {{4 0}} -ipady 4")
|
|
rE(f"grid {fparam}.c3.arc -column 0 -row 0 -sticky new -padx {{2 2}} -pady {{4 0}} -ipady 4")
|
|
rE(f"grid {fparam}.c3.spotting -column 0 -row 1 -sticky new -padx {{2 2}} -pady {{4 0}} -ipady 4")
|
|
rE(f"grid {fparam}.c1 -column 0 -row 0 -sticky n")
|
|
rE(f"grid {fparam}.c2 -column 2 -row 0 -sticky n")
|
|
rE(f"grid {fparam}.c3 -column 4 -row 0 -sticky n")
|
|
rE(f"grid columnconfigure {fparam} 1 -weight 1")
|
|
rE(f"grid columnconfigure {fparam} 3 -weight 1")
|
|
|
|
# new settings frame
|
|
rE(f"frame {fsetup}")
|
|
# left panel
|
|
rE(f"frame {fsetup}.l")
|
|
# gui frame
|
|
rE(f"labelframe {fsetup}.l.gui -text {{{_('GUI')}}} -relief groove")
|
|
rE(f"label {fsetup}.l.gui.closedialogL -text {{{_('Close Dialog')}}} -anchor e")
|
|
rE(f"checkbutton {fsetup}.l.gui.closedialog -variable closeDialog -width 2 -anchor w -indicatoron 0")
|
|
rE(f"label {fsetup}.l.gui.wsizeL -text {{{_('Window Size')}}} -width 13 -anchor e")
|
|
rE(f"ComboBox {fsetup}.l.gui.wsize -modifycmd {{set_window_size combo}} -textvariable winSize -bd 1 -width 10 -justify right -editable 0")
|
|
rE(f"{fsetup}.l.gui.wsize configure -values {{default last fullscreen maximized}}")
|
|
rE(f"label {fsetup}.l.gui.orientL -text {{{_('Window Orient')}}} -width 13 -anchor e")
|
|
rE(f"ComboBox {fsetup}.l.gui.orient -modifycmd set_orientation -textvariable orient -bd 1 -width 10 -justify right -editable 0")
|
|
rE(f"{fsetup}.l.gui.orient configure -values {{landscape portrait}}")
|
|
rE(f"label {fsetup}.l.gui.fsizeL -text {{{_('Font Size')}}} -anchor e")
|
|
rE(f"ComboBox {fsetup}.l.gui.fsize -modifycmd font_changed -textvariable fontSize -bd 1 -width 10 -justify right -editable 0")
|
|
rE(f"{fsetup}.l.gui.fsize configure -values {{7 8 9 10 11 12 13 14 15 16 17 18 19 20}}")
|
|
rE(f"label {fsetup}.l.gui.fguiL -text {{{_('GUI Font')}}} -anchor e")
|
|
rE(f"ComboBox {fsetup}.l.gui.fgui -modifycmd {{font_changed 1}} -textvariable guiFont -bd 1 -width 10 -justify right -editable 0")
|
|
for font in sorted(fontsGui):
|
|
rE(f"{fsetup}.l.gui.fgui insert end {{{font}}}")
|
|
rE(f"label {fsetup}.l.gui.fcodeL -text {{{_('Gcode Font')}}} -anchor e")
|
|
rE(f"ComboBox {fsetup}.l.gui.fcode -modifycmd font_changed -textvariable codeFont -bd 1 -width 10 -justify right -editable 0")
|
|
populate_gcode_fonts()
|
|
rE(f"label {fsetup}.l.gui.coneL -text {{{_('Cone Size')}}} -anchor e")
|
|
rE(f"ComboBox {fsetup}.l.gui.cone -modifycmd cone_size_changed -textvariable coneSize -bd 1 -width 10 -justify right -editable 0")
|
|
rE(f"{fsetup}.l.gui.cone configure -values {{0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0}}")
|
|
rE(f"label {fsetup}.l.gui.popLocationL -text {{{_('Popup Location')}}} -width 14 -anchor e")
|
|
rE(f"ComboBox {fsetup}.l.gui.popLocation -textvariable popLocation -bd 1 -width 10 -justify right -editable 0")
|
|
rE(f"{fsetup}.l.gui.popLocation configure -values {{pointer gui center screen center}}")
|
|
rE(f"label {fsetup}.l.gui.zoomL -text {{{_('Table Zoom')}}} -anchor e")
|
|
rE(f"spinbox {fsetup}.l.gui.zoom -width 10 -justify right -wrap true -from 0.1 -to 10.0 -increment 0.1 -format %0.1f")
|
|
rE(f"{fsetup}.l.gui.zoom configure -validate key -vcmd {{{valspin} %W flt 1 %P %s}}")
|
|
spinBoxes.append(f"{fsetup}.l.gui.zoom")
|
|
rE(f"label {fsetup}.l.gui.jogspeedL -width 14 -text {{{_('Jog Speed')}}} -anchor e")
|
|
rE(f"spinbox {fsetup}.l.gui.jogspeed -width 10 -justify right -wrap true")
|
|
minJogSpeed = int(float(rE(f"{ftop}.jogspeed.s cget -from")) * vars.max_speed.get() * 60)
|
|
rE(f"{fsetup}.l.gui.jogspeed configure -from {minJogSpeed} -to {vars.max_speed.get() * 60} -increment 1")
|
|
rE(f"{fsetup}.l.gui.jogspeed configure -format %0.0f")
|
|
rE(f"{fsetup}.l.gui.jogspeed configure -validate key -vcmd {{{valspin} %W int 0 %P %s}}")
|
|
spinBoxes.append(f"{fsetup}.l.gui.jogspeed")
|
|
rE(f"label {fsetup}.l.gui.crspeedL -width 14 -text {{{_('Cut Rec Speed %')}}} -anchor e")
|
|
rE(f"spinbox {fsetup}.l.gui.crspeed -width 10 -justify right -wrap true")
|
|
minJogSpeed = int(float(rE(f"{ftop}.jogspeed.s cget -from")) * vars.max_speed.get() * 60)
|
|
rE(f"{fsetup}.l.gui.crspeed configure -from 1 -to 100 -increment 1")
|
|
rE(f"{fsetup}.l.gui.crspeed configure -format %0.0f")
|
|
rE(f"{fsetup}.l.gui.crspeed configure -validate key -vcmd {{{valspin} %W int 0 %P %s}}")
|
|
spinBoxes.append(f"{fsetup}.l.gui.crspeed")
|
|
rE(f"label {fsetup}.l.gui.matdefaultL -text {{{_('Default Material')}}} -width 14 -anchor e")
|
|
rE(f"ComboBox {fsetup}.l.gui.matdefault -modifycmd change_default_material -textvariable matDefault -bd 1 -width 10 -justify right -editable 0")
|
|
rE(f"label {fsetup}.l.gui.kbShortcutsL -text {{{_('Use KB Shortcuts')}}} -anchor e")
|
|
rE(f"checkbutton {fsetup}.l.gui.kbShortcuts -variable kbShortcuts -command kb_shortcuts_changed -width 2 -anchor w -indicatoron 0")
|
|
rE(f"label {fsetup}.l.gui.useVirtKBL -text {{{_('Use Virtual KB')}}} -anchor e")
|
|
rE(f"checkbutton {fsetup}.l.gui.useVirtKB -variable useVirtKB -command virtual_kb_changed -width 2 -anchor w -indicatoron 0")
|
|
# populate gui frame
|
|
rE(f"grid {fsetup}.l.gui.closedialogL -column 0 -row 0 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fsetup}.l.gui.closedialog -column 1 -row 0 -sticky e -padx {{0 4}} -pady {{4 0}}")
|
|
rE(f"grid {fsetup}.l.gui.wsizeL -column 0 -row 1 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fsetup}.l.gui.wsize -column 1 -row 1 -sticky ew -padx {{0 4}} -pady {{4 0}}")
|
|
rE(f"grid {fsetup}.l.gui.orientL -column 0 -row 2 -sticky e -padx {{4 0}} -pady {{4 0}}")
|
|
rE(f"grid {fsetup}.l.gui.orient -column 1 -row 2 -sticky ew -padx {{0 4}} -pady {{4 0}}")
|
|
rE(f"grid {fsetup}.l.gui.fsizeL -column 0 -row 3 -sticky e -padx {{4 0}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.fsize -column 1 -row 3 -sticky ew -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.fguiL -column 0 -row 4 -sticky e -padx {{4 0}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.fgui -column 1 -row 4 -sticky ew -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.fcodeL -column 0 -row 5 -sticky e -padx {{4 0}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.fcode -column 1 -row 5 -sticky ew -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.coneL -column 0 -row 6 -sticky e -padx {{4 0}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.cone -column 1 -row 6 -sticky ew -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.popLocationL -column 0 -row 7 -sticky e -padx {{4 0}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.popLocation -column 1 -row 7 -sticky ew -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.zoomL -column 0 -row 8 -sticky e -padx {{4 0}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.zoom -column 1 -row 8 -sticky ew -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.jogspeedL -column 0 -row 9 -sticky e -padx {{4 0}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.jogspeed -column 1 -row 9 -sticky ew -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.crspeedL -column 0 -row 10 -sticky e -padx {{4 0}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.crspeed -column 1 -row 10 -sticky ew -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.matdefaultL -column 0 -row 11 -sticky e -padx {{4 0}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.matdefault -column 1 -row 11 -sticky ew -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.kbShortcutsL -column 0 -row 12 -sticky e -padx {{4 0}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.kbShortcuts -column 1 -row 12 -sticky e -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.useVirtKBL -column 0 -row 13 -sticky e -padx {{4 0}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.gui.useVirtKB -column 1 -row 13 -sticky e -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid columnconfigure {fsetup}.l.gui 0 -weight 1")
|
|
# plasmac frame
|
|
rE(f"labelframe {fsetup}.l.plasmac -text {{{_('Plasmac')}}} -relief groove")
|
|
rE(f"label {fsetup}.l.plasmac.modeL -width 13 -text {{{_('Mode')}}} -anchor e")
|
|
rE(f"ComboBox {fsetup}.l.plasmac.mode -modifycmd mode_changed -textvariable plasmacMode -bd 1 -width 12 -justify right -editable 0")
|
|
rE(f"{fsetup}.l.plasmac.mode configure -values {{0 1 2}}")
|
|
# populate plasmac frame
|
|
rE(f"grid {fsetup}.l.plasmac.modeL -column 0 -row 0 -sticky e -padx {{4 0}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.l.plasmac.mode -column 1 -row 0 -sticky ew -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid columnconfigure {fsetup}.l.plasmac 0 -weight 1")
|
|
#populate left panel
|
|
rE(f"grid {fsetup}.l.gui -column 0 -row 0 -sticky new")
|
|
rE(f"grid {fsetup}.l.plasmac -column 0 -row 2 -sticky new")
|
|
|
|
# middle panel for utilities
|
|
rE(f"frame {fsetup}.m")
|
|
# utilities frame
|
|
rE(f"labelframe {fsetup}.m.utilities -text {{{_('Utilities')}}} -relief groove")
|
|
rE(f"button {fsetup}.m.utilities.offsets -command set_peripheral_offsets -text {{{_('Peripheral Offsets')}}} -padx 0")
|
|
# populate utilities frame
|
|
rE(f"grid {fsetup}.m.utilities.offsets -column 0 -row 0 -sticky new -padx 4 -pady {{0 4}}")
|
|
rE(f"grid columnconfigure {fsetup}.m.utilities 0 -weight 1")
|
|
# color frame
|
|
rE(f"labelframe {fsetup}.m.colors -text {{{_('Colors')}}} -relief groove")
|
|
rE(f"label {fsetup}.m.colors.foreL -width 13 -text {{{_('Foreground')}}} -anchor e")
|
|
rE(f"button {fsetup}.m.colors.fore -command {{color_set fore}}")
|
|
rE(f"label {fsetup}.m.colors.backL -width 13 -text {{{_('Background')}}} -anchor e")
|
|
rE(f"button {fsetup}.m.colors.back -command {{color_set back}}")
|
|
rE(f"label {fsetup}.m.colors.disableL -width 13 -text {{{_('Disabled')}}} -anchor e")
|
|
rE(f"button {fsetup}.m.colors.disable -command {{color_set disable}}")
|
|
rE(f"label {fsetup}.m.colors.activeL -width 13 -text {{{_('Active')}}} -anchor e")
|
|
rE(f"button {fsetup}.m.colors.active -command {{color_set active}}")
|
|
rE(f"label {fsetup}.m.colors.warnL -width 13 -text {{{_('Warning')}}} -anchor e")
|
|
rE(f"button {fsetup}.m.colors.warn -command {{color_set warn}}")
|
|
rE(f"label {fsetup}.m.colors.voltL -width 13 -text {{{_('Arc Voltage')}}} -anchor e")
|
|
rE(f"button {fsetup}.m.colors.volt -command {{color_set volt}}")
|
|
rE(f"label {fsetup}.m.colors.arcL -width 13 -text {{{_('Arc OK')}}} -anchor e")
|
|
rE(f"button {fsetup}.m.colors.arc -command {{color_set arc}}")
|
|
rE(f"label {fsetup}.m.colors.ledL -width 13 -text {{{_('LED''s')}}} -anchor e")
|
|
rE(f"button {fsetup}.m.colors.led -command {{color_set led}}")
|
|
rE(f"label {fsetup}.m.colors.troughL -width 13 -text {{{_('Slider Trough')}}} -anchor e")
|
|
rE(f"button {fsetup}.m.colors.trough -command {{color_set trough}}")
|
|
# populate color frame
|
|
rE(f"grid {fsetup}.m.colors.foreL -column 0 -row 0 -sticky e -padx 4 -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.fore -column 1 -row 0 -sticky e -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.backL -column 0 -row 1 -sticky e -padx 4 -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.back -column 1 -row 1 -sticky e -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.disableL -column 0 -row 2 -sticky e -padx 4 -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.disable -column 1 -row 2 -sticky e -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.activeL -column 0 -row 3 -sticky e -padx 4 -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.active -column 1 -row 3 -sticky e -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.warnL -column 0 -row 4 -sticky e -padx 4 -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.warn -column 1 -row 4 -sticky e -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.voltL -column 0 -row 5 -sticky e -padx 4 -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.volt -column 1 -row 5 -sticky e -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.arcL -column 0 -row 6 -sticky e -padx 4 -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.arc -column 1 -row 6 -sticky e -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.ledL -column 0 -row 7 -sticky e -padx 4 -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.led -column 1 -row 7 -sticky e -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.troughL -column 0 -row 8 -sticky e -padx 4 -pady {{4 4}}")
|
|
rE(f"grid {fsetup}.m.colors.trough -column 1 -row 8 -sticky e -padx {{0 4}} -pady {{4 4}}")
|
|
rE(f"grid columnconfigure {fsetup}.m.colors 0 -weight 1")
|
|
# populate middle panel
|
|
rE(f"grid {fsetup}.m.utilities -column 0 -row 0 -sticky new")
|
|
rE(f"grid {fsetup}.m.colors -column 0 -row 1 -sticky new")
|
|
|
|
# right panel for text entries
|
|
rE(f"frame {fsetup}.r")
|
|
# frame for torch enable
|
|
rE(f"labelframe {fsetup}.r.torch -text {{{_('Torch Enable Text')}}} -relief groove")
|
|
rE(f"label {fsetup}.r.torch.blankL -width 2 -anchor w")
|
|
rE(f"label {fsetup}.r.torch.enabledL -text {{{_('Enabled')}}} -width 14 -anchor w")
|
|
rE(f"label {fsetup}.r.torch.disabledL -text {{{_('Disabled')}}} -width 14 -anchor w")
|
|
rE(f"entry {fsetup}.r.torch.enabled -bd 1 -width 14")
|
|
rE(f"entry {fsetup}.r.torch.disabled -bd 1 -width 14")
|
|
rE(f"grid {fsetup}.r.torch.blankL -column 0 -row 0 -sticky nw -padx {{4 0}}")
|
|
rE(f"grid {fsetup}.r.torch.enabledL -column 1 -row 0 -sticky nw -padx {{4 0}}")
|
|
rE(f"grid {fsetup}.r.torch.disabledL -column 2 -row 0 -sticky nw -padx 4")
|
|
rE(f"grid {fsetup}.r.torch.enabled -column 1 -row 1 -sticky nw -padx {{4 0}} -pady {{0 4}}")
|
|
rE(f"grid {fsetup}.r.torch.disabled -column 2 -row 1 -sticky nw -padx 4 -pady {{0 4}}")
|
|
# frame for user buttons
|
|
rE(f"labelframe {fsetup}.r.ubuttons -text {{{_('User Buttons')}}} -relief groove")
|
|
# canvas for scrolling
|
|
rE(f"canvas {fsetup}.r.ubuttons.canvas")
|
|
rE(f"frame {fsetup}.r.ubuttons.canvas.frame")
|
|
rE(f"scrollbar {fsetup}.r.ubuttons.yscroll -orient vertical -command {{{fsetup}.r.ubuttons.canvas yview}}")
|
|
rE(f"scrollbar {fsetup}.r.ubuttons.xscroll -orient horizontal -command {{{fsetup}.r.ubuttons.canvas xview}}")
|
|
rE(f"{fsetup}.r.ubuttons.canvas create window {{0 0}} -anchor nw -window {{{fsetup}.r.ubuttons.canvas.frame}}")
|
|
rE(f"{fsetup}.r.ubuttons.canvas configure -xscrollcommand {{{fsetup}.r.ubuttons.xscroll set}}")
|
|
rE(f"{fsetup}.r.ubuttons.canvas configure -yscrollcommand {{{fsetup}.r.ubuttons.yscroll set}}")
|
|
# layout the canvas
|
|
rE(f"grid {fsetup}.r.ubuttons.yscroll -column 0 -row 0 -sticky nsw -padx {{4 0}}")
|
|
rE(f"grid {fsetup}.r.ubuttons.canvas -column 1 -row 0 -sticky nsew")
|
|
rE(f"grid {fsetup}.r.ubuttons.xscroll -column 1 -row 1 -sticky new -padx {{4 0}}")
|
|
rE(f"grid columnconfigure {fsetup}.r.ubuttons 1 -weight 1")
|
|
rE(f"grid rowconfigure {fsetup}.r.ubuttons 0 -weight 1")
|
|
# user button widgets
|
|
rE(f"label {fsetup}.r.ubuttons.canvas.frame.numL -text # -width 2 -anchor e")
|
|
rE(f"label {fsetup}.r.ubuttons.canvas.frame.nameL -text {{{_('Name')}}} -width 14 -anchor w")
|
|
rE(f"label {fsetup}.r.ubuttons.canvas.frame.codeL -text {{{_('Code')}}} -width 60 -anchor w")
|
|
for n in range(1, maxUserButtons + 1):
|
|
rE(f"label {fsetup}.r.ubuttons.canvas.frame.num{n} -text {str(n)} -anchor e")
|
|
rE(f"entry {fsetup}.r.ubuttons.canvas.frame.name{n} -bd 1 -width 14")
|
|
rE(f"entry {fsetup}.r.ubuttons.canvas.frame.code{n} -bd 1")
|
|
rE(f"grid {fsetup}.r.ubuttons.canvas.frame.num{n} -column 0 -row {n} -sticky ne -padx {{4 0}} -pady {{0 4}}")
|
|
rE(f"grid {fsetup}.r.ubuttons.canvas.frame.name{n} -column 1 -row {n} -sticky nw -padx {{4 0}} -pady {{0 4}}")
|
|
rE(f"grid {fsetup}.r.ubuttons.canvas.frame.code{n} -column 2 -row {n} -sticky new -padx {{4 4}} -pady {{0 4}}")
|
|
rE(f"grid {fsetup}.r.ubuttons.canvas.frame.numL -column 0 -row 0 -sticky ne -padx {{4 0}}")
|
|
rE(f"grid {fsetup}.r.ubuttons.canvas.frame.nameL -column 1 -row 0 -sticky nw -padx {{4 0}}")
|
|
rE(f"grid {fsetup}.r.ubuttons.canvas.frame.codeL -column 2 -row 0 -sticky nw -padx {{4 4}}")
|
|
rE(f"grid columnconfigure {fsetup}.r.ubuttons.canvas.frame 2 -weight 1")
|
|
# frame for shutdown message
|
|
rE(f"labelframe {fsetup}.r.shutdown -text {{{_('Shutdown Message')}}} -relief groove")
|
|
rE(f"entry {fsetup}.r.shutdown.msg -textvariable closeText -bd 1 -width 54")
|
|
rE(f"grid {fsetup}.r.shutdown.msg -column 0 -row 0 -sticky new -padx 4 -pady {{0 4}}")
|
|
rE(f"grid columnconfigure {fsetup}.r.shutdown 0 -weight 1")
|
|
# populate right panel
|
|
rE(f"grid {fsetup}.r.torch -column 0 -row 0 -sticky new")
|
|
rE(f"grid {fsetup}.r.ubuttons -column 0 -row 1 -sticky nsew")
|
|
rE(f"grid {fsetup}.r.shutdown -column 0 -row 2 -sticky new")
|
|
rE(f"grid rowconfigure {fsetup}.r 1 -weight 1")
|
|
rE(f"grid columnconfigure {fsetup}.r 0 -weight 1")
|
|
|
|
# populate settings frame
|
|
populate_settings_frame()
|
|
|
|
# bottom pane widgets
|
|
# configure
|
|
rE(f"{ft} configure -relief flat -pady 0 -bd 0")
|
|
rE(f"{ft}.sb configure -bd 1")
|
|
rE(f"{ft}.text configure -width 10 -height 6 -borderwidth 1 -relief sunken")
|
|
# populate
|
|
rE(f"grid {fleds} -column 0 -row 1 -padx {{2 0}} -pady {{0 2}} -sticky nsew")
|
|
rE(f"grid {ft} -padx {{0 2}} -pady {{0 2}}")
|
|
rE(f"pack {ft}.sb -fill y -side left -padx 1")
|
|
rE(f"pack {ft}.text -fill both -expand 1 -side left -pady 0")
|
|
|
|
# new conversational frames
|
|
rE('frame .toolconv -borderwidth 1 -relief raised')
|
|
rE('frame .fconv -relief flat')
|
|
|
|
# change jog slider resolution
|
|
rE('.pane.top.jogspeed.s configure -resolution 0.00001')
|
|
|
|
# remove all tooltips
|
|
rE('DynamicHelp::delete ftabs_manual.axes.axisx')
|
|
for w in toolButtons:
|
|
rE(f"DynamicHelp::delete .toolbar.{w}")
|
|
|
|
# populate run panel
|
|
populate_run_panel()
|
|
|
|
|
|
##############################################################################
|
|
# INITIALIZATION #
|
|
##############################################################################
|
|
# reinitialize notifications to keep them on top of new widgets
|
|
notify_list = []
|
|
for nw in rE(f"winfo children {notifications}").split():
|
|
for n in rE(f"winfo children {nw}").split():
|
|
if n[-5:] == 'label':
|
|
img = rE(f"{n} cget -image").rsplit('_',1)[1]
|
|
elif n[-6:] == 'label2':
|
|
txt = rE(f"{n} cget -text")
|
|
notify_list.append([img, txt])
|
|
notifications.clear()
|
|
notifications.__init__(root_window)
|
|
if notify_list:
|
|
for n in notify_list:
|
|
notifications.add(n[0], n[1])
|
|
update_title()
|
|
o.show_overlay = False
|
|
o.colors['overlay_alpha'] = 0
|
|
pVars.jogMultiplier.set(1)
|
|
hal.set_p('plasmac.mode', f"{pVars.plasmacMode.get()}")
|
|
hal.set_p('plasmac.torch-enable', '0')
|
|
hal.set_p('plasmac.height-override', f"{torchHeight:0.3f}")
|
|
hal.set_p('plasmac.thc-feed-rate', f"{thcFeedRate}")
|
|
pVars.previewLarge.set(False)
|
|
pVars.laserText.set(_('Laser'))
|
|
value = getPrefs(PREF, 'ENABLE_OPTIONS', 'THC auto', False, bool)
|
|
pVars.thcAuto.set(value)
|
|
value = getPrefs(PREF, 'ENABLE_OPTIONS', 'THC enable', False, bool)
|
|
pVars.thcEnable.set(value)
|
|
hal.set_p('plasmac.thc-enable', str(value))
|
|
value = getPrefs(PREF, 'ENABLE_OPTIONS', 'Corner lock enable', False, bool)
|
|
pVars.cornerEnable.set(value)
|
|
hal.set_p('plasmac.cornerlock-enable', str(value))
|
|
value = getPrefs(PREF, 'ENABLE_OPTIONS', 'Void lock enable', False, bool)
|
|
pVars.voidEnable.set(value)
|
|
hal.set_p('plasmac.voidlock-enable', str(value))
|
|
value = getPrefs(PREF, 'ENABLE_OPTIONS', 'Use auto volts', False, bool)
|
|
pVars.autoVolts.set(value)
|
|
hal.set_p('plasmac.use-auto-volts', str(value))
|
|
value = getPrefs(PREF, 'ENABLE_OPTIONS', 'Ohmic probe enable', False, bool)
|
|
pVars.ohmicEnable.set(value)
|
|
hal.set_p('plasmac.ohmic-probe-enable', str(value))
|
|
value = getPrefs(PREF, 'GUI_OPTIONS', 'Jog speed', int(vars.max_speed.get() * 60 * 0.5), int)
|
|
rE(f"{fsetup}.l.gui.jogspeed set {value}")
|
|
restoreSetup['jogSpeed'] = value
|
|
set_jog_slider(value / vars.max_speed.get() / 60)
|
|
value = getPrefs(PREF, 'GUI_OPTIONS', 'Exit warning text', '', str)
|
|
pVars.closeText.set(value)
|
|
restoreSetup['closeText'] = value
|
|
value = getPrefs(PREF, 'GUI_OPTIONS', 'Exit warning', True, bool)
|
|
pVars.closeDialog.set(value)
|
|
restoreSetup['closeDialog'] = value
|
|
root_window.protocol('WM_DELETE_WINDOW', close_window)
|
|
value = getPrefs(PREF, 'GUI_OPTIONS', 'Preview cone size', 0.5, float)
|
|
pVars.coneSize.set(value)
|
|
restoreSetup['coneSize'] = value
|
|
cone_size_changed()
|
|
value = getPrefs(PREF, 'GUI_OPTIONS', 'Popup location', 'pointer', str)
|
|
pVars.popLocation.set(value)
|
|
restoreSetup['popLocation'] = value
|
|
value = getPrefs(PREF, 'GUI_OPTIONS', 'Table zoom', 1, float)
|
|
rE(f"{fsetup}.l.gui.zoom set {value}")
|
|
restoreSetup['tableZoom'] = value
|
|
value = getPrefs(PREF, 'GUI_OPTIONS','Cut recovery speed %', 20, int)
|
|
restoreSetup['crPercent'] = value
|
|
rE(f"{fsetup}.l.gui.crspeed set {value}")
|
|
# check for valid onboard virtual keyboard
|
|
vkb_validate()
|
|
if vkbData['valid']:
|
|
value = getPrefs(PREF, 'GUI_OPTIONS', 'Use soft keyboard', False, bool)
|
|
else:
|
|
value = False
|
|
pVars.useVirtKB.set(value)
|
|
restoreSetup['useVirtKB'] = value
|
|
if vkbData['valid']:
|
|
virtual_kb_changed()
|
|
# disable keyboard shortcuts if virtual keyboard enabled
|
|
if value:
|
|
value = False
|
|
rE(f"{fsetup}.l.gui.kbShortcutsL configure -state disabled")
|
|
rE(f"{fsetup}.l.gui.kbShortcuts configure -state disabled")
|
|
else:
|
|
value = getPrefs(PREF, 'GUI_OPTIONS', 'Use keyboard shortcuts', True, bool)
|
|
pVars.kbShortcuts.set(value)
|
|
restoreSetup['kbShortcuts'] = value
|
|
keyboard_bindings(value)
|
|
statDivisor = 1000 if unitsPerMm == 1 else 1
|
|
statSuffix = 'M' if unitsPerMm == 1 else '"'
|
|
unitSuffix = 'mm' if unitsPerMm == 1 else 'in'
|
|
# we bring in some ints as floats so we can read QtPlasmaC statistics
|
|
pVars.lengthS.set(getPrefs(PREF, 'STATISTICS', 'Cut length', 0, float))
|
|
pVars.lengthJ.set(f"0.00{statSuffix}")
|
|
pVars.lengthT.set(f"{pVars.lengthS.get() / statDivisor:0.2f}{statSuffix}")
|
|
pVars.pierceS.set(getPrefs(PREF, 'STATISTICS', 'Pierce count', 0, int))
|
|
pVars.pierceJ.set('0')
|
|
pVars.pierceT.set(pVars.pierceS.get())
|
|
pVars.rapidS.set(int(getPrefs(PREF, 'STATISTICS', 'Rapid time', 0, float)))
|
|
pVars.rapidJ.set('00:00:00')
|
|
pVars.rapidT.set(secs_to_hms(pVars.rapidS.get()))
|
|
pVars.probeS.set(int(getPrefs(PREF, 'STATISTICS', 'Probe time', 0, float)))
|
|
pVars.probeJ.set('00:00:00')
|
|
pVars.probeT.set(secs_to_hms(pVars.probeS.get()))
|
|
pVars.torchS.set(int(getPrefs(PREF, 'STATISTICS', 'Torch on time', 0, float)))
|
|
pVars.torchJ.set('00:00:00')
|
|
pVars.torchT.set(secs_to_hms(pVars.torchS.get()))
|
|
pVars.pausedS.set(int(getPrefs(PREF, 'STATISTICS', 'Paused time', 0, float)))
|
|
pVars.pausedJ.set('00:00:00')
|
|
pVars.pausedT.set(secs_to_hms(pVars.pausedS.get()))
|
|
pVars.cutS.set(int(getPrefs(PREF, 'STATISTICS', 'Cut time', 0, float)))
|
|
pVars.cutJ.set('00:00:00')
|
|
pVars.cutT.set(secs_to_hms(pVars.cutS.get()))
|
|
pVars.runS.set(int(getPrefs(PREF, 'STATISTICS', 'Program run time', 0, float)))
|
|
pVars.runJ.set('00:00:00')
|
|
pVars.runT.set(secs_to_hms(pVars.runS.get()))
|
|
laser_button_enable()
|
|
offset_probe_setup()
|
|
for widget in wLeds:
|
|
rE(f"{widget} configure -state disabled")
|
|
widgetValues[widget] = 0
|
|
load_param_clicked()
|
|
mode_changed()
|
|
font_changed()
|
|
ucFile = os.path.join(configPath, 'user_commands.py')
|
|
if os.path.isfile(ucFile):
|
|
exec(compile(open(ucFile, "rb").read(), ucFile, 'exec'))
|
|
else:
|
|
firstRun = 'invalid'
|
|
title = _('LOAD ERROR')
|
|
msg0 = _('Cannot find valid library directory')
|
|
msg1 = _('plasmac2 extensions are not loaded')
|
|
sys.exit()
|
|
|
|
|
|
##############################################################################
|
|
# HAL SETUP - CALLED DIRECTLY FROM AXIS ONCE AT STARTUP #
|
|
##############################################################################
|
|
def user_hal_pins():
|
|
global firstRun, previewSize, halPinList, serial, comPorts
|
|
global materialChangePin, materialChangeNumberPin, materialChangeTimeoutPin
|
|
global materialReloadPin, materialTempPin
|
|
if firstRun == 'invalid':
|
|
return
|
|
# create new hal pins
|
|
comp.newpin('arc-voltage', hal.HAL_FLOAT, hal.HAL_IN)
|
|
comp.newpin('led-arc-ok', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('led-torch', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('led-thc-enabled', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('led-ohmic', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('led-float', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('led-breakaway', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('led-thc-active', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('led-up', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('led-down', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('led-corner-locked', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('led-void-locked', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('refresh', hal.HAL_S32, hal.HAL_IN)
|
|
comp.newpin('material-change-number', hal.HAL_S32, hal.HAL_IN)
|
|
comp.newpin('material-change', hal.HAL_S32, hal.HAL_IN)
|
|
comp.newpin('material-change-timeout', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('material-reload', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('material-temp', hal.HAL_S32, hal.HAL_IN)
|
|
comp.newpin('cut-type', hal.HAL_S32, hal.HAL_IN)
|
|
comp.newpin('thc-enable-out', hal.HAL_BIT, hal.HAL_OUT)
|
|
comp.newpin('program-is-idle', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('laser-on', hal.HAL_BIT, hal.HAL_OUT)
|
|
comp.newpin('preview-tab', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('development', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('conv-block-loaded', hal.HAL_BIT, hal.HAL_IN)
|
|
comp.newpin('offset-set-probe', hal.HAL_BIT, hal.HAL_OUT)
|
|
comp.newpin('offset-set-scribe', hal.HAL_BIT, hal.HAL_OUT)
|
|
ext_hal_create()
|
|
# create some new signals and connect pins
|
|
hal_data = [[0,'plasmac:arc-voltage-out','plasmac.arc-voltage-out','axisui.arc-voltage'],\
|
|
[1,'plasmac:axis-x-min-limit','ini.x.min_limit','plasmac.axis-x-min-limit'],\
|
|
[2,'plasmac:axis-x-max-limit','ini.x.max_limit','plasmac.axis-x-max-limit'],\
|
|
[3,'plasmac:axis-y-min-limit','ini.y.min_limit','plasmac.axis-y-min-limit'],\
|
|
[4,'plasmac:axis-y-max-limit','ini.y.max_limit','plasmac.axis-y-max-limit'],\
|
|
[5,'plasmac:axis-z-min-limit','ini.z.min_limit','plasmac.axis-z-min-limit'],\
|
|
[6,'plasmac:axis-z-max-limit','ini.z.max_limit','plasmac.axis-z-max-limit'],\
|
|
[7,'plasmac:arc-ok-out','plasmac.arc-ok-out','axisui.led-arc-ok'],\
|
|
[8,'plasmac:thc-enabled','plasmac.thc-enabled','axisui.led-thc-enabled'],\
|
|
[9,'plasmac:thc-active','plasmac.thc-active','axisui.led-thc-active'],\
|
|
[10,'plasmac:led-up','plasmac.led-up','axisui.led-up'],\
|
|
[11,'plasmac:led-down','plasmac.led-down','axisui.led-down'],\
|
|
[11,'plasmac:cornerlock-is-locked','plasmac.cornerlock-is-locked','axisui.led-corner-locked'],\
|
|
[13,'plasmac:voidlock-is-locked','plasmac.voidlock-is-locked','axisui.led-void-locked'],\
|
|
[14,'plasmac:offset-set-probe','plasmac.offset-set-probe','axisui.offset-set-probe'],\
|
|
[15,'plasmac:offset-set-scribe','plasmac.offset-set-scribe','axisui.offset-set-scribe'],\
|
|
]
|
|
for line in hal_data:
|
|
if line[0] < 7:
|
|
hal.new_sig(line[1],hal.HAL_FLOAT)
|
|
else:
|
|
hal.new_sig(line[1],hal.HAL_BIT)
|
|
hal.connect(line[2],line[1])
|
|
hal.connect(line[3],line[1])
|
|
# connect pins to some existing signals
|
|
hal.connect('axisui.led-ohmic','plasmac:ohmic-probe-out')
|
|
hal.connect('axisui.led-float','plasmac:float-switch-out')
|
|
hal.connect('axisui.led-breakaway','plasmac:breakaway-switch-out')
|
|
hal.connect('axisui.led-torch','plasmac:torch-on')
|
|
# connect laser-on if it exists
|
|
laser = False
|
|
for signal in hal.get_info_signals():
|
|
if signal['NAME'] == 'plasmac:laser-on':
|
|
laser = True
|
|
break
|
|
if laser:
|
|
hal.connect('axisui.laser-on','plasmac:laser-on')
|
|
# initialize halpin variables
|
|
materialChangePin = comp['material-change']
|
|
materialChangeNumberPin = comp['material-change-number']
|
|
materialChangeTimeoutPin = comp['material-change-timeout']
|
|
materialReloadPin = comp['material-reload']
|
|
materialTempPin = comp['material-temp']
|
|
# do user button setup after hal pin creation
|
|
halPinList = hal.get_info_pins()
|
|
user_button_setup()
|
|
# load materials when setup is complete
|
|
load_materials(-1, False)
|
|
# start powermax comms if valid port
|
|
if pmPort:
|
|
global pmx485
|
|
for parm in ['compStatus','commsError','connected','exists','meshMode']:
|
|
pmx485[parm] = False
|
|
for parm in ['compArcTime','compFault','commsTimer','retryTimer','oldPressure']:
|
|
pmx485[parm] = 0.0
|
|
for parm in ['compMinC','compMaxC','compMinP','compMaxP']:
|
|
pmx485[parm] = 0.0
|
|
for parm in ['oldMode']:
|
|
pmx485[parm] = 0
|
|
try:
|
|
import serial
|
|
import serial.tools.list_ports as comPorts
|
|
if pmx485_check(pmPort):
|
|
pmx485_startup(pmPort)
|
|
except:
|
|
comPorts = None
|
|
msg0 = _('python3-serial cannot be found')
|
|
msg1 = _('Install python3-serial or linuxcnc-dev')
|
|
notifications.add('error', f"{msg0}\n{msg1}")
|
|
# check preferences for a file to load
|
|
addRecent = True
|
|
openFile = getPrefs(PREF, 'GUI_OPTIONS','Open file', '', str)
|
|
loadLast = True if openFile == 'last' else False
|
|
if loadLast:
|
|
openFile = ap.getpref('recentfiles', [], repr).pop(0) if len(ap.getpref('recentfiles', [], repr)) else None
|
|
addRecent = False
|
|
elif openFile:
|
|
openFile = os.path.join(open_directory,openFile)
|
|
# load the file
|
|
if openFile:
|
|
if os.path.exists(openFile):
|
|
open_file_guts(openFile, False, addRecent)
|
|
commands.set_view_z()
|
|
else:
|
|
msg0 = _('does not exist')
|
|
notifications.add('error', f"'{os.path.realpath(openFile)}' {msg0}\n")
|
|
# run users custom hal commands if it exists
|
|
uhFile = os.path.join(configPath, 'user_hal.py')
|
|
if os.path.isfile(uhFile):
|
|
exec(compile(open(uhFile, "rb").read(), uhFile, 'exec'))
|
|
# setup shortcuts help
|
|
install_kb_text(root_window)
|
|
install_kp_text(root_window)
|
|
# setup the about text
|
|
rE('.about.message configure -height 14')
|
|
text = f"\n\nplasmac2 extensions v{VER}\nCopyright (C) 2022, 2023\nPhillip A Carter and Gregory D Carl"
|
|
rE('.about.message configure -state normal')
|
|
rE(f".about.message insert end {{{text}}}")
|
|
rE('.about.message configure -state disabled')
|
|
previewSize = {'w':rE(f"winfo width {tabs_preview}"), 'h':rE(f"winfo height {tabs_preview}")}
|
|
|
|
|
|
##############################################################################
|
|
# PERIODIC FUNCTION - CALLED FROM AXIS EVERY CYCLE #
|
|
##############################################################################
|
|
def user_live_update():
|
|
global firstRun, upFile
|
|
# don't do any updates until first run is complete.
|
|
if firstRun:
|
|
# test this last command in axis to see if we are loaded
|
|
if widgets.numbers_text.bind() and extHalPins:
|
|
upFile = os.path.join(configPath, 'user_periodic.py')
|
|
# setup the colors
|
|
color_change()
|
|
# set the pierce offset hal pins
|
|
comp['x-pierce-offset'] = widgetValues['.param.c2.pierce.x-pierce-offset']
|
|
comp['y-pierce-offset'] = widgetValues['.param.c2.pierce.y-pierce-offset']
|
|
firstRun = None
|
|
return
|
|
if orientStart:
|
|
return
|
|
global isIdle, isIdleHomed, isPaused, isRunning
|
|
global runState, pausedState, relPos, previewSize
|
|
global probeTimer, laserButtonState
|
|
global framingState, activeFunction
|
|
global currentTool, pmx485, homeInProgress
|
|
global materialChangePin, materialChangeNumberPin
|
|
global materialReloadPin, materialTempPin
|
|
global materialChangeTimeoutPin, dryRun
|
|
# set machine state variables
|
|
isIdle = s.task_state == linuxcnc.STATE_ON and s.interp_state == linuxcnc.INTERP_IDLE
|
|
isIdleHomed = isIdle and all_homed()
|
|
isPaused = s.task_state == linuxcnc.STATE_ON and s.paused
|
|
isRunning = not s.interp_state == linuxcnc.INTERP_IDLE and not s.paused
|
|
# check external hal pins
|
|
ext_hal_watch()
|
|
# set current x and y relative positions
|
|
relPos['X'] = round(s.position[0] - s.g5x_offset[0] - s.g92_offset[0], 6)
|
|
relPos['Y'] = round(s.position[1] - s.g5x_offset[1] - s.g92_offset[1], 6)
|
|
# set display units
|
|
if o.canon:
|
|
if 200 in o.canon.state.gcodes:
|
|
vars.metric.set(0)
|
|
else:
|
|
vars.metric.set(1)
|
|
else:
|
|
vars.metric.set(s.linear_units == 1)
|
|
# program has started
|
|
if running() and not runState:
|
|
runState = True
|
|
clear_job_stats()
|
|
# program has ended
|
|
elif not running() and runState:
|
|
runState = False
|
|
save_total_stats()
|
|
# reset single-cut
|
|
if singleCut['G91']:
|
|
ensure_mode(linuxcnc.MODE_MDI)
|
|
c.mdi('G91')
|
|
# reset moving pierce
|
|
for pin in ['creep-speed', 'creep-speed-distance', 'cut-height-delay', 'gouge-speed', \
|
|
'gouge-speed-distance', 'pierce-end-height', 'pierce-motion-delay', 'pierce-type']:
|
|
hal.set_p(f'plasmac.{pin}', '0')
|
|
# override standard tool info
|
|
if current_tool.id != currentTool:
|
|
currentTool = current_tool.id
|
|
if currentTool < 1:
|
|
tool = 'Torch'
|
|
elif currentTool == 1:
|
|
tool = 'Scribe'
|
|
vupdate(pVars.plasmatool, f"Tool: {tool}")
|
|
# update status leds
|
|
for widget in wLeds:
|
|
tmp, item = widget.rsplit('.',1)
|
|
if comp[item] != widgetValues[widget]:
|
|
widgetValues[widget] = comp[item]
|
|
if comp[item] == 1:
|
|
rE(f"{widget} configure -state normal")
|
|
else:
|
|
rE(f"{widget} configure -state disabled")
|
|
# update arc voltage
|
|
rE(f"{fplasma}.arc-voltage configure -text {comp['arc-voltage']:3.0f}v")
|
|
# halpin toggle
|
|
for button in togglePins:
|
|
if hal.get_value(togglePins[button]['pin']) != togglePins[button]['state']:
|
|
set_toggle_pins(button)
|
|
# halpin pulse
|
|
for button in pulsePins:
|
|
# set button color for pulse-halpin buttons
|
|
if hal.get_value(pulsePins[button]['pin']) != pulsePins[button]['state']:
|
|
pulsePins[button]['state'] = hal.get_value(pulsePins[button]['pin'])
|
|
if pulsePins[button]['state']:
|
|
rE(f"{fbuttons}.button{button} configure -bg {colorActive}")
|
|
else:
|
|
rE(f"{fbuttons}.button{button} configure -bg {colorBack}")
|
|
# reset a consumable change
|
|
if (hal.get_value('plasmac.consumable-change') or hal.get_value('plasmac.consumable-change')) and \
|
|
(hal.get_value('axisui.abort') or not s.paused):
|
|
hal.set_p('plasmac.consumable-change', '0')
|
|
hal.set_p('plasmac.x-offset', '0')
|
|
hal.set_p('plasmac.y-offset', '0')
|
|
hal.set_p('plasmac.xy-feed-rate', '0')
|
|
rE(f"{fbuttons}.button{cChangeButton} configure -bg {colorBack}")
|
|
activeFunction = False
|
|
# abort a manual cut
|
|
if manualCut['state'] and not hal.get_value('spindle.0.on'):
|
|
manualCut['state'] = False
|
|
vars.jog_speed.set(manualCut['feed'])
|
|
rE(f".pane.top.jogspeed.s configure -state normal")
|
|
save_total_stats()
|
|
# show cut recovery tab
|
|
if s.paused and 'manual' in rE(f"{ftabs} pages"):
|
|
rE(f"{ftabs} delete manual 0")
|
|
rE(f"{ftabs} delete mdi 0")
|
|
rE(f"{ftabs} insert end cutrecs")
|
|
rE(f"{ftabs} raise cutrecs")
|
|
rE(f"{ftabs} itemconfigure cutrecs -text {{{_('Cut Recovery')}}} -background {colorBack} -foreground {colorFore}")
|
|
# hide cut recovery tab
|
|
if not s.paused and 'cutrecs' in rE(f"{ftabs} pages") and \
|
|
(not hal.get_value('plasmac.paused-motion') or \
|
|
hal.get_value('axisui.abort') or \
|
|
s.task_state == linuxcnc.STATE_ESTOP):
|
|
rE(f"{ftabs} delete cutrecs 0")
|
|
rE(f"{ftabs} insert end manual")
|
|
rE(f"{ftabs} insert end mdi")
|
|
rE(f"{ftabs} raise manual")
|
|
rE(f"{ftabs} itemconfigure manual -text {{{_('Manual')}}} -background {colorBack} -foreground {colorFore}")
|
|
rE(f"{ftabs} itemconfigure mdi -text {{{_('MDI')}}} -background {colorBack} -foreground {colorFore}")
|
|
# if resumed and component has completed a cut recovery then cancel cut recovey
|
|
if not s.paused and not hal.get_value('plasmac.cut-recovering') and hal.get_value('plasmac.cut-recovery'):
|
|
cut_rec_cancel()
|
|
# if consumable change finished then clear offsets
|
|
if hal.get_value('plasmac.state-out') == 26:
|
|
hal.set_p('plasmac.x-offset', '0')
|
|
hal.set_p('plasmac.y-offset', '0')
|
|
# if resumed and laser recovery is active then undo laser offset
|
|
if not s.paused and hal.get_value('plasmac.laser-recovery-state') and hal.get_value('plasmac.laser-recovery-start'):
|
|
hal.set_p('plasmac.laser-recovery-start', '0')
|
|
# reset framing when complete
|
|
if framingState and not hal.get_value('motion.motion-type'):
|
|
comp['laser-on'] = 0
|
|
framingState = False
|
|
activeFunction = False
|
|
live_plotter.clear()
|
|
# dry run button state
|
|
wState = 'disabled' if rE('.toolbar.program_run cget -state') == 'disabled' or not loaded_file else 'normal'
|
|
rE(f"{fbuttons}.dry-run configure -state {wState}")
|
|
# reset after dry run
|
|
if dryRun and isIdle:
|
|
oldX = s.actual_position[0] - dryRun[0]
|
|
oldY = s.actual_position[1] - dryRun[1]
|
|
units = '20' if s.linear_units != 1 else '21'
|
|
ensure_mode(linuxcnc.MODE_MDI)
|
|
c.mdi(f'G{units} G10 L20 P0 X{oldX} Y{oldY}')
|
|
c.wait_complete()
|
|
dryRun = None
|
|
comp['laser-on'] = 0
|
|
hal.set_p('plasmac.dry-run', '0')
|
|
live_plotter.clear()
|
|
# set X0Y0, laser, and offset_setup buttons state
|
|
wState = 'normal' if isIdleHomed else 'disabled'
|
|
rE(f"{fjogf}.zerohome.zeroxy configure -state {wState}")
|
|
rE(f"{fjogf}.zerohome.laser configure -state {wState}")
|
|
rE(f"{fsetup}.m.utilities.offsets configure -state {wState}")
|
|
# set height override buttons state
|
|
wState = 'normal' if isIdle or isPaused or isRunning else 'disabled'
|
|
rE(f"{foverride}.raise configure -state {wState}")
|
|
rE(f"{foverride}.lower configure -state {wState}")
|
|
rE(f"{foverride}.reset configure -state {wState}")
|
|
# set material panel state
|
|
wState = 'normal' if not (isPaused or isRunning) else 'disabled'
|
|
rE(f"{fruns}.material.materials configure -state {wState}")
|
|
rE(f"{fruns}.material.cut-feed-rate configure -state {wState}")
|
|
for child in get_all_children(toolmat):
|
|
rE(f"{child} configure -state {wState}")
|
|
for n in range(1, maxUserButtons + 1):
|
|
if buttonCodes[n]['code']:
|
|
if buttonCodes[n]['code'] == 'ohmic-test':
|
|
if (isIdle or isPaused) and hal.get_value('plasmac.ohmic-probe-enable'):
|
|
rE(f"{fbuttons}.button{n} configure -state normal")
|
|
else:
|
|
rE(f"{fbuttons}.button{n} configure -state disabled")
|
|
elif buttonCodes[n]['code'] == 'cut-type':
|
|
if not isRunning and not isPaused:
|
|
rE(f"{fbuttons}.button{n} configure -state normal")
|
|
else:
|
|
rE(f"{fbuttons}.button{n} configure -state disabled")
|
|
elif buttonCodes[n]['code'] == 'single-cut':
|
|
if isIdleHomed and not activeFunction and str(rE('.toolbar.program_run cget -state')) == 'normal':
|
|
rE(f"{fbuttons}.button{n} configure -state normal")
|
|
else:
|
|
rE(f"{fbuttons}.button{n} configure -state disabled")
|
|
elif buttonCodes[n]['code'] == 'manual-cut':
|
|
if isIdleHomed and not activeFunction and str(rE('.toolbar.program_run cget -state')) == 'normal':
|
|
rE(f"{fbuttons}.button{n} configure -state normal")
|
|
else:
|
|
rE(f"{fbuttons}.button{n} configure -state disabled")
|
|
elif buttonCodes[n]['code'] == 'probe-test':
|
|
if isIdleHomed and (not activeFunction or probeTimer):
|
|
rE(f"{fbuttons}.button{n} configure -state normal")
|
|
else:
|
|
rE(f"{fbuttons}.button{n} configure -state disabled")
|
|
elif buttonCodes[n]['code'] == 'torch-pulse':
|
|
if (isIdleHomed or isPaused) and not activeFunction and hal.get_value('plasmac.torch-enable'):
|
|
rE(f"{fbuttons}.button{n} configure -state normal")
|
|
else:
|
|
rE(f"{fbuttons}.button{n} configure -state disabled")
|
|
elif buttonCodes[n]['code'] == 'change-consumables':
|
|
if isPaused and (not activeFunction or hal.get_value('plasmac.consumable-change')):
|
|
rE(f"{fbuttons}.button{n} configure -state normal")
|
|
else:
|
|
rE(f"{fbuttons}.button{n} configure -state disabled")
|
|
elif buttonCodes[n]['code'] == 'framing':
|
|
if isIdleHomed and not activeFunction:
|
|
rE(f"{fbuttons}.button{n} configure -state normal")
|
|
else:
|
|
rE(f"{fbuttons}.button{n} configure -state disabled")
|
|
elif buttonCodes[n]['code'] == 'load':
|
|
if isIdleHomed and not activeFunction:
|
|
rE(f"{fbuttons}.button{n} configure -state normal")
|
|
else:
|
|
rE(f"{fbuttons}.button{n} configure -state disabled")
|
|
elif buttonCodes[n]['code'] == 'latest-file':
|
|
if isIdleHomed and not activeFunction:
|
|
rE(f"{fbuttons}.button{n} configure -state normal")
|
|
else:
|
|
rE(f"{fbuttons}.button{n} configure -state disabled")
|
|
elif buttonCodes[n]['code'] == 'pulse-halpin':
|
|
if hal.get_value('halui.machine.is-on'):
|
|
rE(f"{fbuttons}.button{n} configure -state normal")
|
|
else:
|
|
rE(f"{fbuttons}.button{n} configure -state disabled")
|
|
elif buttonCodes[n]['code'] == 'toggle-halpin':
|
|
if hal.get_value('halui.machine.is-on'):
|
|
rE(f"{fbuttons}.button{n} configure -state normal")
|
|
else:
|
|
rE(f"{fbuttons}.button{n} configure -state disabled")
|
|
elif 'shell' in buttonCodes[n]['code'][0]:
|
|
if hal.get_value('halui.machine.is-on'):
|
|
rE(f"{fbuttons}.button{n} configure -state normal")
|
|
else:
|
|
rE(f"{fbuttons}.button{n} configure -state disabled")
|
|
else:
|
|
if isIdleHomed and not activeFunction:
|
|
rE(f"{fbuttons}.button{n} configure -state normal")
|
|
else:
|
|
rE(f"{fbuttons}.button{n} configure -state disabled")
|
|
wState = 'normal' if not (isPaused or isRunning) else 'disabled'
|
|
rE(f"{fsetup}.r.ubuttons.canvas.frame.name{n} configure -state {wState}")
|
|
rE(f"{fsetup}.r.ubuttons.canvas.frame.code{n} configure -state {wState}")
|
|
|
|
# material handling
|
|
if materialChangePin != comp['material-change']:
|
|
materialChangePin = comp['material-change']
|
|
material_change_pin_changed(materialChangePin)
|
|
if materialChangeNumberPin != comp['material-change-number']:
|
|
materialChangeNumberPin = comp['material-change-number']
|
|
material_change_number_pin_changed(materialChangeNumberPin)
|
|
if materialChangeTimeoutPin != comp['material-change-timeout']:
|
|
materialChangeTimeoutPin = comp['material-change-timeout']
|
|
material_change_timeout_pin_changed(materialChangeTimeoutPin)
|
|
if materialReloadPin != comp['material-reload']:
|
|
materialReloadPin = comp['material-reload']
|
|
material_reload_pin_changed(materialReloadPin)
|
|
if materialTempPin != comp['material-temp']:
|
|
materialTempPin = comp['material-temp']
|
|
material_temp_pin_changed(materialTempPin)
|
|
# try to show the preview tab if hal pin is set
|
|
if comp['preview-tab']:
|
|
try:
|
|
rE('.pane.top.right raise preview')
|
|
comp['preview-tab'] = 0
|
|
except:
|
|
pass
|
|
# allows user to set a HAL pin to initiate the sequence of:
|
|
# reloading the program
|
|
if comp['refresh'] == 1:
|
|
comp['refresh'] = 2
|
|
commands.reload_file()
|
|
# clearing the live plot
|
|
elif comp['refresh'] == 2:
|
|
comp['refresh'] = 3
|
|
commands.clear_live_plot()
|
|
# rezooming the axis
|
|
elif comp['refresh'] == 3:
|
|
comp['refresh'] = 0
|
|
commands.set_view_z()
|
|
# powermax signals
|
|
if pmx485['exists']:
|
|
if pmx485['compStatus'] != hal.get_value('pmx485.status'):
|
|
pmx485['compStatus'] = hal.get_value('pmx485.status')
|
|
pmx485_status_changed(pmx485['compStatus'])
|
|
if pmx485['compFault'] != hal.get_value('pmx485.fault'):
|
|
pmx485['compFault'] = hal.get_value('pmx485.fault')
|
|
pmx485_fault_changed(pmx485['compFault'])
|
|
if pmx485['compArcTime'] != hal.get_value('pmx485.arcTime'):
|
|
pmx485['compArcTime'] = hal.get_value('pmx485.arcTime')
|
|
pVars.arcT.set(secs_to_hms(pmx485['compArcTime']))
|
|
if pmx485['compMinC'] != hal.get_value('pmx485.current_min'):
|
|
pmx485['compMinC'] = hal.get_value('pmx485.current_min')
|
|
pmx485_min_current_changed()
|
|
if pmx485['compMaxC'] != hal.get_value('pmx485.current_max'):
|
|
pmx485['compMaxC'] = hal.get_value('pmx485.current_max')
|
|
pmx485_max_current_changed()
|
|
if pmx485['compMaxP'] != hal.get_value('pmx485.pressure_max'):
|
|
pmx485['compMaxP'] = hal.get_value('pmx485.pressure_max')
|
|
pmx485_max_pressure_changed()
|
|
if pmx485['commsTimer']:
|
|
pmx485['commsTimer'] -= 0.1
|
|
if pmx485['commsTimer'] <= 0:
|
|
pmx485['commsTimer'] = 0
|
|
pmx485_comms_timeout()
|
|
if pmx485['retryTimer']:
|
|
pmx485['retryTimer'] -= 0.1
|
|
if pmx485['retryTimer'] <= 0:
|
|
pmx485['retryTimer'] = 0
|
|
pmx485_retry_timeout()
|
|
# hide/show override limits checkbox
|
|
if vars.on_any_limit.get() and not rE(f"winfo ismapped {flimitovr}"):
|
|
homeInProgress = False
|
|
for j in range(jointcount):
|
|
if hal.get_value(f"joint.{j}.homing"):
|
|
homeInProgress = True
|
|
break
|
|
if not homeInProgress:
|
|
rE(f"grid {flimitovr} -row 1 -column 0 -columnspan 3 -sticky nsew")
|
|
elif not vars.on_any_limit.get() and rE(f"winfo ismapped {flimitovr}"):
|
|
rE(f"{flimitovr}.button invoke")
|
|
rE(f"grid forget {flimitovr}")
|
|
# hide/show jog inhibit override checkbox
|
|
if rE(f"winfo ismapped {fjogiovr}"):
|
|
if pVars.jogInhibitOvr.get():
|
|
hal.set_p('plasmac.override-jog', '1')
|
|
if not hal.get_value('plasmac.breakaway') and \
|
|
not hal.get_value('plasmac.float-switch') and \
|
|
not hal.get_value('plasmac.ohmic-probe'):
|
|
pVars.jogInhibitOvr.set(False)
|
|
rE(f"grid forget {fjogiovr}")
|
|
else:
|
|
if hal.get_value('plasmac.jog-inhibit'):
|
|
if isIdleHomed:
|
|
rE(f"grid {fjogiovr} -column 0 -row 1 -columnspan 3 -sticky nsew")
|
|
else:
|
|
if not hal.get_value('plasmac.breakaway') and \
|
|
not hal.get_value('plasmac.float-switch') and \
|
|
not hal.get_value('plasmac.ohmic-probe'):
|
|
hal.set_p('plasmac.override-jog', '0')
|
|
# statistics
|
|
if runState or manualCut['state']:
|
|
# cut length
|
|
sNow = int(hal.get_value('plasmac.cut-length') + 0.5)
|
|
if statValues['length'] != sNow:
|
|
if sNow:
|
|
pVars.lengthJ.set(f"{sNow / statDivisor:0.2f}{statSuffix}")
|
|
if hal.get_value('plasmac.torch-enable'):
|
|
pVars.lengthT.set(f"{(sNow + pVars.lengthS.get()) / statDivisor:0.2f}{statSuffix}")
|
|
statValues['length'] = sNow
|
|
# pierce count
|
|
sNow = hal.get_value('plasmac.pierce-count')
|
|
if statValues['pierce'] != sNow:
|
|
if sNow:
|
|
pVars.pierceJ.set(sNow)
|
|
if hal.get_value('plasmac.torch-enable'):
|
|
pVars.pierceT.set(sNow + pVars.pierceS.get())
|
|
statValues['pierce'] = sNow
|
|
# rapid time
|
|
sNow = int(hal.get_value('plasmac.rapid-time') + 0.5)
|
|
if statValues['rapid'] != sNow:
|
|
if sNow:
|
|
pVars.rapidJ.set(secs_to_hms(sNow))
|
|
if hal.get_value('plasmac.torch-enable'):
|
|
pVars.rapidT.set(secs_to_hms(sNow + pVars.rapidS.get()))
|
|
statValues['rapid'] = sNow
|
|
# probe time
|
|
sNow = int(hal.get_value('plasmac.probe-time') + 0.5)
|
|
if statValues['probe'] != sNow:
|
|
if sNow:
|
|
pVars.probeJ.set(secs_to_hms(sNow))
|
|
if hal.get_value('plasmac.torch-enable'):
|
|
pVars.probeT.set(secs_to_hms(sNow + pVars.probeS.get()))
|
|
statValues['probe'] = sNow
|
|
# torch time
|
|
sNow = int(hal.get_value('plasmac.torch-time') + 0.5)
|
|
if statValues['torch'] != sNow:
|
|
if sNow:
|
|
pVars.torchJ.set(secs_to_hms(sNow))
|
|
if hal.get_value('plasmac.torch-enable'):
|
|
pVars.torchT.set(secs_to_hms(sNow + pVars.torchS.get()))
|
|
statValues['torch'] = sNow
|
|
# cut time
|
|
sNow = int(hal.get_value('plasmac.cut-time') + 0.5)
|
|
if statValues['cut'] != sNow:
|
|
if sNow:
|
|
pVars.cutJ.set(secs_to_hms(sNow))
|
|
if hal.get_value('plasmac.torch-enable'):
|
|
pVars.cutT.set(secs_to_hms(sNow + pVars.cutS.get()))
|
|
statValues['cut'] = sNow
|
|
# paused time
|
|
sNow = int(hal.get_value('plasmac.paused-time') + 0.5)
|
|
if statValues['paused'] != sNow:
|
|
if sNow:
|
|
pVars.pausedJ.set(secs_to_hms(sNow))
|
|
if hal.get_value('plasmac.torch-enable'):
|
|
pVars.pausedT.set(secs_to_hms(sNow + pVars.pausedS.get()))
|
|
statValues['paused'] = sNow
|
|
# run time
|
|
sNow = int(hal.get_value('plasmac.run-time') + 0.5)
|
|
if statValues['run'] != sNow:
|
|
if sNow:
|
|
pVars.runJ.set(secs_to_hms(sNow))
|
|
if hal.get_value('plasmac.torch-enable'):
|
|
pVars.runT.set(secs_to_hms(sNow + pVars.runS.get()))
|
|
statValues['run'] = sNow
|
|
# set table view zoom if window resized
|
|
if get_view_type() == 't' and (previewSize['w'] != rE(f"winfo width {tabs_preview}") or previewSize['h'] != rE(f"winfo height {tabs_preview}")):
|
|
previewSize = {'w':rE(f"winfo width {tabs_preview}"), 'h':rE(f"winfo height {tabs_preview}")}
|
|
root_window.update_idletasks()
|
|
commands.set_view_t()
|
|
# show/hide scrollbars for user buttons setup
|
|
if int(rE(f"winfo ismapped {fsetup}")):
|
|
if int(rE(f"winfo width {fsetup}.r.ubuttons.canvas.frame")) > \
|
|
int(rE(f"winfo width {fsetup}.r")) - \
|
|
(20 * int(rE(f"winfo ismapped {fsetup}.r.ubuttons.yscroll"))):
|
|
if not int(rE(f"winfo ismapped {fsetup}.r.ubuttons.xscroll")):
|
|
rE(f"grid {fsetup}.r.ubuttons.xscroll -column 1 -row 1 -sticky new -padx {{4 0}}")
|
|
else:
|
|
if int(rE(f"winfo ismapped {fsetup}.r.ubuttons.xscroll")):
|
|
rE(f"grid forget {fsetup}.r.ubuttons.xscroll")
|
|
if int(rE(f"winfo height {fsetup}.r.ubuttons.canvas.frame")) > \
|
|
int(rE(f"winfo height {fsetup}.r.ubuttons")) - \
|
|
(int(pVars.fontSize.get()) * 2 + 16 * int(rE(f"winfo ismapped {fsetup}.r.ubuttons.xscroll"))):
|
|
if not int(rE(f"winfo ismapped {fsetup}.r.ubuttons.yscroll")):
|
|
rE(f"grid {fsetup}.r.ubuttons.yscroll -column 0 -row 0 -sticky nsw -padx {{4 0}}")
|
|
else:
|
|
if int(rE(f"winfo ismapped {fsetup}.r.ubuttons.yscroll")):
|
|
rE(f"grid forget {fsetup}.r.ubuttons.yscroll")
|
|
cbbox = rE(f"{fsetup}.r.ubuttons.canvas bbox all")
|
|
rE(f"{fsetup}.r.ubuttons.canvas configure -scrollregion {{{cbbox}}}")
|
|
# show/hide virtual keyboard for materials
|
|
if str(rE('focus'))[:15] == f"{fruns}.material.":
|
|
if pVars.useVirtKB.get() and not vkbData['visible']:
|
|
vkb_show('numpad')
|
|
else:
|
|
if vkbData['visible'] and not vkbData['required']:
|
|
vkb_hide()
|
|
# resize manual tab
|
|
ttWidth = int(rE(f"winfo width {fjogf}.zerohome.home")) + int(rE(f"winfo width {fjogf}.zerohome.zero")) * 3 + 18
|
|
rE(f".pane.top.tabs configure -width {ttWidth}")
|
|
# start powermax comms if a valid port exists and it is not yet started
|
|
if pmPort and not hal.component_exists('pmx485') and pmx485_check(pmPort, True):
|
|
pmx485_startup(pmPort)
|
|
# run users custom periodic commands if it exists
|
|
if os.path.isfile(upFile):
|
|
exec(open(upFile).read())
|
|
o.tkRedraw()
|