''' conversational.py Copyright (C) 2019, 2020, 2021, 2022 Phillip A Carter Copyright (C) 2020, 2021, 2022 Gregory D Carl 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. ''' import os, sys import gettext import tkinter as tk from tkinter import ttk from tkinter.filedialog import asksaveasfilename from importlib import reload from shutil import copy as COPY import conv_settings as CONVSET import conv_line as CONVLINE import conv_circle as CONVCIRC import conv_ellipse as CONVELLI import conv_triangle as CONVTRIA import conv_rectangle as CONVRECT import conv_polygon as CONVPOLY import conv_bolt as CONVBOLT import conv_slot as CONVSLOT import conv_star as CONVSTAR import conv_gusset as CONVGUST import conv_sector as CONVSECT import conv_block as CONVBLCK for f in sys.path: if '/lib/python' in f: if '/usr' in f: localeDir = 'usr/share/locale' else: localeDir = os.path.join(f"{f.split('/lib')[0]}",'share','locale') break gettext.install("linuxcnc", localedir=localeDir) class Conv(tk.Tk): def __init__(self, convFirstRun, root, toolFrame, convFrame, combobox, \ imagePath, tmpPath, pVars, unitsPerMm, comp, prefs, getprefs, \ putprefs, fileOpener, wcs_rotation, conv_toggle, color_change, \ plasmacPopUp, o): self.r = root self.rE = root.tk.eval self.toolFrame = toolFrame self.convFrame = convFrame self.unitsPerMm = unitsPerMm self.prefs = prefs self.getPrefs = getprefs self.putPrefs = putprefs self.comp = comp self.fileOpener = fileOpener self.wcs_rotation = wcs_rotation self.pVars = pVars self.conv_toggle = conv_toggle self.plasmacPopUp = plasmacPopUp self.o = o self.shapeLen = {'x':None, 'y':None} self.combobox = combobox self.fTmp = os.path.join(tmpPath, 'temp.ngc') self.fNgc = os.path.join(tmpPath, 'shape.ngc') self.fNgcBkp = os.path.join(tmpPath, 'backup.ngc') self.fNgcSent = os.path.join(tmpPath, 'sent_shape.ngc') self.filteredBkp = os.path.join(tmpPath, 'filtered_bkp.ngc') self.savedSettings = {'start_pos':None, 'cut_type':None, 'lead_in':None, 'lead_out':None} self.buttonState = {'newC':False, 'saveC':False, 'sendC':False, 'settingsC':False} self.oldConvButton = False self.module = None self.oldModule = None if self.unitsPerMm == 1: smallHole = 32 leadin = 5 preAmble = 'G21 G64P0.25' else: smallHole = 1.25 leadin = 0.2 preAmble = 'G20 G64P0.01' preAmble = f"{preAmble} G40 G49 G80 G90 G92.1 G94 G97" self.xOrigin = 0.000 self.yOrigin = 0.000 if self.comp['development']: reload(CONVSET) CONVSET.load(self, preAmble, leadin, smallHole, preAmble) if convFirstRun or self.comp['development']: self.create_widgets(imagePath) self.show_common_widgets() color_change() self.polyCombo['values'] = (_('CIRCUMSCRIBED'), _('INSCRIBED'), _('SIDE LENGTH')) self.lineCombo['values'] = (_('LINE POINT ~ POINT'), _('LINE BY ANGLE'), _('ARC 3P'),\ _('ARC 2P +RADIUS'), _('ARC ANGLE +RADIUS')) self.addC['command'] = lambda:self.add_shape_to_file() self.undoC['command'] = lambda:self.undo_shape() self.newC['command'] = lambda:self.new_pressed(True) self.saveC['command'] = lambda:self.save_pressed() self.settingsC['command'] = lambda:self.settings_pressed() self.sendC['command'] = lambda:self.send_pressed() for entry in self.entries: #entry.bind('', self.auto_preview) # plays havoc with good error detection #entry.bind('', self.auto_preview, add='+') #entry.bind('', self.auto_preview, add='+') entry.bind('', self.preview, add='+') entry.bind('', self.preview, add='+') for entry in self.buttons: entry.bind('', self.button_key_pressed) self.entry_validation() def start(self, materialFileDict, matIndex, existingFile, g5xIndex, setViewZ): sDiff = 40 + int(self.pVars.fontSize.get()) - 7 for i in range(len(self.convShapes)): self.toolButton[i]['width'] = sDiff self.toolButton[i]['height'] = sDiff self.materials = materialFileDict self.matIndex = matIndex self.existingFile = existingFile self.g5xIndex = g5xIndex self.setViewZ = setViewZ self.previewActive = False self.settingsExited = False self.validShape = False self.invalidLeads = 0 self.ocEntry['state'] = 'disabled' self.undoC['text'] = _('RELOAD') self.addC['state'] = 'disabled' self.newC['state'] = 'normal' self.saveC['state'] = 'disabled' self.sendC['state'] = 'disabled' self.settingsC['state'] = 'normal' self.polyCombo.setvalue('first') self.lineCombo.setvalue('first') self.convLine = {} self.convBlock = [False, False] for m in self.materials: values = [str(m) + ': ' + self.materials[m]['name'] for m in self.materials] self.matCombo['values'] = values self.matCombo.setvalue(f"@{self.matIndex}") longest = max(values, key=len) tmpLabel = tk.Label(text=longest) self.matCombo['listboxwidth'] = tmpLabel.winfo_reqwidth() + 20 if self.oldConvButton: self.toolButton[self.convShapes.index(self.oldConvButton)].select() self.shape_request(self.oldConvButton) else: self.toolButton[0].select() self.shape_request('line') if self.existingFile: if 'shape.ngc' not in self.existingFile: COPY(self.filteredBkp, self.fNgc) COPY(self.filteredBkp, self.fNgcBkp) else: self.new_pressed(False) self.l3Entry.focus() def entry_validation(self): self.vcmd = (self.r.register(self.validate_entries)) for w in self.uInts: w.configure(validate='key', validatecommand=(self.vcmd, 'int', '%P', '%W')) for w in self.sFloats: w.configure(validate='key', validatecommand=(self.vcmd, 'flt', '%P', '%W')) for w in self.uFloats: w.configure(validate='key', validatecommand=(self.vcmd, 'pos', '%P', '%W')) def validate_entries(self, style, value, widget): widget = self.r.nametowidget(widget) # determine the type of circle if self.convButton.get() == 'circle' and (widget == self.dEntry or widget == self.shEntry): circleType = 'circle' elif self.convButton.get() == 'boltcircle' and (widget == self.hdEntry or widget == self.shEntry): circleType = 'boltcircle' else: circleType = None # blank is valid if value == '': if circleType: self.circle_check(circleType, value) return True # period in a int is invalid and more than one period is invalid if ('.' in value and style == 'int') or value.count('.') > 1: return False # a negative in a posfloat or int is invalid and more than one negative is invalid if ('-' in value and (style == 'pos' or style == 'int')) or value.count('-') > 1: return False # cannot do math on "-", ".", or "-." but they are valid if value == '.' or value == '-' or value == '-.': if circleType: self.circle_check(circleType, value) return True # if a float cannot be calculated from value then it is invalid try: v = float(value) except: return False # must be a valid value if circleType: self.circle_check(circleType, value) return True def preview(self, event): # # this stops focus moving to the root when return pressed # self.rE(f"after 5 focus {event.widget}") self.module.preview(self) def auto_preview(self, event): # this stops focus moving to the root when return pressed self.rE(f"after 5 focus {event.widget}") # we have no interest in this list of keys if event.keysym in ['Tab']: return # not enough info for an auto_preview yet if event.widget.get() in ['.','-','-.']: print('return due to . - -.') return # if auto preview is valid if self.previewC['state'] == 'normal' and self.convButton.get() != 'settings': self.module.auto_preview(self) def button_key_pressed(self, event): # dummy function for: # press a button widget via the keyboard spacebar pass def circle_check(self, circleType, dia): self.invalidLeads = 0 try: dia = float(dia) except: dia = 0 # cannot do overcut if large hole, no hole, or external circle if dia >= self.smallHoleDia or dia == 0 or (self.ctbValue.get() == _('EXTERNAL') and circleType == 'circle'): self.ocbValue.set(_('OFF')) self.ocButton['state'] = 'disabled' self.ocEntry['state'] = 'disabled' else: self.ocButton['state'] = 'normal' self.ocEntry['state'] = 'normal' # cannot do leadout if small hole if self.ctbValue.get() == _('INTERNAL') or circleType == 'boltcircle': if dia < self.smallHoleDia: self.loLabel['state'] = 'disabled' self.loEntry['state'] = 'disabled' self.invalidLeads = 2 else: # test for large leadin or leadout try: lIn = float(self.liValue.get()) except: lIn = 0 try: lOut = float(self.loValue.get()) except: lOut = 0 if lIn and lIn > dia / 4: self.loLabel['state'] = 'disabled' self.loEntry['state'] = 'disabled' self.invalidLeads = 2 elif lOut and lOut > dia / 4: self.loLabel['state'] = 'disabled' self.invalidLeads = 1 else: self.loLabel['state'] = 'normal' self.loEntry['state'] = 'normal' self.invalidLeads = 0 else: self.loLabel['state'] = 'normal' self.loEntry['state'] = 'normal' self.invalidLeads = 0 # dialog call from shapes def dialog_show_ok(self, title, text): reply = self.plasmacPopUp('error', title, text).reply return reply def new_pressed(self, buttonPressed): if buttonPressed and (self.saveC['state'] or self.sendC['state'] or self.previewActive): title = _('Unsaved Shape') msg0 = _('You have an unsaved, unsent, or active previewed shape') msg1 = _('If you continue it will be deleted') if not self.plasmacPopUp('yesno', title, f"{msg0}\n\n{msg1}\n").reply: return if self.oldConvButton == 'line': if self.lineCombo.get() == _('LINE POINT ~ POINT'): CONVLINE.set_line_point_to_point(self) elif self.lineCombo.get() == _('LINE BY ANGLE'): CONVLINE.set_line_by_angle(self) elif self.lineCombo.get() == _('ARC 3P'): CONVLINE.set_arc_3_points(self) elif self.lineCombo.get() == _('ARC 2P +RADIUS'): CONVLINE.set_arc_2_points_radius(self) elif self.lineCombo.get() == _('ARC ANGLE +RADIUS'): CONVLINE.set_arc_by_angle_radius(self) with open(self.fNgc, 'w') as outNgc: outNgc.write('(new conversational file)\nM2\n') COPY(self.fNgc, self.fTmp) COPY(self.fNgc, self.fNgcBkp) self.fileOpener(self.fNgc, True, False) self.saveC['state'] = 'disabled' self.sendC['state'] = 'disabled' self.validShape = False self.convLine['xLineStart'] = self.convLine['xLineEnd'] = 0 self.convLine['yLineStart'] = self.convLine['yLineEnd'] = 0 self.coValue.set('') self.roValue.set('') self.preview_button_pressed(False) def save_pressed(self): self.convFrame.unbind_all('') self.convFrame.unbind_all('') title = _('Save Error') with open(self.fNgc, 'r') as inFile: for line in inFile: if '(new conversational file)' in line: msg0 = _('An empty file cannot be saved') self.plasmacPopUp('error', title, msg0) return # self.vkb_show() if we add a virtual keyboard ?????????????????????????? fileTypes = [('G-Code Files', '*.ngc *.nc *.tap'), ('All Files', '*.*')] defaultExt = '.ngc' file = asksaveasfilename(filetypes=fileTypes, defaultextension=defaultExt) if file: COPY(self.fNgc, file) self.saveC['state'] = 'disabled' # self.vkb_show(True) if we add a virtual keyboard ?????????????????????? for entry in self.entries: #entry.bind('', self.auto_preview) # plays havoc with good error detection #entry.bind('', self.auto_preview, add='+') #entry.bind('', self.auto_preview, add='+') entry.bind('', self.preview, add='+') entry.bind('', self.preview, add='+') def settings_pressed(self): self.savedSettings['lead_in'] = self.liValue.get() self.savedSettings['lead_out'] = self.loValue.get() self.savedSettings['start_pos'] = self.spbValue.get() self.savedSettings['cut_type'] = self.ctbValue.get() self.buttonState['newC'] = self.newC['state'] self.buttonState['sendC'] = self.sendC['state'] self.buttonState['saveC'] = self.saveC['state'] self.buttonState['settingsC'] = self.settingsC['state'] self.newC['state'] = 'disabled' self.sendC['state'] = 'disabled' self.saveC['state'] = 'disabled' self.settingsC['state'] = 'disabled' self.clear_widgets() if self.comp['development']: reload(CONVSET) for child in self.toolFrame.winfo_children(): if child.winfo_class() == 'Radiobutton': child['state'] = 'disabled' CONVSET.widgets(self) CONVSET.show(self) def send_pressed(self): COPY(self.fNgc, self.fNgcSent) #COPY(self.fNgc, self.filteredBkp) self.existingFile = self.fNgc self.saveC['state'] = 'disabled' self.sendC['state'] = 'disabled' self.fileOpener(self.fNgc, False, False) self.conv_toggle(0, True) def block_request(self): # may need to add this halpin for wcs rotation on abort etc. # self.convBlockLoaded = self.h.newpin('conv_block_loaded', hal.HAL_BIT, hal.HAL_IN) if not self.settingsExited: if self.previewActive and self.active_shape(): return True title = _('Array Error') with open(self.fNgc) as inFile: for line in inFile: if '(new conversational file)' in line: msg0 = _('An empty file cannot be arrayed, rotated, or scaled') self.plasmacPopUp('error', title, msg0) return True # see if we can do something about NURBS blocks down the track elif 'g5.2' in line.lower() or 'g5.3' in line.lower(): msg0 = _('Cannot scale a GCode NURBS block') self.plasmacPopUp('error', title, msg0) return True elif 'M3' in line or 'm3' in line: break return def shape_request(self, shape): #, material): if shape == 'closer': self.conv_toggle(0) return self.oldModule = self.module if shape == 'block': if self.o.canon is not None: unitsMultiplier = 25.4 if self.unitsPerMm == 1 else 1 self.shapeLen['x'] = (self.o.canon.max_extents[0] - self.o.canon.min_extents[0]) * unitsMultiplier self.shapeLen['y'] = (self.o.canon.max_extents[1] - self.o.canon.min_extents[1]) * unitsMultiplier self.module = CONVBLCK if self.block_request(): self.toolButton[self.convShapes.index(self.oldConvButton)].invoke() return elif shape == 'line': self.module = CONVLINE elif shape == 'circle': self.module = CONVCIRC elif shape == 'ellipse': self.module = CONVELLI elif shape == 'triangle': self.module = CONVTRIA elif shape == 'rectangle': self.module = CONVRECT elif shape == 'polygon': self.module = CONVPOLY elif shape == 'boltcircle': self.module = CONVBOLT elif shape == 'slot': self.module = CONVSLOT elif shape == 'star': self.module = CONVSTAR elif shape == 'gusset': self.module = CONVGUST elif shape == 'sector': self.module = CONVSECT else: return if self.comp['development']: reload(self.module) if not self.settingsExited: if self.previewActive and self.active_shape(): return self.preview_button_pressed(False) self.oldConvButton = shape self.settingsC['state'] = 'normal' self.previewC['state'] = 'normal' self.loLabel['state'] = 'normal' self.loEntry['state'] = 'normal' if self.validShape: self.undoC['state'] = 'normal' self.addC['state'] = 'disabled' self.clear_widgets() self.ocButton.config(relief="raised", bg=self.bBackColor) if self.settingsExited: self.liValue.set(self.savedSettings['lead_in']) self.loValue.set(self.savedSettings['lead_out']) self.spbValue.set(self.savedSettings['start_pos']) self.ctbValue.set(self.savedSettings['cut_type']) else: self.ctbValue.set(_('EXTERNAL')) if self.origin: self.spbValue.set(_('CENTER')) else: self.spbValue.set(_('BTM LEFT')) self.liValue.set(f"{self.leadIn}") self.loValue.set(f"{self.leadOut}") self.module.widgets(self) self.settingsExited = False def preview_button_pressed(self, state): self.previewActive = state if state: self.saveC['state'] = 'disabled' self.sendC['state'] = 'disabled' self.undoC['text'] = _('UNDO') else: if self.validShape: self.saveC['state'] = 'normal' self.sendC['state'] = 'normal' self.undoC['text'] = _('RELOAD') self.addC['state'] = 'disabled' self.setViewZ() def active_shape(self): for child in self.toolFrame.winfo_children(): child.deselect() title = _('Active Preview') msg0 = _('Cannot continue with an active previewed shape') reply = self.plasmacPopUp('warn', title, f"{msg0}\n").reply if self.oldConvButton: self.toolButton[self.convShapes.index(self.oldConvButton)].select() self.module = self.oldModule return reply def restore_buttons(self): self.newC['state'] = self.buttonState['newC'] self.sendC['state'] = self.buttonState['sendC'] self.saveC['state'] = self.buttonState['saveC'] self.settingsC['state'] = self.buttonState['settingsC'] def conv_is_float(self, entry): try: return True, float(entry) except: reply = -1 if entry else 0 return False, reply def conv_is_int(self, entry): try: return True, int(entry) except: reply = -1 if entry else 0 return False, reply def undo_shape(self): if not self.previewActive: title = _('Reload Request') if self.existingFile: name = os.path.basename(self.existingFile) msg0 = _('The original file will be loaded') msg1 = _('If you continue all changes will be deleted') if not self.plasmacPopUp('yesno', title, f"{msg0}:\n\n{name}\n\n{msg1}\n").reply: return(True) else: msg0 = _('An empty file will be loaded') msg1 = _('If you continue all changes will be deleted') if not self.plasmacPopUp('yesno', title, f"{msg0}\n\n{msg1}\n").reply: return(True) if self.existingFile: COPY(self.existingFile, self.fNgcBkp) else: with open(self.fNgcBkp, 'w') as outNgc: outNgc.write('(new conversational file)\nM2\n') self.validShape = False self.previewC['state'] = 'normal' self.undoC['state'] = 'disabled' self.saveC['state'] = 'disabled' self.sendC['state'] = 'disabled' if self.convButton.get() == 'line': if self.previewActive: if self.convLine['addSegment'] > 1: self.convLine['addSegment'] = 1 self.module.line_type_changed(self, True) else: self.convLine['addSegment'] = 0 self.module.line_type_changed(self, False) if self.undoC['text'] == _('RELOAD'): self.convLine['xLineStart'] = 0.000 self.convLine['yLineStart'] = 0.000 self.l1Value.set('0.000') self.l2Value.set('0.000') self.convLine['xLineEnd'] = self.convLine['xLineStart'] self.convLine['yLineEnd'] = self.convLine['yLineStart'] if len(self.convLine['gcodeSave']): self.convLine['gcodeLine'] = self.convLine['gcodeSave'] self.previewActive = False # undo the shape if os.path.exists(self.fNgcBkp): COPY(self.fNgcBkp, self.fNgc) self.fileOpener(self.fNgc, True, False) self.addC['state'] = 'disabled' if not self.validShape: self.undoC['state'] = 'disabled' if not self.convBlock[1]: self.convBlock[0] = False self.preview_button_pressed(False) def add_shape_to_file(self): COPY(self.fNgc, self.fNgcBkp) self.validShape = True self.addC['state'] = 'disabled' self.saveC['state'] = 'normal' self.sendC['state'] = 'normal' self.preview_button_pressed(False) if self.convButton.get() == 'line': self.convLine['convAddSegment'] = self.convLine['gcodeLine'] self.convLine['xLineStart'] = self.convLine['xLineEnd'] self.convLine['yLineStart'] = self.convLine['yLineEnd'] self.l1Value.set(f"{self.convLine['xLineEnd']:0.3f}") self.l2Value.set(f"{self.convLine['yLineEnd']:0.3f}") self.convLine['addSegment'] = 1 self.module.line_type_changed(self, True) self.addC['state'] = 'disabled' self.previewActive = False def clear_widgets(self): for child in self.convFrame.winfo_children(): if not self.settingsExited and isinstance(child, tk.Entry): if child.winfo_name() == str(getattr(self, 'liEntry')).rsplit('.',1)[1]: pass elif child.winfo_name() == str(getattr(self, 'loEntry')).rsplit('.',1)[1]: pass elif child.winfo_name() == str(getattr(self, 'liEntry')).rsplit('.',1)[1]: pass elif child.winfo_name() == str(getattr(self, 'liEntry')).rsplit('.',1)[1]: pass elif child.winfo_name() == str(getattr(self, 'caEntry')).rsplit('.',1)[1]: self.caValue.set('360') elif child.winfo_name() == str(getattr(self, 'cnEntry')).rsplit('.',1)[1]: self.cnValue.set('1') elif child.winfo_name() == str(getattr(self, 'rnEntry')).rsplit('.',1)[1]: self.rnValue.set('1') elif child.winfo_name() == str(getattr(self, 'scEntry')).rsplit('.',1)[1]: self.scValue.set('1.0') elif child.winfo_name() == str(getattr(self, 'ocEntry')).rsplit('.',1)[1]: self.ocValue.set(f"{4 * self.unitsPerMm}") child.grid_remove() self.show_common_widgets() def cut_type_clicked(self, circle=False): if self.ctbValue.get() == _('EXTERNAL'): self.ctbValue.set(_('INTERNAL')) else: self.ctbValue.set(_('EXTERNAL')) if circle: try: dia = float(self.dValue.get()) except: dia = 0 if dia >= self.smallHoleDia or dia == 0 or self.ctbValue.get() == _('EXTERNAL'): self.ocButton.config(relief='raised', bg=self.bBackColor, state='disabled') self.ocEntry['state'] = 'disabled' else: self.ocButton['state'] = 'normal' self.ocEntry['state'] = 'normal' self.module.auto_preview(self) def start_point_clicked(self): if self.spbValue.get() == _('BTM LEFT'): self.spbValue.set(_('CENTER')) else: self.spbValue.set(_('BTM LEFT')) self.module.auto_preview(self) def material_changed(self):#, event): # self.matCombo.selection_clear() self.module.auto_preview(self) def show_common_widgets(self): self.convFrame.rowconfigure(11, weight=1) self.spacer.grid(column=0, row=11, sticky='ns') self.previewC.grid(column=0, row=12, padx=(4,0)) self.addC.grid(column=1, row=12, columnspan=2) self.undoC.grid(column=3, row=12) self.sepline.grid(column=0, row=13, columnspan=4, sticky='ew', pady=8, padx=8) self.newC.grid(column=0, row=14, padx=(4,0), pady=(0,4)) self.saveC.grid(column=1, row=14, padx=(4,0), pady=(0,4)) self.settingsC.grid(column=2, row=14, padx=(4,0), pady=(0,4)) self.sendC.grid(column=3, row=14, padx=(4,0), pady=(0,4)) def create_widgets(self, imagePath): for s in self.toolFrame.pack_slaves(): s.destroy() for s in self.convFrame.grid_slaves(): s.destroy() self.convShapes = ['line','circle','ellipse','triangle','rectangle','polygon',\ 'boltcircle','slot','star','gusset','sector','block','closer'] self.convButton = tk.StringVar() self.toolButton = [] self.images = [] # toolbar buttons for i in range(len(self.convShapes)): self.toolButton.append(tk.Radiobutton(self.toolFrame, text=self.convShapes[i], \ command=lambda i=i: self.shape_request(self.convShapes[i]), anchor='center', \ indicatoron=0, selectcolor='gray60', highlightthickness=0, bd=2, \ variable=self.convButton, value=self.convShapes[i], takefocus=0)) self.images.append(tk.PhotoImage(file = os.path.join(imagePath, self.convShapes[i]) + '.png')) self.toolButton[i]['image'] = self.images[i] self.toolButton[i]['width'] = 40 self.toolButton[i]['height'] = 40 if self.convShapes[i] == 'line': self.toolButton[i].pack(side='left', padx=(2,0), pady=1) elif self.convShapes[i] == 'closer': self.toolButton[i].pack(side='right', padx=(0,2), pady=1) else: self.toolButton[i].pack(side='left', padx=(4,0), pady=1) lLength = 10 eLength = 10 self.matLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('MATERIAL')) self.matCombo = self.combobox(self.convFrame, width=lLength, justify='left', bd=1, editable=False) self.matCombo['modifycmd'] = self.material_changed self.spLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('START')) self.spbValue = tk.StringVar() self.spButton = tk.Button(self.convFrame, width=eLength, textvariable=self.spbValue, padx=1, pady=1) self.ctLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('CUT TYPE')) self.ctbValue = tk.StringVar() self.ctButton = tk.Button(self.convFrame, width=eLength, textvariable=self.ctbValue, padx=1, pady=1) self.xsLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('X ORIGIN')) self.xsValue = tk.StringVar() self.xsEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.xsValue, justify='right', bd=1) self.ysLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('Y ORIGIN')) self.ysValue = tk.StringVar() self.ysEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.ysValue, justify='right', bd=1) self.liLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('LEAD IN')) self.liValue = tk.StringVar() self.liEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.liValue, justify='right', bd=1) self.loLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('LEAD OUT')) self.loValue = tk.StringVar() self.loEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.loValue, justify='right', bd=1) self.polyLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('TYPE')) self.polyCombo = self.combobox(self.convFrame, width=lLength, justify='left', bd=1, editable=False) self.sLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('SIDES')) self.sValue = tk.StringVar() self.sEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.sValue, justify='right', bd=1) self.dLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('DIAMETER')) self.dValue = tk.StringVar() self.dEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.dValue, justify='right', bd=1) self.lLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('LENGTH')) self.lValue = tk.StringVar() self.lEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.lValue, justify='right', bd=1) self.wLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('WIDTH')) self.wValue = tk.StringVar() self.wEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.wValue, justify='right', bd=1) self.hLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('HEIGHT')) self.hValue = tk.StringVar() self.aaLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('A ANGLE')) self.aaValue = tk.StringVar() self.aaEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.aaValue, justify='right', bd=1) self.alLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('a LENGTH')) self.alValue = tk.StringVar() self.alEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.alValue, justify='right', bd=1) self.baLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('B ANGLE')) self.baValue = tk.StringVar() self.baEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.baValue, justify='right', bd=1) self.blLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('b LENGTH')) self.blValue = tk.StringVar() self.blEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.blValue, justify='right', bd=1) self.caLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('C ANGLE')) self.caValue = tk.StringVar() self.caEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.caValue, justify='right', bd=1) self.clLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('c LENGTH')) self.clValue = tk.StringVar() self.clEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.clValue, justify='right', bd=1) self.hEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.hValue, justify='right', bd=1) self.hdLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('HOLE DIA')) self.hdValue = tk.StringVar() self.hdEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.hdValue, justify='right', bd=1) self.hoLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('# HOLES')) self.hoValue = tk.StringVar() self.hoEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.hoValue, justify='right', bd=1) self.bcaLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('CIRCLE ANG')) self.bcaValue = tk.StringVar() self.bcaEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.bcaValue, justify='right', bd=1) self.ocLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('OVERCUT')) self.ocValue = tk.StringVar() self.ocEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.ocValue, justify='right', bd=1) self.ocbValue = tk.StringVar(self.r, _('OFF')) self.ocButton = tk.Button(self.convFrame, width=eLength, textvariable=self.ocbValue, padx=1, pady=1) self.pLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('POINTS')) self.pValue = tk.StringVar() self.pEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.pValue, justify='right', bd=1) self.odLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('OUTER DIA')) self.odValue = tk.StringVar() self.odEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.odValue, justify='right', bd=1) self.idLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('INNER DIA')) self.idValue = tk.StringVar() self.idEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.idValue, justify='right', bd=1) self.rLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('RADIUS')) self.rbValue = tk.StringVar(self.r, _('RADIUS')) self.rButton = tk.Button(self.convFrame, width=eLength, textvariable=self.rbValue, padx=1, pady=1) self.rValue = tk.StringVar() self.rEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.rValue, justify='right', bd=1) self.saLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('SEC ANGLE')) self.saValue = tk.StringVar() self.saEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.saValue, justify='right', bd=1) self.aLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('ANGLE')) self.aValue = tk.StringVar() self.aEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.aValue, justify='right', bd=1) self.r1bValue = tk.StringVar() self.r1Button = tk.Button(self.convFrame, width=eLength, textvariable=self.r1bValue, padx=1, pady=1) self.r1Value = tk.StringVar() self.r1Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.r1Value, justify='right', bd=1) self.r2bValue = tk.StringVar() self.r2Button = tk.Button(self.convFrame, width=eLength, textvariable=self.r2bValue, padx=1, pady=1) self.r2Value = tk.StringVar() self.r2Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.r2Value, justify='right', bd=1) self.r3bValue = tk.StringVar() self.r3Button = tk.Button(self.convFrame, width=eLength, textvariable=self.r3bValue, padx=1, pady=1) self.r3Value = tk.StringVar() self.r3Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.r3Value, justify='right', bd=1) self.r4bValue = tk.StringVar() self.r4Button = tk.Button(self.convFrame, width=eLength, textvariable=self.r4bValue, padx=1, pady=1) self.r4Value = tk.StringVar() self.r4Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.r4Value, justify='right', bd=1) # block self.ccLabel = tk.Label(self.convFrame, width=lLength, text=_('COLUMNS')) self.cnLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('NUMBER')) self.cnValue = tk.StringVar() self.cnEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.cnValue, justify='right', bd=1) self.coLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('OFFSET')) self.coValue = tk.StringVar() self.coEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.coValue, justify='right', bd=1) self.rrLabel = tk.Label(self.convFrame, width=lLength, text=_('ROWS')) self.rnLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('NUMBER')) self.rnValue = tk.StringVar() self.rnEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.rnValue, justify='right', bd=1) self.roLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('OFFSET')) self.roValue = tk.StringVar() self.roEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.roValue, justify='right', bd=1) self.bsLabel = tk.Label(self.convFrame, width=lLength, text=_('SHAPE')) self.scLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('SCALE')) self.scValue = tk.StringVar() self.scEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.scValue, justify='right', bd=1) self.rtLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('ROTATION')) self.rtValue = tk.StringVar() self.rtEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.rtValue, justify='right', bd=1) self.mirror = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('MIRROR')) self.flip = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('FLIP')) self.oLabel = tk.Label(self.convFrame, width=lLength, text=_('ORIGIN OFFSET')) # lines and arcs self.lnLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('TYPE')) self.lineCombo = self.combobox(self.convFrame, width=lLength, justify='left', bd=1, editable=False) self.l1Label = tk.Label(self.convFrame, width=lLength, anchor='e', text='') self.l1Value = tk.StringVar() self.l1Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.l1Value, justify='right', bd=1) self.l2Label = tk.Label(self.convFrame, width=lLength, anchor='e', text='') self.l2Value = tk.StringVar() self.l2Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.l2Value, justify='right', bd=1) self.l3Label = tk.Label(self.convFrame, width=lLength, anchor='e', text='') self.l3Value = tk.StringVar() self.l3Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.l3Value, justify='right', bd=1) self.l4Label = tk.Label(self.convFrame, width=lLength, anchor='e', text='') self.l4Value = tk.StringVar() self.l4Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.l4Value, justify='right', bd=1) self.l5Label = tk.Label(self.convFrame, width=lLength, anchor='e', text='') self.l5Value = tk.StringVar() self.l5Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.l5Value, justify='right', bd=1) self.l6Label = tk.Label(self.convFrame, width=lLength, anchor='e', text='') self.l6Value = tk.StringVar() self.l6Entry = tk.Entry(self.convFrame, width=eLength, textvariable=self.l6Value, justify='right', bd=1) self.g23bValue = tk.StringVar() self.g23Arc = tk.Button(self.convFrame, width=eLength, textvariable=self.g23bValue, padx=1, pady=1) # settings self.preLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('PREAMBLE')) self.preValue = tk.StringVar() self.preEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.preValue, bd=1) self.pstLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('POSTAMBLE')) self.pstValue = tk.StringVar() self.pstEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.pstValue, bd=1) self.llLabel = tk.Label(self.convFrame, width=lLength, text=_('LEAD LENGTHS')) self.shLabel = tk.Label(self.convFrame, width=lLength, text=_('SMALL HOLES')) self.shValue = tk.StringVar() self.shEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.shValue, justify='right', bd=1) self.hsValue = tk.StringVar() self.hsEntry = tk.Entry(self.convFrame, width=eLength, textvariable=self.hsValue, justify='right', bd=1) self.hsLabel = tk.Label(self.convFrame, width=lLength, anchor='e', text=_('SPEED %')) self.pvLabel = tk.Label(self.convFrame, width=lLength, text=_('PREVIEW')) self.saveS = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('SAVE')) self.reloadS = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('RELOAD')) self.exitS = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('EXIT')) # bottom self.previewC = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('PREVIEW')) self.addC = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('ADD')) self.undoC = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('UNDO')) self.newC = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('NEW')) self.saveC = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('SAVE')) self.settingsC = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('SETTINGS')) self.sendC = tk.Button(self.convFrame, width=eLength, padx=1, pady=1, text=_('SEND')) # spacer and separator self.spacer = tk.Label(self.convFrame) self.sepline = ttk.Separator(self.convFrame, orient='horizontal') # get default background color self.bBackColor = self.sendC.cget('bg') # create lists of entries self.uInts = [self.hoEntry, self.sEntry, self.pEntry, self.cnEntry, self.rnEntry] self.sFloats = [self.xsEntry, self.ysEntry, self.aEntry, self.caEntry, \ self.coEntry, self.roEntry, self.rtEntry] self.uFloats = [self.liEntry, self.loEntry, self.dEntry, self.ocEntry, self.hdEntry, \ self.wEntry, self.rEntry, self.saEntry, self.hEntry, self.r1Entry, \ self.r2Entry, self.r3Entry, self.r4Entry, self.lEntry, self.odEntry, \ self.idEntry, self.aaEntry, self.baEntry, self.caEntry, self.alEntry, \ self.blEntry, self.clEntry, self.scEntry, self.shEntry, self.hsEntry, \ self.l1Entry, self.l2Entry, self.l3Entry, self.l4Entry, self.l5Entry, \ self.l6Entry, ] self.entries = [] for entry in self.uInts: self.entries.append(entry) for entry in self.sFloats: self.entries.append(entry) for entry in self.uFloats: self.entries.append(entry) self.buttons = [self.spButton, self.ctButton, self.ocButton, self.rButton, self.r1Button, \ self.r2Button, self.r3Button, self.r4Button, self.mirror, self.flip, \ self.g23Arc, self.saveS, self.reloadS, self.exitS, self.previewC, \ self.addC, self.undoC, self.newC, self.saveC, self.settingsC, self.sendC] for button in self.buttons: button.configure(takefocus=0) self.combos = [self.matCombo, self.polyCombo, self.lineCombo] for combo in self.combos: combo.configure(takefocus=0)