Advertisement
senj0h

k40_whisperer with CLI in dev in progress v0.0

Jun 8th, 2018
264
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 162.72 KB | None | 0 0
  1. #!/usr/bin/python
  2. """
  3.    K40 Whisperer
  4.  
  5.    Copyright (C) <2018>  <Scorch>
  6.    This program is free software: you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation, either version 3 of the License, or
  9.    (at your option) any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  
  19. """
  20. version = '0.19'
  21. title_text = "K40 Whisperer V"+version
  22.  
  23. import sys
  24. from math import *
  25. from egv import egv
  26. from nano_library import K40_CLASS
  27. from dxf import DXF_CLASS
  28. from svg_reader import SVG_READER
  29. from svg_reader import SVG_TEXT_EXCEPTION
  30. from g_code_library import G_Code_Rip
  31. from interpolate import interpolate
  32.  
  33. import inkex
  34. import simplestyle
  35. import simpletransform
  36. import cubicsuperpath
  37. import cspsubdiv
  38. import traceback
  39.  
  40.  
  41. #DEBUG = True
  42. DEBUG = False
  43.  
  44. VERSION = sys.version_info[0]
  45. LOAD_MSG = ""
  46.  
  47. if VERSION == 3:
  48.     from tkinter import *
  49.     from tkinter.filedialog import *
  50.     import tkinter.messagebox
  51.     MAXINT = sys.maxsize
  52.    
  53. else:
  54.     from Tkinter import *
  55.     from tkFileDialog import *
  56.     import tkMessageBox
  57.     MAXINT = sys.maxint
  58.  
  59. if VERSION < 3 and sys.version_info[1] < 6:
  60.     def next(item):
  61.         return item.next()
  62.    
  63. try:
  64.     import psyco
  65.     psyco.full()
  66.     LOAD_MSG = LOAD_MSG+"\nPsyco Loaded\n"
  67. except:
  68.     pass
  69.  
  70. import math
  71. from time import time
  72. import os
  73. import re
  74. import binascii
  75. import getopt
  76. import operator
  77. import webbrowser
  78. from PIL import Image
  79. from PIL import ImageOps
  80. try:
  81.     Image.warnings.simplefilter('ignore', Image.DecompressionBombWarning)
  82. except:
  83.     pass
  84. try:
  85.     from PIL import ImageTk
  86.     from PIL import _imaging
  87. except:
  88.     pass #Don't worry everything will still work
  89.  
  90. QUIET = False
  91.  
  92. class ECoord():
  93.     def __init__(self):
  94.         self.reset()
  95.        
  96.     def reset(self):
  97.         self.image      = None
  98.         self.reset_path()
  99.  
  100.     def reset_path(self):
  101.         self.ecoords    = []
  102.         self.len        = 0
  103.         self.move       = 0
  104.         self.sorted     = False
  105.         self.bounds     = (0,0,0,0)
  106.         self.gcode_time = 0        
  107.  
  108.     def make_ecoords(self,coords,scale=1):
  109.         self.reset()
  110.         self.len  = 0
  111.         self.move = 0
  112.        
  113.         xmax, ymax = -1e10, -1e10
  114.         xmin, ymin =  1e10,  1e10
  115.         self.ecoords=[]
  116.         Acc=.001
  117.         oldx = oldy = -99990.0
  118.         first_stroke = True
  119.         loop=0
  120.         for line in coords:
  121.             XY = line
  122.             x1 = XY[0]*scale
  123.             y1 = XY[1]*scale
  124.             x2 = XY[2]*scale
  125.             y2 = XY[3]*scale
  126.             dxline= x2-x1
  127.             dyline= y2-y1
  128.             len_line=sqrt(dxline*dxline + dyline*dyline)
  129.            
  130.             dx = oldx - x1
  131.             dy = oldy - y1
  132.             dist   = sqrt(dx*dx + dy*dy)
  133.             # check and see if we need to move to a new discontinuous start point
  134.             if (dist > Acc) or first_stroke:
  135.                 loop = loop+1
  136.                 self.ecoords.append([x1,y1,loop])
  137.                 if not first_stroke:
  138.                     self.move = self.move + dist
  139.                 first_stroke = False
  140.                
  141.             self.len = self.len + len_line
  142.             self.ecoords.append([x2,y2,loop])
  143.             oldx, oldy = x2, y2
  144.             xmax=max(xmax,x1,x2)
  145.             ymax=max(ymax,y1,y2)
  146.             xmin=min(xmin,x1,x2)
  147.             ymin=min(ymin,y1,y2)
  148.         self.bounds = (xmin,xmax,ymin,ymax)
  149.  
  150.     def set_ecoords(self,ecoords,data_sorted=False):
  151.         self.ecoords = ecoords
  152.         self.computeEcoordsLen()
  153.         self.data_sorted=data_sorted
  154.  
  155.     def set_image(self,PIL_image):
  156.         self.image = PIL_image
  157.  
  158.     def computeEcoordsLen(self):
  159.         xmax, ymax = -1e10, -1e10
  160.         xmin, ymin =  1e10,  1e10
  161.        
  162.         if self.ecoords == [] :
  163.             return
  164.         on = 0
  165.         move = 0
  166.         time = 0
  167.         for i in range(2,len(self.ecoords)):
  168.             x1 = self.ecoords[i-1][0]
  169.             y1 = self.ecoords[i-1][1]
  170.             x2 = self.ecoords[i][0]
  171.             y2 = self.ecoords[i][1]
  172.             loop      = self.ecoords[i  ][2]
  173.             loop_last = self.ecoords[i-1][2]
  174.            
  175.             xmax=max(xmax,x1,x2)
  176.             ymax=max(ymax,y1,y2)
  177.             xmin=min(xmin,x1,x2)
  178.             ymin=min(ymin,y1,y2)
  179.            
  180.             dx = x2-x1
  181.             dy = y2-y1
  182.             dist = sqrt(dx*dx + dy*dy)
  183.            
  184.             if len(self.ecoords[i]) > 3:
  185.                 feed = self.ecoords[i][3]
  186.                 time = time + dist/feed*60
  187.                
  188.             if loop == loop_last:
  189.                 on   = on + dist
  190.             else:
  191.                 move = move + dist
  192.             #print "on= ",on," move= ",move
  193.         self.bounds = (xmin,xmax,ymin,ymax)
  194.         self.len = on
  195.         self.move = move
  196.         self.gcode_time = time
  197.    
  198.    
  199. ################################################################################
  200. class Application(Frame):
  201.     def __init__(self, master):
  202.         Frame.__init__(self, master)
  203.         self.w = 780
  204.         self.h = 490
  205.         frame = Frame(master, width= self.w, height=self.h)
  206.         self.master = master
  207.         self.x = -1
  208.         self.y = -1
  209.         self.createWidgets()
  210.  
  211.     def resetPath(self):
  212.         self.RengData  = ECoord()
  213.         self.VengData  = ECoord()
  214.         self.VcutData  = ECoord()
  215.         self.GcodeData = ECoord()
  216.         self.SCALE = 1
  217.         self.Design_bounds = (0,0,0,0)
  218.         self.UI_image = None
  219.         #if self.HomeUR.get():
  220.         self.move_head_window_temporary([0.0,0.0])
  221.         #else:
  222.         #    self.move_head_window_temporary([0.0,0.0])
  223.            
  224.         self.pos_offset=[0.0,0.0]
  225.        
  226.     def createWidgets(self):
  227.         self.initComplete = 0
  228.         self.stop=[]
  229.         self.stop.append(False)
  230.        
  231.         self.k40 = None
  232.        
  233.         self.master.bind("<Configure>", self.Master_Configure)
  234.         self.master.bind('<Enter>', self.bindConfigure)
  235.         self.master.bind('<F1>', self.KEY_F1)
  236.         self.master.bind('<F5>', self.KEY_F5)
  237.  
  238.         self.master.bind('<Control-Left>' , self.Move_Left)
  239.         self.master.bind('<Control-Right>', self.Move_Right)
  240.         self.master.bind('<Control-Up>'   , self.Move_Up)
  241.         self.master.bind('<Control-Down>' , self.Move_Down)
  242.  
  243.         self.include_Reng = BooleanVar()
  244.         self.include_Rpth = BooleanVar()
  245.         self.include_Veng = BooleanVar()
  246.         self.include_Vcut = BooleanVar()
  247.         self.include_Gcde = BooleanVar()
  248.         self.include_Time = BooleanVar()
  249.  
  250.         self.advanced = BooleanVar()
  251.        
  252.         self.halftone     = BooleanVar()
  253.         self.mirror       = BooleanVar()
  254.         self.rotate       = BooleanVar()
  255.         self.inputCSYS    = BooleanVar()
  256.         self.HomeUR       = BooleanVar()
  257.         self.engraveUP    = BooleanVar()
  258.         self.init_home    = BooleanVar()
  259.         self.pre_pr_crc   = BooleanVar()
  260.         self.inside_first = BooleanVar()
  261.  
  262.         self.ht_size    = StringVar()
  263.         self.Reng_feed  = StringVar()
  264.         self.Veng_feed  = StringVar()
  265.         self.Vcut_feed  = StringVar()
  266.  
  267.         self.Reng_passes = StringVar()
  268.         self.Veng_passes = StringVar()
  269.         self.Vcut_passes = StringVar()
  270.         self.Gcde_passes = StringVar()
  271.        
  272.        
  273.         self.board_name = StringVar()
  274.         self.units      = StringVar()
  275.         self.jog_step   = StringVar()
  276.         self.rast_step  = StringVar()
  277.         self.funits     = StringVar()
  278.        
  279.  
  280.         self.bezier_M1     = StringVar()
  281.         self.bezier_M2     = StringVar()
  282.         self.bezier_weight = StringVar()
  283.  
  284.         self.LaserXsize = StringVar()
  285.         self.LaserYsize = StringVar()
  286.  
  287.         self.LaserXscale = StringVar()
  288.         self.LaserYscale = StringVar()
  289.  
  290.         self.gotoX = StringVar()
  291.         self.gotoY = StringVar()
  292.  
  293.         self.inkscape_path = StringVar()
  294.         self.t_timeout  = StringVar()
  295.         self.n_timeouts  = StringVar()
  296.        
  297.         self.Reng_time = StringVar()
  298.         self.Veng_time = StringVar()
  299.         self.Vcut_time = StringVar()
  300.         self.Gcde_time = StringVar()
  301.        
  302.         ###########################################################################
  303.         #                         INITILIZE VARIABLES                             #
  304.         #    if you want to change a default setting this is the place to do it   #
  305.         ###########################################################################
  306.         self.include_Reng.set(1)
  307.         self.include_Rpth.set(0)
  308.         self.include_Veng.set(1)
  309.         self.include_Vcut.set(1)
  310.         self.include_Gcde.set(1)
  311.         self.include_Time.set(0)
  312.         self.advanced.set(0)
  313.        
  314.         self.halftone.set(0)
  315.         self.mirror.set(0)
  316.         self.rotate.set(0)
  317.         self.inputCSYS.set(0)
  318.         self.HomeUR.set(0)
  319.         self.engraveUP.set(0)
  320.         self.init_home.set(1)
  321.         self.pre_pr_crc.set(1)
  322.         self.inside_first.set(1)
  323.        
  324.         self.ht_size.set(500)
  325.  
  326.         self.Reng_feed.set("100")
  327.         self.Veng_feed.set("20")
  328.         self.Vcut_feed.set("10")
  329.         self.Reng_passes.set("1")
  330.         self.Veng_passes.set("1")
  331.         self.Vcut_passes.set("1")
  332.         self.Gcde_passes.set("1")
  333.        
  334.        
  335.         self.jog_step.set("10.0")
  336.         self.rast_step.set("0.002")
  337.        
  338.         self.bezier_weight.set("3.5")
  339.         self.bezier_M1.set("2.5")
  340.         self.bezier_M2.set("0.50")
  341.  
  342.         self.bezier_weight_default = float(self.bezier_weight.get())
  343.         self.bezier_M1_default     = float(self.bezier_M1.get())
  344.         self.bezier_M2_default     = float(self.bezier_M2.get())
  345.        
  346.                                        
  347.         self.board_name.set("LASER-M2") # Options are
  348.                                         #    "LASER-M2",
  349.                                         #    "LASER-M1",
  350.                                         #    "LASER-M",
  351.                                         #    "LASER-B2",
  352.                                         #    "LASER-B1",
  353.                                         #    "LASER-B",
  354.                                         #    "LASER-A"
  355.  
  356.  
  357.         self.units.set("mm")            # Options are "in" and "mm"
  358.         self.t_timeout.set("2000")  
  359.         self.n_timeouts.set("30")
  360.  
  361.         self.HOME_DIR    = os.path.expanduser("~")
  362.        
  363.         if not os.path.isdir(self.HOME_DIR):
  364.             self.HOME_DIR = ""
  365.  
  366.         self.DESIGN_FILE = (self.HOME_DIR+"/None")
  367.        
  368.         self.aspect_ratio =  0
  369.         self.segID   = []
  370.        
  371.         self.LaserXsize.set("325")
  372.         self.LaserYsize.set("220")
  373.        
  374.         self.LaserXscale.set("1.000")
  375.         self.LaserYscale.set("1.000")
  376.  
  377.         self.gotoX.set("0.0")
  378.         self.gotoY.set("0.0")
  379.        
  380.         self.laserX    = 0.0
  381.         self.laserY    = 0.0
  382.         self.PlotScale = 1.0
  383.  
  384.         # PAN and ZOOM STUFF
  385.         self.panx = 0
  386.         self.panx = 0
  387.         self.lastx = 0
  388.         self.lasty = 0
  389.         self.move_start_x = 0
  390.         self.move_start_y = 0
  391.  
  392.        
  393.         self.RengData  = ECoord()
  394.         self.VengData  = ECoord()
  395.         self.VcutData  = ECoord()
  396.         self.GcodeData = ECoord()
  397.         self.SCALE = 1
  398.         self.Design_bounds = (0,0,0,0)
  399.         self.UI_image = None
  400.         self.pos_offset=[0.0,0.0]
  401.  
  402.        
  403.         # Derived variables
  404.         if self.units.get() == 'in':
  405.             self.funits.set('in/min')
  406.             self.units_scale = 1.0
  407.         else:
  408.             self.units.set('mm')
  409.             self.funits.set('mm/s')
  410.             self.units_scale = 25.4
  411.        
  412.         self.statusMessage = StringVar()
  413.         self.statusMessage.set("Welcome to K40 Whisperer")
  414.        
  415.        
  416.         self.Reng_time.set("0")
  417.         self.Veng_time.set("0")
  418.         self.Vcut_time.set("0")
  419.         self.Gcde_time.set("0")
  420.        
  421.         ##########################################################################
  422.         ###                     END INITILIZING VARIABLES                      ###
  423.         ##########################################################################
  424.  
  425.         # make a Status Bar
  426.         self.statusbar = Label(self.master, textvariable=self.statusMessage, \
  427.                                    bd=1, relief=SUNKEN , height=1)
  428.         self.statusbar.pack(anchor=SW, fill=X, side=BOTTOM)
  429.        
  430.  
  431.         # Canvas
  432.         lbframe = Frame( self.master )
  433.         self.PreviewCanvas_frame = lbframe
  434.         self.PreviewCanvas = Canvas(lbframe, width=self.w-(220+20), height=self.h-200, background="grey")
  435.         self.PreviewCanvas.pack(side=LEFT, fill=BOTH, expand=1)
  436.         self.PreviewCanvas_frame.place(x=230, y=10)
  437.  
  438.         self.PreviewCanvas.tag_bind('LaserTag',"<1>"              , self.mousePanStart)
  439.         self.PreviewCanvas.tag_bind('LaserTag',"<B1-Motion>"      , self.mousePan)
  440.         self.PreviewCanvas.tag_bind('LaserTag',"<ButtonRelease-1>", self.mousePanStop)
  441.  
  442.         # Left Column #
  443.         self.separator1 = Frame(self.master, height=2, bd=1, relief=SUNKEN)
  444.         self.separator2 = Frame(self.master, height=2, bd=1, relief=SUNKEN)
  445.         self.separator3 = Frame(self.master, height=2, bd=1, relief=SUNKEN)
  446.         self.separator4 = Frame(self.master, height=2, bd=1, relief=SUNKEN)
  447.        
  448.         self.Label_Reng_feed_u = Label(self.master,textvariable=self.funits, anchor=W)
  449.         self.Entry_Reng_feed   = Entry(self.master,width="15")
  450.         self.Entry_Reng_feed.configure(textvariable=self.Reng_feed,justify='center',fg="black")
  451.         self.Reng_feed.trace_variable("w", self.Entry_Reng_feed_Callback)
  452.         self.NormalColor =  self.Entry_Reng_feed.cget('bg')
  453.  
  454.         self.Label_Veng_feed_u = Label(self.master,textvariable=self.funits, anchor=W)
  455.         self.Entry_Veng_feed   = Entry(self.master,width="15")
  456.         self.Entry_Veng_feed.configure(textvariable=self.Veng_feed,justify='center',fg="blue")
  457.         self.Veng_feed.trace_variable("w", self.Entry_Veng_feed_Callback)
  458.         self.NormalColor =  self.Entry_Veng_feed.cget('bg')
  459.  
  460.         self.Label_Vcut_feed_u = Label(self.master,textvariable=self.funits, anchor=W)
  461.         self.Entry_Vcut_feed   = Entry(self.master,width="15")
  462.         self.Entry_Vcut_feed.configure(textvariable=self.Vcut_feed,justify='center',fg="red")
  463.         self.Vcut_feed.trace_variable("w", self.Entry_Vcut_feed_Callback)
  464.         self.NormalColor =  self.Entry_Vcut_feed.cget('bg')
  465.  
  466.         # Buttons
  467.         self.Reng_Button  = Button(self.master,text="Raster Engrave", command=self.Raster_Eng)
  468.         self.Veng_Button  = Button(self.master,text="Vector Engrave", command=self.Vector_Eng)
  469.         self.Vcut_Button  = Button(self.master,text="Vector Cut"    , command=self.Vector_Cut)
  470.         self.Grun_Button  = Button(self.master,text="Run G-Code"    , command=self.Gcode_Cut)
  471.        
  472.         self.Label_Position_Control = Label(self.master,text="Position Controls:", anchor=W)
  473.        
  474.         self.Initialize_Button = Button(self.master,text="Initialize Laser Cutter", command=self.Initialize_Laser)
  475.  
  476.         self.Open_Button       = Button(self.master,text="Open\nDesign File",   command=self.menu_File_Open_Design)
  477.         self.Reload_Button     = Button(self.master,text="Reload\nDesign File", command=self.menu_Reload_Design)
  478.        
  479.         self.Home_Button       = Button(self.master,text="Home",             command=self.Home)
  480.         self.UnLock_Button     = Button(self.master,text="Unlock Rail",     command=self.Unlock)
  481.         self.Stop_Button       = Button(self.master,text="Stop",             command=self.Stop)
  482.  
  483.         try:
  484.             self.left_image  = self.Imaging_Free(Image.open("left.png"),bg=None)
  485.             self.right_image = self.Imaging_Free(Image.open("right.png"),bg=None)
  486.             self.up_image    = self.Imaging_Free(Image.open("up.png"),bg=None)
  487.             self.down_image  = self.Imaging_Free(Image.open("down.png"),bg=None)
  488.            
  489.             self.Right_Button   = Button(self.master,image=self.right_image, command=self.Move_Right)
  490.             self.Left_Button    = Button(self.master,image=self.left_image,  command=self.Move_Left)
  491.             self.Up_Button      = Button(self.master,image=self.up_image,    command=self.Move_Up)
  492.             self.Down_Button    = Button(self.master,image=self.down_image,  command=self.Move_Down)
  493.  
  494.             self.UL_image  = self.Imaging_Free(Image.open("UL.png"),bg=None)
  495.             self.UR_image  = self.Imaging_Free(Image.open("UR.png"),bg=None)
  496.             self.LR_image  = self.Imaging_Free(Image.open("LR.png"),bg=None)
  497.             self.LL_image  = self.Imaging_Free(Image.open("LL.png"),bg=None)
  498.             self.CC_image  = self.Imaging_Free(Image.open("CC.png"),bg=None)
  499.            
  500.             self.UL_Button = Button(self.master,image=self.UL_image, command=self.Move_UL)
  501.             self.UR_Button = Button(self.master,image=self.UR_image, command=self.Move_UR)
  502.             self.LR_Button = Button(self.master,image=self.LR_image, command=self.Move_LR)
  503.             self.LL_Button = Button(self.master,image=self.LL_image, command=self.Move_LL)
  504.             self.CC_Button = Button(self.master,image=self.CC_image, command=self.Move_CC)
  505.            
  506.         except:
  507.             self.Right_Button   = Button(self.master,text=">",          command=self.Move_Right)
  508.             self.Left_Button    = Button(self.master,text="<",          command=self.Move_Left)
  509.             self.Up_Button      = Button(self.master,text="^",          command=self.Move_Up)
  510.             self.Down_Button    = Button(self.master,text="v",          command=self.Move_Down)
  511.  
  512.             self.UL_Button = Button(self.master,text=" ", command=self.Move_UL)
  513.             self.UR_Button = Button(self.master,text=" ", command=self.Move_UR)
  514.             self.LR_Button = Button(self.master,text=" ", command=self.Move_LR)
  515.             self.LL_Button = Button(self.master,text=" ", command=self.Move_LL)
  516.             self.CC_Button = Button(self.master,text=" ", command=self.Move_CC)
  517.  
  518.         self.Label_Step   = Label(self.master,text="Jog Step", anchor=CENTER )
  519.         self.Label_Step_u = Label(self.master,textvariable=self.units, anchor=W)
  520.         self.Entry_Step   = Entry(self.master,width="15")
  521.         self.Entry_Step.configure(textvariable=self.jog_step, justify='center')
  522.         self.jog_step.trace_variable("w", self.Entry_Step_Callback)
  523.  
  524.         ###########################################################################
  525.         self.GoTo_Button    = Button(self.master,text="Move To", command=self.GoTo)
  526.        
  527.         self.Entry_GoToX   = Entry(self.master,width="15",justify='center')
  528.         self.Entry_GoToX.configure(textvariable=self.gotoX)
  529.         self.gotoX.trace_variable("w", self.Entry_GoToX_Callback)
  530.         self.Entry_GoToY   = Entry(self.master,width="15",justify='center')
  531.         self.Entry_GoToY.configure(textvariable=self.gotoY)
  532.         self.gotoY.trace_variable("w", self.Entry_GoToY_Callback)
  533.        
  534.         self.Label_GoToX   = Label(self.master,text="X", anchor=CENTER )
  535.         self.Label_GoToY   = Label(self.master,text="Y", anchor=CENTER )
  536.         ###########################################################################
  537.         # End Left Column #
  538.  
  539.         # Advanced Column     #
  540.         self.separator_vert = Frame(self.master, height=2, bd=1, relief=SUNKEN)
  541.         self.Label_Advanced_column = Label(self.master,text="Advanced Settings",anchor=CENTER)
  542.         self.separator_adv = Frame(self.master, height=2, bd=1, relief=SUNKEN)      
  543.  
  544.         self.Label_Halftone_adv = Label(self.master,text="Halftone (Dither)")
  545.         self.Checkbutton_Halftone_adv = Checkbutton(self.master,text=" ", anchor=W)
  546.         self.Checkbutton_Halftone_adv.configure(variable=self.halftone)
  547.         self.halftone.trace_variable("w", self.menu_View_Refresh_Callback)
  548.  
  549.         self.Label_Mirror_adv = Label(self.master,text="Mirror Design")
  550.         self.Checkbutton_Mirror_adv = Checkbutton(self.master,text=" ", anchor=W)
  551.         self.Checkbutton_Mirror_adv.configure(variable=self.mirror)
  552.         self.mirror.trace_variable("w", self.menu_View_Mirror_Refresh_Callback)
  553.  
  554.         self.Label_Rotate_adv = Label(self.master,text="Rotate Design")
  555.         self.Checkbutton_Rotate_adv = Checkbutton(self.master,text=" ", anchor=W)
  556.         self.Checkbutton_Rotate_adv.configure(variable=self.rotate)
  557.         self.rotate.trace_variable("w", self.menu_View_Mirror_Refresh_Callback)
  558.    
  559.         self.Label_inputCSYS_adv = Label(self.master,text="Use Input CSYS")
  560.         self.Checkbutton_inputCSYS_adv = Checkbutton(self.master,text=" ", anchor=W)
  561.         self.Checkbutton_inputCSYS_adv.configure(variable=self.inputCSYS)
  562.         self.inputCSYS.trace_variable("w", self.menu_View_inputCSYS_Refresh_Callback)
  563.  
  564.         self.Label_Inside_First_adv = Label(self.master,text="Cut Inside First")
  565.         self.Checkbutton_Inside_First_adv = Checkbutton(self.master,text=" ", anchor=W)
  566.         self.Checkbutton_Inside_First_adv.configure(variable=self.inside_first)
  567.         self.inside_first.trace_variable("w", self.menu_Inside_First_Callback)
  568.  
  569.         self.Label_Reng_passes = Label(self.master,text="Raster Eng. Passes")
  570.         self.Entry_Reng_passes   = Entry(self.master,width="15")
  571.         self.Entry_Reng_passes.configure(textvariable=self.Reng_passes,justify='center',fg="black")
  572.         self.Reng_passes.trace_variable("w", self.Entry_Reng_passes_Callback)
  573.         self.NormalColor =  self.Entry_Reng_passes.cget('bg')
  574.  
  575.         self.Label_Veng_passes = Label(self.master,text="Vector Eng. Passes")
  576.         self.Entry_Veng_passes   = Entry(self.master,width="15")
  577.         self.Entry_Veng_passes.configure(textvariable=self.Veng_passes,justify='center',fg="blue")
  578.         self.Veng_passes.trace_variable("w", self.Entry_Veng_passes_Callback)
  579.         self.NormalColor =  self.Entry_Veng_passes.cget('bg')
  580.  
  581.         self.Label_Vcut_passes = Label(self.master,text="Vector Cut Passes")
  582.         self.Entry_Vcut_passes   = Entry(self.master,width="15")
  583.         self.Entry_Vcut_passes.configure(textvariable=self.Vcut_passes,justify='center',fg="red")
  584.         self.Vcut_passes.trace_variable("w", self.Entry_Vcut_passes_Callback)
  585.         self.NormalColor =  self.Entry_Vcut_passes.cget('bg')
  586.  
  587.         self.Label_Gcde_passes = Label(self.master,text="G-Code Passes")
  588.         self.Entry_Gcde_passes   = Entry(self.master,width="15")
  589.         self.Entry_Gcde_passes.configure(textvariable=self.Gcde_passes,justify='center',fg="black")
  590.         self.Gcde_passes.trace_variable("w", self.Entry_Gcde_passes_Callback)
  591.         self.NormalColor =  self.Entry_Gcde_passes.cget('bg')
  592.  
  593.        
  594.         self.Hide_Adv_Button = Button(self.master,text="Hide Advanced", command=self.Hide_Advanced)
  595.        
  596.         # End Right Column #
  597.  
  598.         #GEN Setting Window Entry initializations
  599.         self.Entry_Sspeed    = Entry()
  600.         self.Entry_BoxGap    = Entry()
  601.         self.Entry_ContAngle = Entry()
  602.  
  603.         # Make Menu Bar
  604.         self.menuBar = Menu(self.master, relief = "raised", bd=2)
  605.  
  606.         top_File = Menu(self.menuBar, tearoff=0)
  607.         top_File.add("command", label = "Save Settings File", command = self.menu_File_Save)
  608.         top_File.add("command", label = "Read Settings File", command = self.menu_File_Open_Settings_File)
  609.  
  610.         top_File.add_separator()
  611.         top_File.add("command", label = "Open Design (SVG/DXF/G-Code)"  , command = self.menu_File_Open_Design)
  612.         top_File.add("command", label = "Reload Design"          , command = self.menu_Reload_Design)
  613.  
  614.         if DEBUG:
  615.             top_File.add_separator()
  616.             top_File.add("command", label = "Open EGV File"     , command = self.menu_File_Open_EGV)
  617.  
  618.    
  619.         top_File.add_separator()
  620.         top_File.add("command", label = "Exit"              , command = self.menu_File_Quit)
  621.        
  622.         self.menuBar.add("cascade", label="File", menu=top_File)
  623.  
  624.         #top_Edit = Menu(self.menuBar, tearoff=0)
  625.         #self.menuBar.add("cascade", label="Edit", menu=top_Edit)
  626.  
  627.         top_View = Menu(self.menuBar, tearoff=0)
  628.         top_View.add("command", label = "Refresh   <F5>", command = self.menu_View_Refresh)
  629.         top_View.add_separator()
  630.         top_View.add_checkbutton(label = "Show Raster Image"  ,  variable=self.include_Reng ,command= self.menu_View_Refresh)
  631.         if DEBUG:
  632.             top_View.add_checkbutton(label = "Show Raster Paths"  ,  variable=self.include_Rpth ,command= self.menu_View_Refresh)
  633.         top_View.add_checkbutton(label = "Show Vector Engrave",  variable=self.include_Veng ,command= self.menu_View_Refresh)
  634.         top_View.add_checkbutton(label = "Show Vector Cut"    ,  variable=self.include_Vcut ,command= self.menu_View_Refresh)
  635.         top_View.add_checkbutton(label = "Show G-Code Paths"  ,  variable=self.include_Gcde ,command= self.menu_View_Refresh)
  636.         top_View.add_checkbutton(label = "Show Time Estimates",  variable=self.include_Time ,command= self.menu_View_Refresh)
  637.  
  638.         #top_View.add_separator()
  639.         #top_View.add("command", label = "computeAccurateReng",command= self.computeAccurateReng)
  640.         #top_View.add("command", label = "computeAccurateVeng",command= self.computeAccurateVeng)
  641.         #top_View.add("command", label = "computeAccurateVcut",command= self.computeAccurateVcut)
  642.  
  643.         self.menuBar.add("cascade", label="View", menu=top_View)
  644.  
  645.  
  646.         top_USB = Menu(self.menuBar, tearoff=0)
  647.         top_USB.add("command", label = "Reset USB", command = self.Reset)
  648.         top_USB.add("command", label = "Release USB", command = self.Release_USB)
  649.         top_USB.add("command", label = "Initialize Laser", command = self.Initialize_Laser)
  650.         self.menuBar.add("cascade", label="USB", menu=top_USB)
  651.        
  652.  
  653.         top_Settings = Menu(self.menuBar, tearoff=0)
  654.         top_Settings.add("command", label = "General Settings", command = self.GEN_Settings_Window)
  655.         top_Settings.add("command", label = "Raster Settings",  command = self.RASTER_Settings_Window)
  656.         top_Settings.add_separator()
  657.         top_Settings.add_checkbutton(label = "Advanced Settings", variable=self.advanced ,command= self.menu_View_Refresh)
  658.        
  659.         self.menuBar.add("cascade", label="Settings", menu=top_Settings)
  660.        
  661.         top_Help = Menu(self.menuBar, tearoff=0)
  662.         top_Help.add("command", label = "About (e-mail)", command = self.menu_Help_About)
  663.         top_Help.add("command", label = "Web Page", command = self.menu_Help_Web)
  664.         self.menuBar.add("cascade", label="Help", menu=top_Help)
  665.  
  666.         self.master.config(menu=self.menuBar)
  667.  
  668.         ##########################################################################
  669.         #                  Config File and command line options                  #
  670.         ##########################################################################
  671.         config_file = "k40_whisperer.txt"
  672.         home_config1 = self.HOME_DIR + "/" + config_file
  673.         if ( os.path.isfile(config_file) ):
  674.             self.Open_Settings_File(config_file)
  675.         elif ( os.path.isfile(home_config1) ):
  676.             self.Open_Settings_File(home_config1)
  677.         arguments = len(sys.argv) - 1
  678.         if arguments >=1:
  679.         # read commandline arguments, first
  680.             fullCmdArguments = sys.argv
  681.  
  682.         # - further arguments
  683.             argumentList = fullCmdArguments[1:]
  684.         #opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
  685.             unixOptions = "cghHio:rsnvV"  
  686.             gnuOptions = ["help","go","stop","home","init","open","cut","raster", "vector", "verbose"]  
  687.  
  688.             try:  
  689.                 arguments, values = getopt.getopt(argumentList, unixOptions, gnuOptions)
  690.             except getopt.error as err:  
  691.             # output error, and return with an error code
  692.                 print (str(err))
  693.                 sys.exit(2)
  694.  
  695.             # evaluate given options
  696.             for currentArgument, currentValue in arguments:  
  697.                 if currentArgument in ("-i", "--init"):
  698.                     print ("initializing the laser")
  699.                     self.Initialize_Laser()
  700.                     #sage()
  701.                     #command=self.Initialize_Laser
  702.                 elif currentArgument in ("-H", "--home"):
  703.                     print ("move to the home position")
  704.                     self.Home()
  705.                 elif currentArgument in ("-h", "--help"):
  706.                     print ("CLI arguments are as follows")
  707.                     print ("-g --go     Starts the job with whatever other arguments")
  708.                     print ("-s --stop   Stops the job, doesnt go home, or un initialize")
  709.                     print ("-H --home   Sends the cutting head to the home [0,0] position")
  710.                     print ("-i --init   Initializes the laser, or prints errors if it fails")
  711.                     print ("-o --open   Requires an SVG file to open")
  712.                     print ("-h --help   Prints this dialog")
  713.                     print ("-c --cut    Tell the laser to cut")
  714.                     print ("-r --raster Raster Engrave")
  715.                     print ("-v --vector Vector Engrave")
  716.                     print ("-V          Verbose mode lo U wish.. I guess I could set debug mode")
  717.                     print ("-u --unlock Unlock the print head")
  718.                     print(" ")
  719.                     print("Example Useage: $python k40_whisperer.py -i -H -o c.svg -r ")
  720.        
  721.                 elif currentArgument in ("-o", "--open"):
  722.                     print (("opening an svg (%s)") % (currentValue))
  723.                     self.Open_SVG(currentValue)
  724.                 elif currentArgument in ("-g", "--go"):
  725.                     print ("Start cutting or moving the head")
  726.                     #This option doesn't translate into a direct action like the other functions do.
  727.                 elif currentArgument in ("-s", "--stop"):
  728.                     print ("Stop Cutting")
  729.                     self.Stop()
  730.                 elif currentArgument in ("-u", "--unlock"):
  731.                     print ("unlocked the print head")
  732.                     self.Unlock()
  733.                 elif currentArgument in ("-c", "cut"):
  734.                     print ("cuts the open svg file")
  735.                     self.Vector_Cut()
  736.                 elif currentArgument in ("-r", "--raster"):
  737.                     print ("raster Engraves the opened file")
  738.                     self.Raster_Eng()
  739.                 elif currentArgument in ("-v", "--vector"):
  740.                     print ("Vector Engraves the opend file")
  741.                     self.Vector_Eng()
  742.                 elif currentArgument in ("-V"):
  743.                     print (("Verbose mode lol u wish, well, there is debug mode"))
  744.                     print ("Version 0.19 K40_whisperer source")
  745.                     print ("Version 0.0  K40 CLI source")
  746.  
  747.                 else:
  748.                     print ("FOILED! put in some args if you want CLI mode")
  749.                    
  750.  
  751. ####Original DEV-OPS be liek: close if you have CLI arguments.            
  752. #
  753. #        opts, args = None, None
  754. #        try:
  755. #            opts, args = getopt.getopt(sys.argv[1:], "ho:",["help", "other_option"])
  756. #            print args[1:]
  757. #        except:
  758. #            debug_message('Unable to interpret command line options')
  759. #            sys.exit()
  760. ##        for option, value in opts:
  761. ##            if option in ('-h','--help'):
  762. ##                fmessage(' ')
  763. ##                fmessage('Usage: python .py [-g file]')
  764. ##                fmessage('-o    : unknown other option (also --other_option)')
  765. ##                fmessage('-h    : print this help (also --help)\n')
  766. ##                sys.exit()
  767. ##            if option in ('-o','--other_option'):
  768. ##                pass
  769.  
  770.         ##########################################################################
  771.  
  772. ################################################################################
  773.     def entry_set(self, val2, calc_flag=0, new=0):
  774.         if calc_flag == 0 and new==0:
  775.             try:
  776.                 self.statusbar.configure( bg = 'yellow' )
  777.                 val2.configure( bg = 'yellow' )
  778.                 self.statusMessage.set(" Recalculation required.")
  779.             except:
  780.                 pass
  781.         elif calc_flag == 3:
  782.             try:
  783.                 val2.configure( bg = 'red' )
  784.                 self.statusbar.configure( bg = 'red' )
  785.                 self.statusMessage.set(" Value should be a number. ")
  786.             except:
  787.                 pass
  788.         elif calc_flag == 2:
  789.             try:
  790.                 self.statusbar.configure( bg = 'red' )
  791.                 val2.configure( bg = 'red' )
  792.             except:
  793.                 pass
  794.         elif (calc_flag == 0 or calc_flag == 1) and new==1 :
  795.             try:
  796.                 self.statusbar.configure( bg = 'white' )
  797.                 self.statusMessage.set(" ")
  798.                 val2.configure( bg = 'white' )
  799.             except:
  800.                 pass
  801.         elif (calc_flag == 1) and new==0 :
  802.             try:
  803.                 self.statusbar.configure( bg = 'white' )
  804.                 self.statusMessage.set(" ")
  805.                 val2.configure( bg = 'white' )
  806.             except:
  807.                 pass
  808.  
  809.         elif (calc_flag == 0 or calc_flag == 1) and new==2:
  810.             return 0
  811.         return 1
  812.  
  813. ################################################################################
  814.     def Write_Config_File(self, event):
  815.         config_data = self.WriteConfig()
  816.         config_file = "k40_whisperer.txt"
  817.         configname_full = self.HOME_DIR + "/" + config_file
  818.  
  819.         win_id=self.grab_current()
  820.         if ( os.path.isfile(configname_full) ):
  821.             if not message_ask_ok_cancel("Replace", "Replace Exiting Configuration File?\n"+configname_full):
  822.                 try:
  823.                     win_id.withdraw()
  824.                     win_id.deiconify()
  825.                 except:
  826.                     pass
  827.                 return
  828.         try:
  829.             fout = open(configname_full,'w')
  830.         except:
  831.             self.statusMessage.set("Unable to open file for writing: %s" %(configname_full))
  832.             self.statusbar.configure( bg = 'red' )
  833.             return
  834.         for line in config_data:
  835.             try:
  836.                 fout.write(line+'\n')
  837.             except:
  838.                 fout.write('(skipping line)\n')
  839.         fout.close
  840.         self.statusMessage.set("Configuration File Saved: %s" %(configname_full))
  841.         self.statusbar.configure( bg = 'white' )
  842.         try:
  843.             win_id.withdraw()
  844.             win_id.deiconify()
  845.         except:
  846.             pass
  847.  
  848.     ################################################################################
  849.     def WriteConfig(self):
  850.         global Zero
  851.         header = []
  852.         header.append('( K40 Whisperer Settings: '+version+' )')
  853.         header.append('( by Scorch - 2017 )')
  854.         header.append("(=========================================================)")
  855.         # BOOL
  856.         header.append('(k40_whisperer_set include_Reng  %s )'  %( int(self.include_Reng.get())  ))
  857.         header.append('(k40_whisperer_set include_Veng  %s )'  %( int(self.include_Veng.get())  ))
  858.         header.append('(k40_whisperer_set include_Vcut  %s )'  %( int(self.include_Vcut.get())  ))
  859.         header.append('(k40_whisperer_set include_Gcde  %s )'  %( int(self.include_Gcde.get())  ))
  860.         header.append('(k40_whisperer_set include_Time  %s )'  %( int(self.include_Time.get())  ))
  861.        
  862.         header.append('(k40_whisperer_set halftone      %s )'  %( int(self.halftone.get())      ))
  863.         header.append('(k40_whisperer_set HomeUR        %s )'  %( int(self.HomeUR.get())        ))
  864.         header.append('(k40_whisperer_set inputCSYS     %s )'  %( int(self.inputCSYS.get())     ))
  865.         header.append('(k40_whisperer_set advanced      %s )'  %( int(self.advanced.get())      ))
  866.         header.append('(k40_whisperer_set mirror        %s )'  %( int(self.mirror.get())        ))
  867.         header.append('(k40_whisperer_set rotate        %s )'  %( int(self.rotate.get())        ))
  868.        
  869.         header.append('(k40_whisperer_set engraveUP     %s )'  %( int(self.engraveUP.get())     ))
  870.         header.append('(k40_whisperer_set init_home     %s )'  %( int(self.init_home.get())     ))
  871.         header.append('(k40_whisperer_set pre_pr_crc    %s )'  %( int(self.pre_pr_crc.get())    ))
  872.         header.append('(k40_whisperer_set inside_first  %s )'  %( int(self.inside_first.get())  ))
  873.  
  874.         # STRING.get()
  875.         header.append('(k40_whisperer_set board_name    %s )'  %( self.board_name.get()     ))
  876.         header.append('(k40_whisperer_set units         %s )'  %( self.units.get()          ))
  877.         header.append('(k40_whisperer_set Reng_feed     %s )'  %( self.Reng_feed.get()      ))
  878.         header.append('(k40_whisperer_set Veng_feed     %s )'  %( self.Veng_feed.get()      ))
  879.         header.append('(k40_whisperer_set Vcut_feed     %s )'  %( self.Vcut_feed.get()      ))
  880.         header.append('(k40_whisperer_set jog_step      %s )'  %( self.jog_step.get()       ))
  881.  
  882.         header.append('(k40_whisperer_set Reng_passes   %s )'  %( self.Reng_passes.get()    ))
  883.         header.append('(k40_whisperer_set Veng_passes   %s )'  %( self.Veng_passes.get()    ))
  884.         header.append('(k40_whisperer_set Vcut_passes   %s )'  %( self.Vcut_passes.get()    ))
  885.         header.append('(k40_whisperer_set Gcde_passes   %s )'  %( self.Gcde_passes.get()    ))
  886.  
  887.         header.append('(k40_whisperer_set rast_step     %s )'  %( self.rast_step.get()      ))
  888.         header.append('(k40_whisperer_set ht_size       %s )'  %( self.ht_size.get()        ))
  889.        
  890.         header.append('(k40_whisperer_set LaserXsize    %s )'  %( self.LaserXsize.get()     ))
  891.         header.append('(k40_whisperer_set LaserYsize    %s )'  %( self.LaserYsize.get()     ))
  892.         header.append('(k40_whisperer_set LaserXscale   %s )'  %( self.LaserXscale.get()    ))
  893.         header.append('(k40_whisperer_set LaserYscale   %s )'  %( self.LaserYscale.get()    ))
  894.         header.append('(k40_whisperer_set gotoX         %s )'  %( self.gotoX.get()          ))
  895.         header.append('(k40_whisperer_set gotoY         %s )'  %( self.gotoY.get()          ))
  896.  
  897.         header.append('(k40_whisperer_set bezier_M1     %s )'  %( self.bezier_M1.get()      ))
  898.         header.append('(k40_whisperer_set bezier_M2     %s )'  %( self.bezier_M2.get()      ))
  899.        
  900.         header.append('(k40_whisperer_set bezier_weight %s )'  %( self.bezier_weight.get()  ))
  901.  
  902.  
  903.  
  904.        
  905.         header.append('(k40_whisperer_set t_timeout     %s )'  %( self.t_timeout.get()      ))
  906.         header.append('(k40_whisperer_set n_timeouts    %s )'  %( self.n_timeouts.get()     ))
  907.        
  908.         header.append('(k40_whisperer_set designfile    \042%s\042 )' %( self.DESIGN_FILE   ))
  909.         header.append('(k40_whisperer_set inkscape_path \042%s\042 )' %( self.inkscape_path.get() ))
  910.  
  911.  
  912.         self.jog_step
  913.         header.append("(=========================================================)")
  914.  
  915.         return header
  916.         ######################################################
  917.  
  918.     def Quit_Click(self, event):
  919.         self.statusMessage.set("Exiting!")
  920.         root.destroy()
  921.  
  922.     def mousePanStart(self,event):
  923.         self.panx = event.x
  924.         self.pany = event.y
  925.         self.move_start_x = event.x
  926.         self.move_start_y = event.y
  927.        
  928.     def mousePan(self,event):
  929.         all = self.PreviewCanvas.find_all()
  930.         dx = event.x-self.panx
  931.         dy = event.y-self.pany
  932.  
  933.         self.PreviewCanvas.move('LaserTag', dx, dy)
  934.         self.lastx = self.lastx + dx
  935.         self.lasty = self.lasty + dy
  936.         self.panx = event.x
  937.         self.pany = event.y
  938.        
  939.     def mousePanStop(self,event):
  940.         Xold = round(self.laserX,3)
  941.         Yold = round(self.laserY,3)
  942.  
  943.         can_dx = event.x-self.move_start_x
  944.         can_dy = -(event.y-self.move_start_y)
  945.        
  946.         dx = can_dx*self.PlotScale
  947.         dy = can_dy*self.PlotScale
  948.         if self.HomeUR.get():
  949.             dx = -dx
  950.         self.laserX,self.laserY = self.XY_in_bounds(dx,dy)
  951.         DXmils = round((self.laserX - Xold)*1000.0,0)
  952.         DYmils = round((self.laserY - Yold)*1000.0,0)
  953.         self.Send_Rapid_Move(DXmils,DYmils)
  954.         self.menu_View_Refresh()
  955.  
  956.     def LASER_Size(self):
  957.         MINX = 0.0
  958.         MAXY = 0.0
  959.         if self.units.get()=="in":
  960.             MAXX =  float(self.LaserXsize.get())
  961.             MINY = -float(self.LaserYsize.get())
  962.         else:
  963.             MAXX =  float(self.LaserXsize.get())/25.4
  964.             MINY = -float(self.LaserYsize.get())/25.4
  965.  
  966.         return (MAXX-MINX,MAXY-MINY)
  967.  
  968.  
  969.     def XY_in_bounds(self,dx_inches,dy_inches):
  970.         MINX = 0.0
  971.         MAXY = 0.0
  972.         if self.units.get()=="in":
  973.             MAXX =  float(self.LaserXsize.get())
  974.             MINY = -float(self.LaserYsize.get())
  975.         else:
  976.             MAXX =  float(self.LaserXsize.get())/25.4
  977.             MINY = -float(self.LaserYsize.get())/25.4
  978.  
  979.         if self.inputCSYS.get() and self.RengData.image == None:
  980.             xmin,xmax,ymin,ymax = 0.0,0.0,0.0,0.0
  981.         else:
  982.             xmin,xmax,ymin,ymax = self.Get_Design_Bounds()
  983.        
  984.         X = self.laserX + dx_inches
  985.         X = min(MAXX-(xmax-xmin),X)
  986.         X = max(MINX,X)
  987.        
  988.         Y = self.laserY + dy_inches
  989.         Y = max(MINY+(ymax-ymin),Y)
  990.         Y = min(MAXY,Y)
  991.        
  992.         X = round(X,3)
  993.         Y = round(Y,3)
  994.         return X,Y
  995.  
  996. ##    def computeAccurateVeng(self):
  997. ##        self.update_gui("Optimize vector engrave.")
  998. ##        self.VengData.set_ecoords(self.optimize_paths(self.VengData.ecoords),data_sorted=True)
  999. ##        self.refreshTime()
  1000. ##            
  1001. ##    def computeAccurateVcut(self):
  1002. ##        self.update_gui("Optimize vector cut.")
  1003. ##        self.VcutData.set_ecoords(self.optimize_paths(self.VcutData.ecoords),data_sorted=True)
  1004. ##        self.refreshTime()
  1005. ##
  1006. ##    def computeAccurateReng(self):
  1007. ##        self.update_gui("Calculating Raster engrave.")
  1008. ##        if self.RengData.image != None:        
  1009. ##            if self.RengData.ecoords == []:
  1010. ##                self.make_raster_coords()
  1011. ##        self.RengData.sorted = True
  1012. ##        self.refreshTime()
  1013.  
  1014.  
  1015.     def format_time(self,time_in_seconds):
  1016.         # format the duration from seconds to something human readable
  1017.         if time_in_seconds >=0 :
  1018.             s = round(time_in_seconds)
  1019.             m,s=divmod(s,60)
  1020.             h,m=divmod(m,60)
  1021.             res = ""
  1022.             if h > 0:
  1023.                 res =  "%dh " %(h)
  1024.             if m > 0:
  1025.                 res += "%dm " %(m)
  1026.             if h == 0:
  1027.                 res += "%ds " %(s)
  1028.             #L=len(res)
  1029.             #for i in range(L,8):
  1030.             #    res =  res+" "
  1031.             return res
  1032.         else :
  1033.             return "?"
  1034.  
  1035.     def refreshTime(self):
  1036.         if not self.include_Time.get():
  1037.             return
  1038.         if self.units.get() == 'in':
  1039.             factor =  60.0
  1040.         else :
  1041.             factor = 25.4
  1042.  
  1043.         Raster_eng_feed = float(self.Reng_feed.get()) / factor
  1044.         Vector_eng_feed = float(self.Veng_feed.get()) / factor
  1045.         Vector_cut_feed = float(self.Vcut_feed.get()) / factor
  1046.        
  1047.         Raster_eng_passes = float(self.Reng_passes.get())
  1048.         Vector_eng_passes = float(self.Veng_passes.get())
  1049.         Vector_cut_passes = float(self.Vcut_passes.get())
  1050.         Gcode_passes      = float(self.Gcde_passes.get())
  1051.  
  1052.         rapid_feed = 100.0 / 25.4   # 100 mm/s move feed to be confirmed
  1053.  
  1054.        
  1055.         #if self.RengData.sorted:
  1056.         #    wim, him = self.RengData.image.size
  1057.         #    Reng_time  =  ( (self.RengData.len)/Raster_eng_feed + (him/self.input_dpi)/rapid_feed) * Raster_eng_passes
  1058.         #else:
  1059.         try:
  1060.             wim, him = self.RengData.image.size
  1061.             Reng_time  =   ((wim/self.input_dpi * him/self.input_dpi)/ float(self.rast_step.get()) ) / Raster_eng_feed*Raster_eng_passes
  1062.         except:
  1063.             Reng_time = 0
  1064.  
  1065.         Veng_time  =  (self.VengData.len / Vector_eng_feed + self.VengData.move / rapid_feed) * Vector_eng_passes
  1066.         Vcut_time  =  (self.VcutData.len / Vector_cut_feed + self.VcutData.move / rapid_feed) * Vector_cut_passes
  1067.         Gcode_time =  self.GcodeData.gcode_time * Gcode_passes
  1068.                
  1069.         self.Reng_time.set("Raster Engrave: %s" %(self.format_time(Reng_time)))
  1070.         self.Veng_time.set("Vector Engrave: %s" %(self.format_time(Veng_time)))
  1071.         self.Vcut_time.set("    Vector Cut: %s" %(self.format_time(Vcut_time)))
  1072.         self.Gcde_time.set("         Gcode: %s" %(self.format_time(Gcode_time)))
  1073.        
  1074.         ##########################################
  1075.         cszw = int(self.PreviewCanvas.cget("width"))
  1076.         cszh = int(self.PreviewCanvas.cget("height"))
  1077.         HUD_vspace = 15
  1078.         HUD_X = cszw-5
  1079.         HUD_Y = cszh-5
  1080.         self.PreviewCanvas.delete("HUD")
  1081.         if self.GcodeData.ecoords == []:
  1082.             self.PreviewCanvas.create_text(HUD_X, HUD_Y             , fill = "red"  ,text =self.Vcut_time.get(), anchor="se",tags="HUD")
  1083.             self.PreviewCanvas.create_text(HUD_X, HUD_Y-HUD_vspace  , fill = "blue" ,text =self.Veng_time.get(), anchor="se",tags="HUD")
  1084.             self.PreviewCanvas.create_text(HUD_X, HUD_Y-HUD_vspace*2, fill = "black",text =self.Reng_time.get(), anchor="se",tags="HUD")
  1085.         else:
  1086.             self.PreviewCanvas.create_text(HUD_X, HUD_Y, fill = "black",text =self.Gcde_time.get(), anchor="se",tags="HUD")
  1087.         ##########################################
  1088.  
  1089.  
  1090.     def Settings_ReLoad_Click(self, event):
  1091.         win_id=self.grab_current()
  1092.  
  1093.     def Close_Current_Window_Click(self):
  1094.         win_id=self.grab_current()
  1095.         win_id.destroy()
  1096.        
  1097.     # Left Column #
  1098.     #############################
  1099.     def Entry_Reng_feed_Check(self):
  1100.         try:
  1101.             value = float(self.Reng_feed.get())
  1102.             if  value <= 0.0:
  1103.                 self.statusMessage.set(" Feed Rate should be greater than 0.0 ")
  1104.                 return 2 # Value is invalid number
  1105.         except:
  1106.             return 3     # Value not a number
  1107.         self.refreshTime()
  1108.         return 0         # Value is a valid number
  1109.     def Entry_Reng_feed_Callback(self, varName, index, mode):
  1110.         self.entry_set(self.Entry_Reng_feed, self.Entry_Reng_feed_Check(), new=1)        
  1111.     #############################
  1112.     def Entry_Veng_feed_Check(self):
  1113.         try:
  1114.             value = float(self.Veng_feed.get())
  1115.             if  value <= 0.0:
  1116.                 self.statusMessage.set(" Feed Rate should be greater than 0.0 ")
  1117.                 return 2 # Value is invalid number
  1118.         except:
  1119.             return 3     # Value not a number
  1120.         self.refreshTime()
  1121.         return 0         # Value is a valid number
  1122.     def Entry_Veng_feed_Callback(self, varName, index, mode):
  1123.         self.entry_set(self.Entry_Veng_feed, self.Entry_Veng_feed_Check(), new=1)
  1124.     #############################
  1125.     def Entry_Vcut_feed_Check(self):
  1126.         try:
  1127.             value = float(self.Vcut_feed.get())
  1128.             if  value <= 0.0:
  1129.                 self.statusMessage.set(" Feed Rate should be greater than 0.0 ")
  1130.                 return 2 # Value is invalid number
  1131.         except:
  1132.             return 3     # Value not a number
  1133.         self.refreshTime()
  1134.         return 0         # Value is a valid number
  1135.     def Entry_Vcut_feed_Callback(self, varName, index, mode):
  1136.         self.entry_set(self.Entry_Vcut_feed, self.Entry_Vcut_feed_Check(), new=1)
  1137.        
  1138.     #############################
  1139.     def Entry_Step_Check(self):
  1140.         try:
  1141.             value = float(self.jog_step.get())
  1142.             if  value <= 0.0:
  1143.                 self.statusMessage.set(" Step should be greater than 0.0 ")
  1144.                 return 2 # Value is invalid number
  1145.         except:
  1146.             return 3     # Value not a number
  1147.         return 0         # Value is a valid number
  1148.     def Entry_Step_Callback(self, varName, index, mode):
  1149.         self.entry_set(self.Entry_Step, self.Entry_Step_Check(), new=1)
  1150.  
  1151.  
  1152.     #############################
  1153.     def Entry_GoToX_Check(self):
  1154.         try:
  1155.             value = float(self.gotoX.get())
  1156.             if  (value < 0.0) and (not self.HomeUR.get()):
  1157.                 self.statusMessage.set(" Value should be greater than 0.0 ")
  1158.                 return 2 # Value is invalid number
  1159.             elif (value > 0.0) and self.HomeUR.get():
  1160.                 self.statusMessage.set(" Value should be less than 0.0 ")
  1161.                 return 2 # Value is invalid number
  1162.         except:
  1163.             return 3     # Value not a number
  1164.         return 0         # Value is a valid number
  1165.     def Entry_GoToX_Callback(self, varName, index, mode):
  1166.         self.entry_set(self.Entry_GoToX, self.Entry_GoToX_Check(), new=1)
  1167.  
  1168.     #############################
  1169.     def Entry_GoToY_Check(self):
  1170.         try:
  1171.             value = float(self.gotoY.get())
  1172.             if  value > 0.0:
  1173.                 self.statusMessage.set(" Value should be less than 0.0 ")
  1174.                 return 2 # Value is invalid number
  1175.         except:
  1176.             return 3     # Value not a number
  1177.         return 0         # Value is a valid number
  1178.     def Entry_GoToY_Callback(self, varName, index, mode):
  1179.         self.entry_set(self.Entry_GoToY, self.Entry_GoToY_Check(), new=1)
  1180.        
  1181.     #############################
  1182.     def Entry_Rstep_Check(self):
  1183.         try:
  1184.             value = self.get_raster_step_1000in()
  1185.             if  value <= 0 or value > 63:
  1186.                 self.statusMessage.set(" Step should be between 0.001 and 0.063 in")
  1187.                 return 2 # Value is invalid number
  1188.         except:
  1189.             return 3     # Value not a number
  1190.         return 0         # Value is a valid number
  1191.     def Entry_Rstep_Callback(self, varName, index, mode):
  1192.         self.entry_set(self.Entry_Rstep, self.Entry_Rstep_Check(), new=1)
  1193.  
  1194.     #############################
  1195.     # End Left Column #
  1196.     #############################
  1197.     def bezier_weight_Callback(self, varName=None, index=None, mode=None):
  1198.         self.bezier_plot()
  1199.        
  1200.     def bezier_M1_Callback(self, varName=None, index=None, mode=None):
  1201.         self.bezier_plot()
  1202.  
  1203.     def bezier_M2_Callback(self, varName=None, index=None, mode=None):
  1204.         self.bezier_plot()
  1205.  
  1206.     def bezier_plot(self):
  1207.         self.BezierCanvas.delete('bez')
  1208.  
  1209.         #self.BezierCanvas.create_line( 5,260-0,260,260-255,fill="black", capstyle="round", width = 2, tags='bez')
  1210.         M1 = float(self.bezier_M1.get())
  1211.         M2 = float(self.bezier_M2.get())
  1212.         w  = float(self.bezier_weight.get())
  1213.         num = 10
  1214.         x,y = self.generate_bezier(M1,M2,w,n=num)
  1215.         for i in range(0,num):
  1216.             self.BezierCanvas.create_line( 5+x[i],260-y[i],5+x[i+1],260-y[i+1],fill="black", \
  1217.                                            capstyle="round", width = 2, tags='bez')
  1218.         self.BezierCanvas.create_text(128, 0, text="Output Level vs. Input Level",anchor="n", tags='bez')
  1219.            
  1220.     #############################
  1221.     def Entry_Timeout_Check(self):
  1222.         try:
  1223.             value = float(self.t_timeout.get())
  1224.             if  value <= 0.0:
  1225.                 self.statusMessage.set(" Timeout should be greater than 0 ")
  1226.                 return 2 # Value is invalid number
  1227.         except:
  1228.             return 3     # Value not a number
  1229.         return 0         # Value is a valid number
  1230.     def Entry_Timeout_Callback(self, varName, index, mode):
  1231.         self.entry_set(self.Entry_Timeout,self.Entry_Timeout_Check(), new=1)
  1232.  
  1233.     #############################
  1234.     def Entry_N_Timeouts_Check(self):
  1235.         try:
  1236.             value = float(self.n_timeouts.get())
  1237.             if  value <= 0.0:
  1238.                 self.statusMessage.set(" N_Timeouts should be greater than 0 ")
  1239.                 return 2 # Value is invalid number
  1240.         except:
  1241.             return 3     # Value not a number
  1242.         return 0         # Value is a valid number
  1243.     def Entry_N_Timeouts_Callback(self, varName, index, mode):
  1244.         self.entry_set(self.Entry_N_Timeouts,self.Entry_N_Timeouts_Check(), new=1)
  1245.        
  1246.     #############################
  1247.     def Entry_Laser_Area_Width_Check(self):
  1248.         try:
  1249.             value = float(self.LaserXsize.get())
  1250.             if  value <= 0.0:
  1251.                 self.statusMessage.set(" Width should be greater than 0 ")
  1252.                 return 2 # Value is invalid number
  1253.         except:
  1254.             return 3     # Value not a number
  1255.         return 0         # Value is a valid number
  1256.     def Entry_Laser_Area_Width_Callback(self, varName, index, mode):
  1257.         self.entry_set(self.Entry_Laser_Area_Width,self.Entry_Laser_Area_Width_Check(), new=1)
  1258.  
  1259.     #############################
  1260.     def Entry_Laser_Area_Height_Check(self):
  1261.         try:
  1262.             value = float(self.LaserYsize.get())
  1263.             if  value <= 0.0:
  1264.                 self.statusMessage.set(" Height should be greater than 0 ")
  1265.                 return 2 # Value is invalid number
  1266.         except:
  1267.             return 3     # Value not a number
  1268.         return 0         # Value is a valid number
  1269.     def Entry_Laser_Area_Height_Callback(self, varName, index, mode):
  1270.         self.entry_set(self.Entry_Laser_Area_Height,self.Entry_Laser_Area_Height_Check(), new=1)
  1271.  
  1272.  
  1273.     #############################
  1274.     def Entry_Laser_X_Scale_Check(self):
  1275.         try:
  1276.             value = float(self.LaserXscale.get())
  1277.             if  value <= 0.0:
  1278.                 self.statusMessage.set(" Scale should be greater than 0 ")
  1279.                 return 2 # Value is invalid number
  1280.         except:
  1281.             return 3     # Value not a number
  1282.         return 0         # Value is a valid number
  1283.     def Entry_Laser_X_Scale_Callback(self, varName, index, mode):
  1284.         self.entry_set(self.Entry_Laser_X_Scale,self.Entry_Laser_X_Scale_Check(), new=1)
  1285.     #############################
  1286.     def Entry_Laser_Y_Scale_Check(self):
  1287.         try:
  1288.             value = float(self.LaserYscale.get())
  1289.             if  value <= 0.0:
  1290.                 self.statusMessage.set(" Height should be greater than 0 ")
  1291.                 return 2 # Value is invalid number
  1292.         except:
  1293.             return 3     # Value not a number
  1294.         return 0         # Value is a valid number
  1295.     def Entry_Laser_Y_Scale_Callback(self, varName, index, mode):
  1296.         self.entry_set(self.Entry_Laser_Y_Scale,self.Entry_Laser_Y_Scale_Check(), new=1)
  1297.  
  1298.     # Advanced Column #
  1299.     #############################
  1300.     def Entry_Reng_passes_Check(self):
  1301.         try:
  1302.             value = int(self.Reng_passes.get())
  1303.             if  value < 1:
  1304.                 self.statusMessage.set(" Number of passes should be greater than 0 ")
  1305.                 return 2 # Value is invalid number
  1306.         except:
  1307.             return 3     # Value not a number
  1308.         self.refreshTime()
  1309.         return 0         # Value is a valid number
  1310.     def Entry_Reng_passes_Callback(self, varName, index, mode):
  1311.         self.entry_set(self.Entry_Reng_passes, self.Entry_Reng_passes_Check(), new=1)        
  1312.     #############################
  1313.     def Entry_Veng_passes_Check(self):
  1314.         try:
  1315.             value = int(self.Veng_passes.get())
  1316.             if  value < 1:
  1317.                 self.statusMessage.set(" Number of passes should be greater than 0 ")
  1318.                 return 2 # Value is invalid number
  1319.         except:
  1320.             return 3     # Value not a number
  1321.         self.refreshTime()
  1322.         return 0         # Value is a valid number
  1323.     def Entry_Veng_passes_Callback(self, varName, index, mode):
  1324.         self.entry_set(self.Entry_Veng_passes, self.Entry_Veng_passes_Check(), new=1)
  1325.     #############################
  1326.     def Entry_Vcut_passes_Check(self):
  1327.         try:
  1328.             value = int(self.Vcut_passes.get())
  1329.             if  value < 1:
  1330.                 self.statusMessage.set(" Number of passes should be greater than 0 ")
  1331.                 return 2 # Value is invalid number
  1332.         except:
  1333.             return 3     # Value not a number
  1334.         self.refreshTime()
  1335.         return 0         # Value is a valid number
  1336.     def Entry_Vcut_passes_Callback(self, varName, index, mode):
  1337.         self.entry_set(self.Entry_Vcut_passes, self.Entry_Vcut_passes_Check(), new=1)
  1338.        
  1339.     #############################
  1340.     def Entry_Gcde_passes_Check(self):
  1341.         try:
  1342.             value = int(self.Gcde_passes.get())
  1343.             if  value < 1:
  1344.                 self.statusMessage.set(" Number of passes should be greater than 0 ")
  1345.                 return 2 # Value is invalid number
  1346.         except:
  1347.             return 3     # Value not a number
  1348.         return 0         # Value is a valid number
  1349.     def Entry_Gcde_passes_Callback(self, varName, index, mode):
  1350.         self.entry_set(self.Entry_Gcde_passes, self.Entry_Gcde_passes_Check(), new=1)
  1351.        
  1352.     #############################
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358.     ##########################################################################
  1359.     ##########################################################################
  1360.     def Check_All_Variables(self):
  1361.         pass
  1362. ##        MAIN_error_cnt= \
  1363. ##        self.entry_set(self.Entry_Yscale, self.Entry_Yscale_Check()    ,2) +\
  1364. ##        self.entry_set(self.Entry_Toptol, self.Entry_Toptol_Check()    ,2)
  1365. ##
  1366. ##        GEN_error_cnt= \
  1367. ##        self.entry_set(self.Entry_ContAngle,self.Entry_ContAngle_Check(),2)
  1368.  
  1369. ##        ERROR_cnt = MAIN_error_cnt + GEN_error_cnt
  1370. ##
  1371. ##        if (ERROR_cnt > 0):
  1372. ##            self.statusbar.configure( bg = 'red' )
  1373. ##        if (GEN_error_cnt > 0):
  1374. ##            self.statusMessage.set(\
  1375. ##                " Entry Error Detected: Check Entry Values in General Settings Window ")
  1376. ##        if (MAIN_error_cnt > 0):
  1377. ##            self.statusMessage.set(\
  1378. ##                " Entry Error Detected: Check Entry Values in Main Window ")
  1379. ##
  1380. ##        return ERROR_cnt
  1381.  
  1382.  
  1383.  
  1384.     #############################
  1385.     def Inkscape_Path_Click(self, event):
  1386.         win_id=self.grab_current()
  1387.         newfontdir = askopenfilename(filetypes=[("Executable Files",("inkscape.exe","*inkscape*")),\
  1388.                                                 ("All Files","*")],\
  1389.                                                  initialdir=self.inkscape_path.get())
  1390.         if newfontdir != "" and newfontdir != ():
  1391.             self.inkscape_path.set(newfontdir.encode("utf-8"))
  1392.         try:
  1393.             win_id.withdraw()
  1394.             win_id.deiconify()
  1395.         except:
  1396.             pass
  1397.  
  1398.  
  1399.     def Entry_units_var_Callback(self):
  1400.         if (self.units.get() == 'in') and (self.funits.get()=='mm/s'):
  1401.             self.funits.set('in/min')
  1402.             self.Scale_Linear_Inputs('in')
  1403.         elif (self.units.get() == 'mm') and (self.funits.get()=='in/min'):
  1404.             self.funits.set('mm/s')
  1405.             self.Scale_Linear_Inputs('mm')
  1406.            
  1407.     def Scale_Linear_Inputs(self, new_units=None):
  1408.         if new_units=='in':
  1409.             self.units_scale = 1.0
  1410.             factor  = 1/25.4
  1411.             vfactor = 60.0/25.4
  1412.         elif new_units=='mm':
  1413.             factor  = 25.4
  1414.             vfactor = 25.4/60.0
  1415.             self.units_scale = 25.4
  1416.         else:
  1417.             return
  1418.         self.LaserXsize.set( self.Scale_Text_Value('%.2f',self.LaserXsize.get(),factor) )
  1419.         self.LaserYsize.set( self.Scale_Text_Value('%.2f',self.LaserYsize.get(),factor) )
  1420.         self.jog_step.set  ( self.Scale_Text_Value('%.3f',self.jog_step.get()  ,factor) )
  1421.         self.gotoX.set     ( self.Scale_Text_Value('%.3f',self.gotoX.get()     ,factor) )
  1422.         self.gotoY.set     ( self.Scale_Text_Value('%.3f',self.gotoY.get()     ,factor) )
  1423.         self.Reng_feed.set ( self.Scale_Text_Value('%.1f',self.Reng_feed.get() ,vfactor) )
  1424.         self.Veng_feed.set ( self.Scale_Text_Value('%.1f',self.Veng_feed.get() ,vfactor) )
  1425.         self.Vcut_feed.set ( self.Scale_Text_Value('%.1f',self.Vcut_feed.get() ,vfactor) )
  1426.  
  1427.     def Scale_Text_Value(self,format_txt,Text_Value,factor):
  1428.         try:
  1429.             return format_txt %(float(Text_Value)*factor )
  1430.         except:
  1431.             return ''
  1432.  
  1433.     def menu_File_Open_Settings_File(self):
  1434.         init_dir = os.path.dirname(self.DESIGN_FILE)
  1435.         if ( not os.path.isdir(init_dir) ):
  1436.             init_dir = self.HOME_DIR
  1437.         fileselect = askopenfilename(filetypes=[("Settings Files","*.txt"),\
  1438.                                                 ("All Files","*")],\
  1439.                                                  initialdir=init_dir)
  1440.         if fileselect != '' and fileselect != ():
  1441.             self.Open_Settings_File(fileselect)
  1442.  
  1443.  
  1444.     def menu_Reload_Design(self):
  1445.         file_full = self.DESIGN_FILE
  1446.         file_name = os.path.basename(file_full)
  1447.         if ( os.path.isfile(file_full) ):
  1448.             filname = file_full
  1449.         elif ( os.path.isfile( file_name ) ):
  1450.             filname = file_name
  1451.         elif ( os.path.isfile( self.HOME_DIR+"/"+file_name ) ):
  1452.             filname = self.HOME_DIR+"/"+file_name
  1453.         else:
  1454.             self.statusMessage.set("file not found: %s" %(os.path.basename(file_full)) )
  1455.             self.statusbar.configure( bg = 'red' )
  1456.             return
  1457.        
  1458.        
  1459.         Name, fileExtension = os.path.splitext(filname)
  1460.         TYPE=fileExtension.upper()
  1461.         if TYPE=='.DXF':
  1462.             self.Open_DXF(filname)
  1463.         elif TYPE=='.SVG':
  1464.             self.Open_SVG(filname)
  1465.         else:
  1466.             self.Open_G_Code(filname)
  1467.         self.menu_View_Refresh()
  1468.        
  1469.  
  1470.     def menu_File_Open_Design(self):
  1471.         init_dir = os.path.dirname(self.DESIGN_FILE)
  1472.         if ( not os.path.isdir(init_dir) ):
  1473.             init_dir = self.HOME_DIR
  1474.  
  1475.         fileselect = askopenfilename(filetypes=[("Design Files", ("*.svg","*.dxf")),
  1476.                                             ("G-Code Files", ("*.ngc","*.gcode","*.g","*.tap")),\
  1477.                                             ("DXF Files","*.dxf"),\
  1478.                                             ("SVG Files","*.svg"),\
  1479.                                             ("All Files","*"),\
  1480.                                             ("Design Files ", ("*.svg","*.dxf"))],\
  1481.                                             initialdir=init_dir)
  1482.        
  1483.         if ( not os.path.isfile(fileselect) ):
  1484.             return
  1485.                
  1486.         Name, fileExtension = os.path.splitext(fileselect)
  1487.         self.update_gui("Opening '%s'" % fileselect )
  1488.         TYPE=fileExtension.upper()
  1489.         if TYPE=='.DXF':
  1490.             self.Open_DXF(fileselect)
  1491.         elif TYPE=='.SVG':
  1492.             self.Open_SVG(fileselect)
  1493.         else:
  1494.             self.Open_G_Code(fileselect)
  1495.  
  1496.            
  1497.         self.DESIGN_FILE = fileselect
  1498.         self.menu_View_Refresh()
  1499.        
  1500.  
  1501.     def menu_File_Open_EGV(self):
  1502.         init_dir = os.path.dirname(self.DESIGN_FILE)
  1503.         if ( not os.path.isdir(init_dir) ):
  1504.             init_dir = self.HOME_DIR
  1505.         fileselect = askopenfilename(filetypes=[("Engraver Files", ("*.egv","*.EGV")),\
  1506.                                                     ("All Files","*")],\
  1507.                                                      initialdir=init_dir)
  1508.  
  1509.         if fileselect != '' and fileselect != ():
  1510.             self.DESIGN_FILE = fileselect
  1511.             self.Open_EGV(fileselect)
  1512.             self.menu_View_Refresh()
  1513.            
  1514.     def Open_EGV(self,filemname):
  1515.         pass
  1516.         EGV_data=[]
  1517.         data=""
  1518.         with open(filemname) as f:
  1519.             while True:
  1520.                 c = f.read(1)
  1521.                 if not c:
  1522.                   break
  1523.                 if c=='\n' or c==' ' or c=='\r':
  1524.                     pass
  1525.                 else:
  1526.                     data=data+"%c" %c
  1527.                     EGV_data.append(ord(c))
  1528.         if message_ask_ok_cancel("EGV", "Send EGV Data to Laser...."):
  1529.             self.send_egv_data(EGV_data)
  1530.  
  1531.        
  1532.     def Open_SVG(self,filemname):
  1533.         self.resetPath()
  1534.                
  1535.         self.SVG_FILE = filemname
  1536.         svg_reader =  SVG_READER()
  1537.         svg_reader.set_inkscape_path(self.inkscape_path.get())
  1538.         self.input_dpi = 1000
  1539.         svg_reader.image_dpi = self.input_dpi
  1540.         try:
  1541.             try:
  1542.                 svg_reader.parse(self.SVG_FILE)
  1543.                 svg_reader.make_paths()
  1544.             except SVG_TEXT_EXCEPTION as e:
  1545.                 svg_reader = SVG_READER()
  1546.                 svg_reader.set_inkscape_path(self.inkscape_path.get())
  1547.                 self.statusMessage.set("Converting TEXT to PATHS.")
  1548.                 self.master.update()
  1549.                 svg_reader.parse(self.SVG_FILE)
  1550.                 svg_reader.make_paths(txt2paths=True)
  1551.                
  1552.         except StandardError as e:
  1553.             msg1 = "SVG file load failed: "
  1554.             msg2 = "%s" %(e)
  1555.             self.statusMessage.set((msg1+msg2).split("\n")[0] )
  1556.             self.statusbar.configure( bg = 'red' )
  1557.             message_box(msg1, msg2)
  1558.             debug_message(traceback.format_exc())
  1559.             return
  1560.         except:
  1561.             self.statusMessage.set("Unable To open SVG File: %s" %(filemname))
  1562.             debug_message(traceback.format_exc())
  1563.             return
  1564.         xmax = svg_reader.Xsize/25.4
  1565.         ymax = svg_reader.Ysize/25.4
  1566.         xmin = 0
  1567.         ymin = 0
  1568.  
  1569.         self.Design_bounds = (xmin,xmax,ymin,ymax)
  1570.        
  1571.         ##########################
  1572.         ###   Create ECOORDS   ###
  1573.         ##########################
  1574.         self.VcutData.make_ecoords(svg_reader.cut_lines,scale=1/25.4)
  1575.         self.VengData.make_ecoords(svg_reader.eng_lines,scale=1/25.4)
  1576.  
  1577.         ##########################
  1578.         ###   Load Image       ###
  1579.         ##########################
  1580.         self.RengData.set_image(svg_reader.raster_PIL)
  1581.        
  1582.         if (self.RengData.image != None):
  1583.             self.wim, self.him = self.RengData.image.size
  1584.             self.aspect_ratio =  float(self.wim-1) / float(self.him-1)
  1585.             #self.make_raster_coords()
  1586.         self.refreshTime()
  1587.  
  1588.     def make_ecoords(self,coords,scale=1):
  1589.         xmax, ymax = -1e10, -1e10
  1590.         xmin, ymin =  1e10,  1e10
  1591.         ecoords=[]
  1592.         Acc=.001
  1593.         oldx = oldy = -99990.0
  1594.         first_stroke = True
  1595.         loop=0
  1596.         for line in coords:
  1597.             XY = line
  1598.             x1 = XY[0]*scale
  1599.             y1 = XY[1]*scale
  1600.             x2 = XY[2]*scale
  1601.             y2 = XY[3]*scale
  1602.             dx = oldx - x1
  1603.             dy = oldy - y1
  1604.             dist = sqrt(dx*dx + dy*dy)
  1605.             # check and see if we need to move to a new discontinuous start point
  1606.             if (dist > Acc) or first_stroke:
  1607.                 loop = loop+1
  1608.                 first_stroke = False
  1609.                 ecoords.append([x1,y1,loop])
  1610.             ecoords.append([x2,y2,loop])
  1611.             oldx, oldy = x2, y2
  1612.             xmax=max(xmax,x1,x2)
  1613.             ymax=max(ymax,y1,y2)
  1614.             xmin=min(xmin,x1,x2)
  1615.             ymin=min(ymin,y1,y2)
  1616.         bounds = (xmin,xmax,ymin,ymax)
  1617.         return ecoords,bounds
  1618.  
  1619. ##    def convert_greyscale(self,image):
  1620. ##        image = image.convert('RGB')
  1621. ##        x_lim, y_lim = image.size
  1622. ##        grey = Image.new("L", image.size, color=255)
  1623. ##        
  1624. ##        pixel = image.load()
  1625. ##        grey_pixel = grey.load()
  1626. ##        
  1627. ##        for y in range(1, y_lim):
  1628. ##            self.statusMessage.set("Converting to greyscale: %.1f %%" %( (100.0*y)/y_lim ) )
  1629. ##            self.master.update()
  1630. ##            for x in range(1, x_lim):
  1631. ##                value = pixel[x, y]
  1632. ##                grey_pixel[x,y] = int( value[0]*.333 + value[1]*.333 +value[2]*.333 )
  1633. ##                #grey_pixel[x,y] = int( value[0]*.210 + value[1]*.720 +value[2]*.007 )
  1634. ##                grey_pixel[x,y] = int( value[0]*.299 + value[1]*.587 +value[2]*.114 )
  1635. ##
  1636. ##        grey.save("adjusted_grey.png","PNG")
  1637. ##        return grey
  1638.  
  1639.    
  1640.     #####################################################################
  1641.     def make_raster_coords(self):
  1642.             ecoords=[]
  1643.             if (self.RengData.image != None):
  1644.                 cutoff=128
  1645.                 image_temp = self.RengData.image.convert("L")
  1646.  
  1647.                 if self.mirror.get():
  1648.                     image_temp = ImageOps.mirror(image_temp)
  1649.  
  1650.                 if self.rotate.get():
  1651.                     #image_temp = image_temp.rotate(90,expand=True)
  1652.                     image_temp = self.rotate_raster(image_temp)
  1653.  
  1654.                 Xscale = float(self.LaserXscale.get())
  1655.                 Yscale = float(self.LaserYscale.get())
  1656.                 if Xscale != 1.0 or Yscale != 1.0:
  1657.                     wim,him = image_temp.size
  1658.                     nw = int(wim*Xscale)
  1659.                     nh = int(him*Yscale)
  1660.                     image_temp = image_temp.resize((nw,nh))
  1661.  
  1662.                    
  1663.                 if self.halftone.get():
  1664.                     #start = time()
  1665.                     ht_size_mils =  round( 1000.0 / float(self.ht_size.get()) ,1)
  1666.                     npixels = int( round(ht_size_mils,1) )
  1667.                     if npixels == 0:
  1668.                         return
  1669.                     wim,him = image_temp.size
  1670.                     # Convert to Halftoning and save
  1671.                     nw=int(wim / npixels)
  1672.                     nh=int(him / npixels)
  1673.                     image_temp = image_temp.resize((nw,nh))
  1674.                    
  1675.                     image_temp = self.convert_halftoning(image_temp)
  1676.                     image_temp = image_temp.resize((wim,him))
  1677.                     #print time()-start
  1678.                    
  1679.                 if DEBUG:
  1680.                     image_name = os.path.expanduser("~")+"/IMAGE.png"
  1681.                     image_temp.save(image_name,"PNG")
  1682.  
  1683.                 Reng_np = image_temp.load()
  1684.                 wim,him = image_temp.size
  1685.                 #######################################
  1686.                 x=0
  1687.                 y=0
  1688.                 loop=1
  1689.                
  1690.                 Raster_step = self.get_raster_step_1000in()
  1691.                 for i in range(0,him,Raster_step):
  1692.                     if i%100 ==0:
  1693.                         self.statusMessage.set("Raster Engraving: Creating Scan Lines: %.1f %%" %( (100.0*i)/him ) )
  1694.                         self.master.update()
  1695.                     if self.stop[0]==True:
  1696.                         raise StandardError("Action stopped by User.")
  1697.                     line = []
  1698.                     cnt=1
  1699.                     for j in range(1,wim):
  1700.                         if (Reng_np[j,i] == Reng_np[j-1,i]):
  1701.                             cnt = cnt+1
  1702.                         else:
  1703.                             laser = "U" if Reng_np[j-1,i] > cutoff else "D"
  1704.                             line.append((cnt,laser))
  1705.                             cnt=1
  1706.                     laser = "U" if Reng_np[j-1,i] > cutoff else "D"
  1707.                     line.append((cnt,laser))
  1708.                    
  1709.                     y=(him-i)/1000.0
  1710.                     x=0
  1711.                     rng = range(0,len(line),1)
  1712.                        
  1713.                     for i in rng:
  1714.                         seg = line[i]
  1715.                         delta = seg[0]/1000.0
  1716.                         if seg[1]=="D":
  1717.                             loop=loop+1
  1718.                             ecoords.append([x      ,y,loop])
  1719.                             ecoords.append([x+delta,y,loop])
  1720.                         x = x + delta
  1721.                        
  1722.             if ecoords!=[]:
  1723.                 self.RengData.set_ecoords(ecoords,data_sorted=True)
  1724.     #######################################################################
  1725.  
  1726.  
  1727.     def rotate_raster(self,image_in):
  1728.         wim,him = image_in.size
  1729.         im_rotated = Image.new("L", (him, wim), "white")
  1730.  
  1731.         image_in_np   = image_in.load()
  1732.         im_rotated_np = im_rotated.load()
  1733.        
  1734.         for i in range(1,him):
  1735.             for j in range(1,wim):
  1736.                 im_rotated_np[i,wim-j] = image_in_np[j,i]
  1737.         return im_rotated
  1738.    
  1739.     def get_raster_step_1000in(self):
  1740.         val_in = float(self.rast_step.get())
  1741.         value = int(round(val_in*1000.0,1))
  1742.         return value
  1743.  
  1744.  
  1745.     def generate_bezier(self,M1,M2,w,n=100):
  1746.         if (M1==M2):
  1747.             x1=0
  1748.             y1=0
  1749.         else:
  1750.             x1 = 255*(1-M2)/(M1-M2)
  1751.             y1 = M1*x1
  1752.         x=[]
  1753.         y=[]
  1754.         # Calculate Bezier Curve
  1755.         for step in range(0,n+1):
  1756.             t    = float(step)/float(n)
  1757.             Ct   = 1 / ( pow(1-t,2)+2*(1-t)*t*w+pow(t,2) )
  1758.             x.append( Ct*( 2*(1-t)*t*w*x1+pow(t,2)*255) )
  1759.             y.append( Ct*( 2*(1-t)*t*w*y1+pow(t,2)*255) )
  1760.         return x,y
  1761.  
  1762.     '''This Example opens an Image and transform the image into halftone.  -Isai B. Cicourel'''
  1763.     # Create a Half-tone version of the image
  1764.     def convert_halftoning(self,image):
  1765.         image = image.convert('L')
  1766.         x_lim, y_lim = image.size
  1767.         pixel = image.load()
  1768.        
  1769.         M1 = float(self.bezier_M1.get())
  1770.         M2 = float(self.bezier_M2.get())
  1771.         w  = float(self.bezier_weight.get())
  1772.        
  1773.         if w > 0:
  1774.             x,y = self.generate_bezier(M1,M2,w)
  1775.            
  1776.             interp = interpolate(x, y) # Set up interpolate class
  1777.             val_map=[]
  1778.             # Map Bezier Curve to values between 0 and 255
  1779.             for val in range(0,256):
  1780.                 val_out = int(round(interp[val])) # Get the interpolated value at each value
  1781.                 val_map.append(val_out)
  1782.             # Adjust image
  1783.             for y in range(1, y_lim):
  1784.                 self.statusMessage.set("Raster Engraving: Adjusting Image Darkness: %.1f %%" %( (100.0*y)/y_lim ) )
  1785.                 self.master.update()
  1786.                 for x in range(1, x_lim):
  1787.                     pixel[x, y] = val_map[ pixel[x, y] ]
  1788.  
  1789.         self.statusMessage.set("Raster Engraving: Creating Halftone Image." )
  1790.         self.master.update()
  1791.         image = image.convert('1')
  1792.         return image
  1793.  
  1794.     #######################################################################
  1795.  
  1796.     def Open_G_Code(self,filename):
  1797.         self.resetPath()
  1798.        
  1799.         g_rip = G_Code_Rip()
  1800.         try:
  1801.             MSG = g_rip.Read_G_Code(filename, XYarc2line = True, arc_angle=2, units="in", Accuracy="")
  1802.             Error_Text = ""
  1803.             if MSG!=[]:
  1804.                 for line in MSG:
  1805.                     Error_Text = Error_Text + line + "\n"
  1806.                     message_box("G-Code Messages", Error_Text)
  1807.         except StandardError as e:
  1808.             msg1 = "G-Code Load Failed:  "
  1809.             msg2 = "Filename: %s" %(filename)
  1810.             msg3 = "%s" %(e)
  1811.             self.statusMessage.set((msg1+msg3).split("\n")[0] )
  1812.             self.statusbar.configure( bg = 'red' )
  1813.             message_box(msg1, "%s\n%s" %(msg2,msg3))
  1814.             debug_message(traceback.format_exc())
  1815.  
  1816.            
  1817.         ecoords= g_rip.generate_laser_paths(g_rip.g_code_data)
  1818.         self.GcodeData.set_ecoords(ecoords,data_sorted=True)
  1819.         self.Design_bounds = self.GcodeData.bounds
  1820.  
  1821.        
  1822.     def Open_DXF(self,filemname):
  1823.         self.resetPath()
  1824.        
  1825.         self.DXF_FILE = filemname
  1826.         dxf_import=DXF_CLASS()
  1827.         segarc = 2
  1828.         try:
  1829.             fd = open(self.DXF_FILE)
  1830.             dxf_import.GET_DXF_DATA(fd,tol_deg=segarc)
  1831.             fd.close()
  1832.         except StandardError as e:
  1833.             msg1 = "DXF Load Failed:"
  1834.             msg2 = "%s" %(e)
  1835.             self.statusMessage.set((msg1+msg2).split("\n")[0] )
  1836.             self.statusbar.configure( bg = 'red' )
  1837.             message_box(msg1, msg2)
  1838.             debug_message(traceback.format_exc())
  1839.         except:
  1840.             fmessage("Unable To open Drawing Exchange File (DXF) file.")
  1841.             debug_message(traceback.format_exc())
  1842.             return
  1843.        
  1844.         new_origin=False
  1845.         dxf_engrave_coords = dxf_import.DXF_COORDS_GET_TYPE(engrave=True, new_origin=False)
  1846.         dxf_cut_coords     = dxf_import.DXF_COORDS_GET_TYPE(engrave=False,new_origin=False)
  1847.        
  1848.         dxf_units = dxf_import.units
  1849.         if dxf_import.dxf_messages != "":
  1850.             msg_split=dxf_import.dxf_messages.split("\n")
  1851.             msg_split.sort()
  1852.             msg_split.append("")
  1853.             mcnt=1
  1854.             msg_out = ""
  1855.             for i in range(1,len(msg_split)):
  1856.                 if msg_split[i-1]==msg_split[i]:
  1857.                     mcnt=mcnt+1
  1858.                 else:
  1859.                     if msg_split[i-1]!="":
  1860.                         msg_line = "%s (%d places)\n" %(msg_split[i-1],mcnt)
  1861.                         msg_out = msg_out + msg_line
  1862.                     mcnt=1
  1863.             message_box("DXF Import:",msg_out)
  1864.            
  1865.         if dxf_units=="Unitless":
  1866.             d = UnitsDialog(root)
  1867.             dxf_units = d.result
  1868.  
  1869.         if dxf_units=="Inches":
  1870.             dxf_scale = 1.0
  1871.         elif dxf_units=="Feet":
  1872.             dxf_scale = 12.0
  1873.         elif dxf_units=="Miles":
  1874.             dxf_scale = 5280.0*12.0
  1875.         elif dxf_units=="Millimeters":
  1876.             dxf_scale = 1.0/25.4
  1877.         elif dxf_units=="Centimeters":
  1878.             dxf_scale = 1.0/2.54
  1879.         elif dxf_units=="Meters":
  1880.             dxf_scale = 1.0/254.0
  1881.         elif dxf_units=="Kilometers":
  1882.             dxf_scale = 1.0/254000.0
  1883.         elif dxf_units=="Microinches":
  1884.             dxf_scale = 1.0/1000000.0
  1885.         elif dxf_units=="Mils":
  1886.             dxf_scale = 1.0/1000.0
  1887.         else:
  1888.             return
  1889.        
  1890.         ##########################
  1891.         ###   Create ECOORDS   ###
  1892.         ##########################
  1893.         self.VcutData.make_ecoords(dxf_cut_coords    ,scale=dxf_scale)
  1894.         self.VengData.make_ecoords(dxf_engrave_coords,scale=dxf_scale)
  1895.  
  1896.         xmin = min(self.VcutData.bounds[0],self.VengData.bounds[0])
  1897.         xmax = max(self.VcutData.bounds[1],self.VengData.bounds[1])
  1898.         ymin = min(self.VcutData.bounds[2],self.VengData.bounds[2])
  1899.         ymax = max(self.VcutData.bounds[3],self.VengData.bounds[3])
  1900.         self.Design_bounds = (xmin,xmax,ymin,ymax)
  1901.  
  1902.  
  1903.     def Open_Settings_File(self,filename):
  1904.         try:
  1905.             fin = open(filename,'r')
  1906.         except:
  1907.             fmessage("Unable to open file: %s" %(filename))
  1908.             return
  1909.        
  1910.         text_codes=[]
  1911.         ident = "k40_whisperer_set"
  1912.         for line in fin:
  1913.             if ident in line:
  1914.                 # BOOL
  1915.                 if "include_Reng"  in line:
  1916.                     self.include_Reng.set(line[line.find("include_Reng"):].split()[1])
  1917.                 elif "include_Veng"  in line:
  1918.                     self.include_Veng.set(line[line.find("include_Veng"):].split()[1])
  1919.                 elif "include_Vcut"  in line:
  1920.                     self.include_Vcut.set(line[line.find("include_Vcut"):].split()[1])
  1921.                 elif "include_Gcde"  in line:
  1922.                     self.include_Gcde.set(line[line.find("include_Gcde"):].split()[1])
  1923.                 elif "include_Time"  in line:
  1924.                     self.include_Time.set(line[line.find("include_Time"):].split()[1])
  1925.                 elif "halftone"  in line:
  1926.                     self.halftone.set(line[line.find("halftone"):].split()[1])
  1927.                 elif "HomeUR"  in line:
  1928.                     self.HomeUR.set(line[line.find("HomeUR"):].split()[1])                    
  1929.                 elif "inputCSYS"  in line:
  1930.                     self.inputCSYS.set(line[line.find("inputCSYS"):].split()[1])
  1931.                 elif "advanced"  in line:
  1932.                     self.advanced.set(line[line.find("advanced"):].split()[1])
  1933.                 elif "mirror"  in line:
  1934.                     self.mirror.set(line[line.find("mirror"):].split()[1])
  1935.                 elif "rotate"  in line:
  1936.                     self.rotate.set(line[line.find("rotate"):].split()[1])
  1937.                 elif "engraveUP"  in line:
  1938.                     self.engraveUP.set(line[line.find("engraveUP"):].split()[1])
  1939.                 elif "init_home"  in line:
  1940.                     self.init_home.set(line[line.find("init_home"):].split()[1])
  1941.                 elif "pre_pr_crc"  in line:
  1942.                     self.pre_pr_crc.set(line[line.find("pre_pr_crc"):].split()[1])
  1943.                 elif "inside_first"  in line:
  1944.                     self.inside_first.set(line[line.find("inside_first"):].split()[1])
  1945.        
  1946.                 # STRING.set()
  1947.                 elif "board_name" in line:
  1948.                     self.board_name.set(line[line.find("board_name"):].split()[1])
  1949.                 elif "units"    in line:
  1950.                     self.units.set(line[line.find("units"):].split()[1])
  1951.                 elif "Reng_feed"    in line:
  1952.                      self.Reng_feed .set(line[line.find("Reng_feed"):].split()[1])
  1953.                 elif "Veng_feed"    in line:
  1954.                      self.Veng_feed .set(line[line.find("Veng_feed"):].split()[1])  
  1955.                 elif "Vcut_feed"    in line:
  1956.                      self.Vcut_feed.set(line[line.find("Vcut_feed"):].split()[1])
  1957.                 elif "jog_step"    in line:
  1958.                      self.jog_step.set(line[line.find("jog_step"):].split()[1])
  1959.                      
  1960.                 elif "Reng_passes"    in line:
  1961.                      self.Reng_passes.set(line[line.find("Reng_passes"):].split()[1])
  1962.                 elif "Veng_passes"    in line:
  1963.                      self.Veng_passes.set(line[line.find("Veng_passes"):].split()[1])
  1964.                 elif "Vcut_passes"    in line:
  1965.                      self.Vcut_passes.set(line[line.find("Vcut_passes"):].split()[1])
  1966.                 elif "Gcde_passes"    in line:
  1967.                      self.Gcde_passes.set(line[line.find("Gcde_passes"):].split()[1])
  1968.  
  1969.                 elif "rast_step"    in line:
  1970.                      self.rast_step.set(line[line.find("rast_step"):].split()[1])
  1971.                 elif "ht_size"    in line:
  1972.                      self.ht_size.set(line[line.find("ht_size"):].split()[1])
  1973.  
  1974.                 elif "LaserXsize"    in line:
  1975.                      self.LaserXsize.set(line[line.find("LaserXsize"):].split()[1])
  1976.                 elif "LaserYsize"    in line:
  1977.                      self.LaserYsize.set(line[line.find("LaserYsize"):].split()[1])
  1978.                 elif "LaserXscale"    in line:
  1979.                      self.LaserXscale.set(line[line.find("LaserXscale"):].split()[1])
  1980.                 elif "LaserYscale"    in line:
  1981.                      self.LaserYscale.set(line[line.find("LaserYscale"):].split()[1])
  1982.                      
  1983.                 elif "gotoX"    in line:
  1984.                      self.gotoX.set(line[line.find("gotoX"):].split()[1])
  1985.                 elif "gotoY"    in line:
  1986.                      self.gotoY.set(line[line.find("gotoY"):].split()[1])
  1987.  
  1988.                 elif "bezier_M1"    in line:
  1989.                      self.bezier_M1.set(line[line.find("bezier_M1"):].split()[1])
  1990.                 elif "bezier_M2"    in line:
  1991.                      self.bezier_M2.set(line[line.find("bezier_M2"):].split()[1])
  1992.                 elif "bezier_weight"    in line:
  1993.                      self.bezier_weight.set(line[line.find("bezier_weight"):].split()[1])
  1994.        
  1995.                 elif "t_timeout"    in line:
  1996.                      self.t_timeout.set(line[line.find("t_timeout"):].split()[1])
  1997.                 elif "n_timeouts"    in line:
  1998.                      self.n_timeouts.set(line[line.find("n_timeouts"):].split()[1])
  1999.  
  2000.                 elif "designfile"    in line:
  2001.                        self.DESIGN_FILE=(line[line.find("designfile"):].split("\042")[1])
  2002.                 elif "inkscape_path"    in line:
  2003.                      self.inkscape_path.set(line[line.find("inkscape_path"):].split("\042")[1])
  2004.                      
  2005.         fin.close()
  2006.  
  2007.         fileName, fileExtension = os.path.splitext(self.DESIGN_FILE)
  2008.         init_file=os.path.basename(fileName)
  2009.        
  2010.         if init_file != "None":
  2011.             if ( os.path.isfile(self.DESIGN_FILE) ):
  2012.                 pass
  2013.             else:
  2014.                 self.statusMessage.set("Image file not found: %s " %(self.DESIGN_FILE))
  2015.  
  2016.         if self.units.get() == 'in':
  2017.             self.funits.set('in/min')
  2018.             self.units_scale = 1.0
  2019.         else:
  2020.             self.units.set('mm')
  2021.             self.funits.set('mm/s')
  2022.             self.units_scale = 25.4
  2023.  
  2024.         temp_name, fileExtension = os.path.splitext(filename)
  2025.         file_base=os.path.basename(temp_name)
  2026.            
  2027.         if self.initComplete == 1:
  2028.             self.menu_Mode_Change()
  2029.             self.DESIGN_FILE = filename
  2030.            
  2031.     ##########################################################################
  2032.     ##########################################################################
  2033.     def menu_File_Save(self):
  2034.         #if (self.Check_All_Variables() > 0):
  2035.         #    return
  2036.  
  2037.         settings_data = self.WriteConfig()
  2038.         init_dir = os.path.dirname(self.DESIGN_FILE)
  2039.         if ( not os.path.isdir(init_dir) ):
  2040.             init_dir = self.HOME_DIR
  2041.            
  2042.         fileName, fileExtension = os.path.splitext(self.DESIGN_FILE)
  2043.         init_file=os.path.basename(fileName)
  2044.  
  2045.         filename = asksaveasfilename(defaultextension='.txt', \
  2046.                                      filetypes=[("Text File","*.txt")],\
  2047.                                      initialdir=init_dir,\
  2048.                                      initialfile= init_file )
  2049.  
  2050.         if filename != '' and filename != ():
  2051.             try:
  2052.                 fout = open(filename,'w')
  2053.             except:
  2054.                 self.statusMessage.set("Unable to open file for writing: %s" %(filename))
  2055.                 self.statusbar.configure( bg = 'red' )
  2056.                 return
  2057.  
  2058.             for line in settings_data:
  2059.                 try:
  2060.                     fout.write(line+'\n')
  2061.                 except:
  2062.                     fout.write('(skipping line)\n')
  2063.                     debug_message(traceback.format_exc())
  2064.             fout.close
  2065.             self.statusMessage.set("File Saved: %s" %(filename))
  2066.             self.statusbar.configure( bg = 'white' )
  2067.        
  2068.     def Get_Design_Bounds(self):
  2069.         if self.rotate.get():
  2070.             ymin =  self.Design_bounds[0]
  2071.             ymax =  self.Design_bounds[1]
  2072.             xmin = -self.Design_bounds[3]
  2073.             xmax = -self.Design_bounds[2]
  2074.         else:
  2075.             xmin,xmax,ymin,ymax = self.Design_bounds
  2076.         return (xmin,xmax,ymin,ymax)
  2077.    
  2078.     def Move_UL(self,dummy=None):
  2079.         xmin,xmax,ymin,ymax = self.Get_Design_Bounds()
  2080.         if self.HomeUR.get():
  2081.             Xnew = self.laserX + (xmax-xmin)
  2082.             DX = round((xmax-xmin)*1000.0)
  2083.         else:
  2084.             Xnew = self.laserX
  2085.             DX = 0
  2086.            
  2087.         (Xsize,Ysize)=self.LASER_Size()
  2088.         if Xnew <= Xsize+.001:
  2089.             self.move_head_window_temporary([DX,0.0])
  2090.         else:
  2091.             pass
  2092.  
  2093.     def Move_UR(self,dummy=None):
  2094.         xmin,xmax,ymin,ymax = self.Get_Design_Bounds()
  2095.         if self.HomeUR.get():
  2096.             Xnew = self.laserX
  2097.             DX = 0
  2098.         else:
  2099.             Xnew = self.laserX + (xmax-xmin)
  2100.             DX = round((xmax-xmin)*1000.0)
  2101.  
  2102.         (Xsize,Ysize)=self.LASER_Size()
  2103.         if Xnew <= Xsize+.001:
  2104.             self.move_head_window_temporary([DX,0.0])
  2105.         else:
  2106.             pass
  2107.    
  2108.     def Move_LR(self,dummy=None):
  2109.         xmin,xmax,ymin,ymax = self.Get_Design_Bounds()
  2110.         if self.HomeUR.get():
  2111.             Xnew = self.laserX
  2112.             DX = 0
  2113.         else:
  2114.             Xnew = self.laserX + (xmax-xmin)
  2115.             DX = round((xmax-xmin)*1000.0)
  2116.            
  2117.         Ynew = self.laserY - (ymax-ymin)
  2118.         (Xsize,Ysize)=self.LASER_Size()
  2119.         if Xnew <= Xsize+.001 and Ynew >= -Ysize-.001:
  2120.             DY = round((ymax-ymin)*1000.0)
  2121.             self.move_head_window_temporary([DX,-DY])
  2122.         else:
  2123.             pass
  2124.    
  2125.     def Move_LL(self,dummy=None):
  2126.         xmin,xmax,ymin,ymax = self.Get_Design_Bounds()
  2127.         if self.HomeUR.get():
  2128.             Xnew = self.laserX + (xmax-xmin)
  2129.             DX = round((xmax-xmin)*1000.0)
  2130.         else:
  2131.             Xnew = self.laserX
  2132.             DX = 0
  2133.            
  2134.         Ynew = self.laserY - (ymax-ymin)
  2135.         (Xsize,Ysize)=self.LASER_Size()
  2136.         if Xnew <= Xsize+.001 and Ynew >= -Ysize-.001:
  2137.             DY = round((ymax-ymin)*1000.0)
  2138.             self.move_head_window_temporary([DX,-DY])
  2139.         else:
  2140.             pass
  2141.  
  2142.     def Move_CC(self,dummy=None):
  2143.         xmin,xmax,ymin,ymax = self.Get_Design_Bounds()
  2144.         if self.HomeUR.get():
  2145.             Xnew = self.laserX + (xmax-xmin)/2.0
  2146.             DX = round((xmax-xmin)/2.0*1000.0)
  2147.         else:
  2148.             Xnew = self.laserX + (xmax-xmin)/2.0
  2149.             DX = round((xmax-xmin)/2.0*1000.0)
  2150.  
  2151.            
  2152.         Ynew = self.laserY - (ymax-ymin)/2.0
  2153.         (Xsize,Ysize)=self.LASER_Size()
  2154.         if Xnew <= Xsize+.001 and Ynew >= -Ysize-.001:
  2155.             DY = round((ymax-ymin)/2.0*1000.0)
  2156.             self.move_head_window_temporary([DX,-DY])
  2157.         else:
  2158.             pass
  2159.  
  2160.  
  2161.     def Move_Right(self,dummy=None):
  2162.         JOG_STEP = float( self.jog_step.get() )
  2163.         self.Rapid_Move( JOG_STEP,0 )
  2164.  
  2165.     def Move_Left(self,dummy=None):
  2166.         JOG_STEP = float( self.jog_step.get() )
  2167.         self.Rapid_Move( -JOG_STEP,0 )
  2168.  
  2169.     def Move_Up(self,dummy=None):
  2170.         JOG_STEP = float( self.jog_step.get() )
  2171.         self.Rapid_Move( 0,JOG_STEP )
  2172.  
  2173.     def Move_Down(self,dummy=None):
  2174.         JOG_STEP = float( self.jog_step.get() )
  2175.         self.Rapid_Move( 0,-JOG_STEP )
  2176.  
  2177.     def Rapid_Move(self,dx,dy):
  2178.         if self.units.get()=="in":
  2179.             dx_inches = round(dx,3)
  2180.             dy_inches = round(dy,3)
  2181.         else:
  2182.             dx_inches = round(dx/25.4,3)
  2183.             dy_inches = round(dy/25.4,3)
  2184.  
  2185.         if (self.HomeUR.get()):
  2186.             dx_inches = -dx_inches
  2187.  
  2188.         Xnew,Ynew = self.XY_in_bounds(dx_inches,dy_inches)
  2189.         dxmils = (Xnew - self.laserX)*1000.0
  2190.         dymils = (Ynew - self.laserY)*1000.0
  2191.        
  2192.         self.Send_Rapid_Move(dxmils,dymils)
  2193.            
  2194.         self.laserX  = Xnew
  2195.         self.laserY  = Ynew
  2196.         self.menu_View_Refresh()
  2197.  
  2198.     def Send_Rapid_Move(self,dxmils,dymils):
  2199.         try:
  2200.             if self.k40 != None:
  2201.                 if float(self.LaserXscale.get()) != 1.0 or float(self.LaserYscale.get()) != 1.0:
  2202.                     dxmils = int(round(dxmils *float(self.LaserXscale.get())))
  2203.                     dymils = int(round(dymils *float(self.LaserYscale.get())))
  2204.                 self.k40.rapid_move(dxmils,dymils)
  2205.         except StandardError as e:
  2206.             msg1 = "Rapid Move Failed: "
  2207.             msg2 = "%s" %(e)
  2208.             if msg2 == "":
  2209.                 formatted_lines = traceback.format_exc().splitlines()
  2210.             self.statusMessage.set((msg1+msg2).split("\n")[0] )
  2211.             self.statusbar.configure( bg = 'red' )
  2212.             message_box(msg1, msg2)
  2213.             debug_message(traceback.format_exc())
  2214.  
  2215.     def update_gui(self, message=None):
  2216.         if message!=None:
  2217.             self.statusMessage.set(message)  
  2218.         self.master.update()
  2219.  
  2220.     def set_gui(self,new_state="normal"):
  2221.         self.menuBar.entryconfigure("File"    , state=new_state)
  2222.         self.menuBar.entryconfigure("View"    , state=new_state)
  2223.         self.menuBar.entryconfigure("USB"     , state=new_state)
  2224.         self.menuBar.entryconfigure("Settings", state=new_state)
  2225.         self.menuBar.entryconfigure("Help"    , state=new_state)
  2226.         self.PreviewCanvas.configure(state=new_state)
  2227.        
  2228.         for w in self.master.winfo_children():
  2229.             try:
  2230.                 w.configure(state=new_state)
  2231.             except:
  2232.                 pass
  2233.         self.Stop_Button.configure(state="normal")
  2234.         self.statusbar.configure(state="normal")
  2235.         self.master.update()
  2236.  
  2237.     def Vector_Cut(self):
  2238.         self.stop[0]=False
  2239.         self.set_gui("disabled")
  2240.         self.statusbar.configure( bg = 'green' )
  2241.         self.statusMessage.set("Vector Cut: Processing Vector Data.")
  2242.         self.master.update()
  2243.         if self.VcutData.ecoords!=[]:
  2244.             self.send_data("Vector_Cut")
  2245.         else:
  2246.             self.statusbar.configure( bg = 'yellow' )
  2247.             self.statusMessage.set("No vector data to cut")
  2248.         self.set_gui("normal")
  2249.        
  2250.     def Vector_Eng(self):
  2251.         self.stop[0]=False
  2252.         self.set_gui("disabled")
  2253.         self.statusbar.configure( bg = 'green' )
  2254.         self.statusMessage.set("Vector Engrave: Processing Vector Data.")
  2255.         self.master.update()
  2256.         if self.VengData.ecoords!=[]:
  2257.             self.send_data("Vector_Eng")
  2258.         else:
  2259.             self.statusbar.configure( bg = 'yellow' )
  2260.             self.statusMessage.set("No vector data to engrave")
  2261.         self.set_gui("normal")
  2262.  
  2263.     def Raster_Eng(self):
  2264.         self.stop[0]=False
  2265.         self.set_gui("disabled")
  2266.         self.statusbar.configure( bg = 'green' )
  2267.         self.statusMessage.set("Raster Engraving: Processing Image Data.")
  2268.         self.master.update()
  2269.         try:
  2270.             self.make_raster_coords()
  2271.             if self.RengData.ecoords!=[]:
  2272.                 self.send_data("Raster_Eng")
  2273.             else:
  2274.                 self.statusbar.configure( bg = 'yellow' )
  2275.                 self.statusMessage.set("No raster data to engrave")
  2276.         except StandardError as e:
  2277.             msg1 = "Making Raster Data Stopped: "
  2278.             msg2 = "%s" %(e)
  2279.             self.statusMessage.set((msg1+msg2).split("\n")[0] )
  2280.             self.statusbar.configure( bg = 'red' )
  2281.             message_box(msg1, msg2)
  2282.             debug_message(traceback.format_exc())
  2283.         self.set_gui("normal")
  2284.  
  2285.  
  2286.     def Gcode_Cut(self):
  2287.         self.stop[0]=False
  2288.         self.set_gui("disabled")
  2289.         self.statusbar.configure( bg = 'green' )
  2290.         self.statusMessage.set("G Code Cutting.")
  2291.         self.master.update()
  2292.         if self.GcodeData.ecoords!=[]:
  2293.             self.send_data("Gcode_Cut")
  2294.         else:
  2295.             self.statusbar.configure( bg = 'yellow' )
  2296.             self.statusMessage.set("No g-code data to cut")
  2297.         self.set_gui("normal")
  2298.  
  2299.  
  2300.     ################################################################################
  2301.     def Sort_Paths(self,ecoords,i_loop=2):
  2302.         ##########################
  2303.         ###   find loop ends   ###
  2304.         ##########################
  2305.         Lbeg=[]
  2306.         Lend=[]
  2307.         if len(ecoords)>0:
  2308.             Lbeg.append(0)
  2309.             loop_old=ecoords[0][i_loop]
  2310.             for i in range(1,len(ecoords)):
  2311.                 loop = ecoords[i][i_loop]
  2312.                 if loop != loop_old:
  2313.                     Lbeg.append(i)
  2314.                     Lend.append(i-1)
  2315.                 loop_old=loop
  2316.             Lend.append(i)
  2317.  
  2318.         #######################################################
  2319.         # Find new order based on distance to next beg or end #
  2320.         #######################################################
  2321.         order_out = []
  2322.         use_beg=0
  2323.         if len(ecoords)>0:
  2324.             order_out.append([Lbeg[0],Lend[0]])
  2325.         inext = 0
  2326.         total=len(Lbeg)
  2327.         for i in range(total-1):
  2328.             if use_beg==1:
  2329.                 ii=Lbeg.pop(inext)
  2330.                 Lend.pop(inext)
  2331.             else:
  2332.                 ii=Lend.pop(inext)
  2333.                 Lbeg.pop(inext)
  2334.  
  2335.             Xcur = ecoords[ii][0]
  2336.             Ycur = ecoords[ii][1]
  2337.  
  2338.             dx = Xcur - ecoords[ Lbeg[0] ][0]
  2339.             dy = Ycur - ecoords[ Lbeg[0] ][1]
  2340.             min_dist = dx*dx + dy*dy
  2341.  
  2342.             dxe = Xcur - ecoords[ Lend[0] ][0]
  2343.             dye = Ycur - ecoords[ Lend[0] ][1]
  2344.             min_diste = dxe*dxe + dye*dye
  2345.  
  2346.             inext=0
  2347.             inexte=0
  2348.             for j in range(1,len(Lbeg)):
  2349.                 dx = Xcur - ecoords[ Lbeg[j] ][0]
  2350.                 dy = Ycur - ecoords[ Lbeg[j] ][1]
  2351.                 dist = dx*dx + dy*dy
  2352.                 if dist < min_dist:
  2353.                     min_dist=dist
  2354.                     inext=j
  2355.                 ###
  2356.                 dxe = Xcur - ecoords[ Lend[j] ][0]
  2357.                 dye = Ycur - ecoords[ Lend[j] ][1]
  2358.                 diste = dxe*dxe + dye*dye
  2359.                 if diste < min_diste:
  2360.                     min_diste=diste
  2361.                     inexte=j
  2362.                 ###
  2363.             if min_diste < min_dist:
  2364.                 inext=inexte
  2365.                 order_out.append([Lend[inexte],Lbeg[inexte]])
  2366.                 use_beg=1
  2367.             else:
  2368.                 order_out.append([Lbeg[inext],Lend[inext]])
  2369.                 use_beg=0
  2370.         ###########################################################
  2371.         return order_out
  2372.    
  2373.     #####################################################
  2374.     # determine if a point is inside a given polygon or not
  2375.     # Polygon is a list of (x,y) pairs.
  2376.     # http://www.ariel.com.au/a/python-point-int-poly.html
  2377.     #####################################################
  2378.     def point_inside_polygon(self,x,y,poly):
  2379.         n = len(poly)
  2380.         inside = -1
  2381.         p1x = poly[0][0]
  2382.         p1y = poly[0][1]
  2383.         for i in range(n+1):
  2384.             p2x = poly[i%n][0]
  2385.             p2y = poly[i%n][1]
  2386.             if y > min(p1y,p2y):
  2387.                 if y <= max(p1y,p2y):
  2388.                     if x <= max(p1x,p2x):
  2389.                         if p1y != p2y:
  2390.                             xinters = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
  2391.                         if p1x == p2x or x <= xinters:
  2392.                             inside = inside * -1
  2393.             p1x,p1y = p2x,p2y
  2394.  
  2395.         return inside
  2396.  
  2397.     def optimize_paths(self,ecoords):
  2398.         order_out = self.Sort_Paths(ecoords)
  2399.         lastx=-999
  2400.         lasty=-999
  2401.         Acc=0.004
  2402.         cuts=[]
  2403.  
  2404.         for line in order_out:
  2405.             temp=line
  2406.             if temp[0] > temp[1]:
  2407.                 step = -1
  2408.             else:
  2409.                 step = 1
  2410.  
  2411.             loop_old = -1
  2412.            
  2413.             for i in range(temp[0],temp[1]+step,step):
  2414.                 x1   = ecoords[i][0]
  2415.                 y1   = ecoords[i][1]
  2416.                 loop = ecoords[i][2]
  2417.                 # check and see if we need to move to a new discontinuous start point
  2418.                 if (loop != loop_old):
  2419.                     dx = x1-lastx
  2420.                     dy = y1-lasty
  2421.                     dist = sqrt(dx*dx + dy*dy)
  2422.                     if dist > Acc:
  2423.                         cuts.append([[x1,y1]])
  2424.                     else:
  2425.                         cuts[-1].append([x1,y1])
  2426.                 else:
  2427.                     cuts[-1].append([x1,y1])
  2428.                 lastx = x1
  2429.                 lasty = y1
  2430.                 loop_old = loop
  2431.         #####################################################
  2432.         # For each loop determine if other loops are inside #
  2433.         #####################################################
  2434.         Nloops=len(cuts)
  2435.         self.LoopTree=[]
  2436.         for iloop in range(Nloops):
  2437.             self.LoopTree.append([])
  2438. ##            CUR_PCT=float(iloop)/Nloops*100.0
  2439. ##            if (not self.batch.get()):
  2440. ##                self.statusMessage.set('Determining Which Side of Loop to Cut: %d of %d' %(iloop+1,Nloops))
  2441. ##                self.master.update()
  2442.             ipoly = cuts[iloop]
  2443.             ## Check points in other loops (could just check one) ##
  2444.             if ipoly != []:
  2445.                 for jloop in range(Nloops):
  2446.                     if jloop != iloop:
  2447.                         inside = 0
  2448.                         inside = inside + self.point_inside_polygon(cuts[jloop][0][0],cuts[jloop][0][1],ipoly)
  2449.                         if inside > 0:
  2450.                             self.LoopTree[iloop].append(jloop)
  2451.         #####################################################
  2452.         for i in range(Nloops):
  2453.             lns=[]
  2454.             lns.append(i)
  2455.             self.remove_self_references(lns,self.LoopTree[i])
  2456.  
  2457.         self.order=[]
  2458.         self.loops = range(Nloops)
  2459.         for i in range(Nloops):
  2460.             if self.LoopTree[i]!=[]:
  2461.                 self.addlist(self.LoopTree[i])
  2462.                 self.LoopTree[i]=[]
  2463.             if self.loops[i]!=[]:
  2464.                 self.order.append(self.loops[i])
  2465.                 self.loops[i]=[]
  2466.         ecoords_out = []
  2467.         for i in self.order:
  2468.             line = cuts[i]
  2469.             for coord in line:
  2470.                 ecoords_out.append([coord[0],coord[1],i])
  2471.         return ecoords_out
  2472.            
  2473.     def remove_self_references(self,loop_numbers,loops):
  2474.         for i in range(0,len(loops)):
  2475.             for j in range(0,len(loop_numbers)):
  2476.                 if loops[i]==loop_numbers[j]:
  2477.                     loops.pop(i)
  2478.                     return
  2479.             if self.LoopTree[loops[i]]!=[]:
  2480.                 loop_numbers.append(loops[i])
  2481.                 self.remove_self_references(loop_numbers,self.LoopTree[loops[i]])
  2482.  
  2483.     def addlist(self,list):
  2484.         for i in list:
  2485.             try: #this try/except is a bad hack fix to a recursion error. It should be fixed properly later.
  2486.                 if self.LoopTree[i]!=[]:
  2487.                     self.addlist(self.LoopTree[i]) #too many recursions here causes cmp error
  2488.                     self.LoopTree[i]=[]
  2489.             except:
  2490.                 pass
  2491.             if self.loops[i]!=[]:
  2492.                 self.order.append(self.loops[i])
  2493.                 self.loops[i]=[]
  2494.  
  2495.  
  2496.     def mirror_rotate_vector_coords(self,coords):
  2497.         xmin = self.Design_bounds[0]
  2498.         xmax = self.Design_bounds[1]
  2499.         coords_rotate_mirror=[]
  2500.        
  2501.         for i in range(len(coords)):
  2502.             coords_rotate_mirror.append(coords[i][:])
  2503.             if self.mirror.get():
  2504.                 coords_rotate_mirror[i][0]=xmin+xmax-coords_rotate_mirror[i][0]
  2505.             if self.rotate.get():
  2506.                 x = coords_rotate_mirror[i][0]
  2507.                 y = coords_rotate_mirror[i][1]
  2508.                 coords_rotate_mirror[i][0] = -y
  2509.                 coords_rotate_mirror[i][1] =  x
  2510.                
  2511.         return coords_rotate_mirror
  2512.  
  2513.     def scale_vector_coords(self,coords,startx,starty):
  2514.         Xscale = float(self.LaserXscale.get())
  2515.         Yscale = float(self.LaserYscale.get())
  2516.         coords_scale=[]
  2517.         if Xscale != 1.0 or Yscale != 1.0:
  2518.             for i in range(len(coords)):
  2519.                 coords_scale.append(coords[i][:])
  2520.                 x = coords_scale[i][0]
  2521.                 y = coords_scale[i][1]
  2522.                 coords_scale[i][0] = x*Xscale
  2523.                 coords_scale[i][1] = y*Yscale
  2524.             scaled_startx = startx*Xscale
  2525.             scaled_starty = starty*Yscale
  2526.         else:
  2527.             coords_scale = coords
  2528.             scaled_startx = startx
  2529.             scaled_starty = starty
  2530.  
  2531.         return coords_scale,scaled_startx,scaled_starty
  2532.  
  2533.     def send_data(self,operation_type=None):
  2534.         if self.k40 == None:
  2535.             self.statusMessage.set("Laser Cutter is not Initialized...")
  2536.             self.statusbar.configure( bg = 'red' )
  2537.             return
  2538.        
  2539.         try:
  2540.             if self.units.get()=='in':
  2541.                 feed_factor = 25.4/60.0
  2542.             else:
  2543.                 feed_factor = 1.0
  2544.                
  2545.             if self.inputCSYS.get() and self.RengData.image == None:
  2546.                 xmin,xmax,ymin,ymax = 0.0,0.0,0.0,0.0
  2547.             else:
  2548.                 xmin,xmax,ymin,ymax = self.Get_Design_Bounds()
  2549.            
  2550.  
  2551.             self.move_head_window_temporary([0,0])
  2552.             startx = xmin
  2553.             starty = ymax
  2554.  
  2555.             if self.HomeUR.get():
  2556.                 FlipXoffset = abs(xmax-xmin)
  2557.                 if self.rotate.get():
  2558.                     startx = -xmin
  2559.             else:
  2560.                 FlipXoffset = 0
  2561.            
  2562.             data=[]
  2563.             egv_inst = egv(target=lambda s:data.append(s))
  2564.            
  2565.             if (operation_type=="Vector_Cut") and  (self.VcutData.ecoords!=[]):
  2566.                 num_passes = int(self.Vcut_passes.get())
  2567.                 Feed_Rate = float(self.Vcut_feed.get())*feed_factor
  2568.                 self.statusMessage.set("Vector Cut: Determining Cut Order....")
  2569.                 self.master.update()
  2570.                 if not self.VcutData.sorted and self.inside_first.get():
  2571.                     self.VcutData.set_ecoords(self.optimize_paths(self.VcutData.ecoords),data_sorted=True)
  2572.                 self.statusMessage.set("Generating EGV data...")
  2573.                 self.master.update()
  2574.  
  2575.                 Vcut_coords = self.VcutData.ecoords
  2576.                 if self.mirror.get() or self.rotate.get():
  2577.                     Vcut_coords = self.mirror_rotate_vector_coords(Vcut_coords)
  2578.  
  2579.                 Vcut_coords,startx,starty = self.scale_vector_coords(Vcut_coords,startx,starty)
  2580.                    
  2581.                 egv_inst.make_egv_data(
  2582.                                                 Vcut_coords,                      \
  2583.                                                 startX=startx,                    \
  2584.                                                 startY=starty,                    \
  2585.                                                 Feed = Feed_Rate,                 \
  2586.                                                 board_name=self.board_name.get(), \
  2587.                                                 Raster_step = 0,                  \
  2588.                                                 update_gui=self.update_gui,       \
  2589.                                                 stop_calc=self.stop,              \
  2590.                                                 FlipXoffset=FlipXoffset
  2591.                                                 )
  2592.  
  2593.  
  2594.             if (operation_type=="Vector_Eng") and  (self.VengData.ecoords!=[]):
  2595.                 num_passes = int(self.Veng_passes.get())
  2596.                 Feed_Rate = float(self.Veng_feed.get())*feed_factor
  2597.                 self.statusMessage.set("Vector Engrave: Determining Cut Order....")
  2598.                 self.master.update()
  2599.                 if not self.VengData.sorted and self.inside_first.get():
  2600.                     self.VengData.set_ecoords(self.optimize_paths(self.VengData.ecoords),data_sorted=True)
  2601.                 self.statusMessage.set("Generating EGV data...")
  2602.                 self.master.update()
  2603.  
  2604.                 Veng_coords = self.VengData.ecoords
  2605.                 if self.mirror.get() or self.rotate.get():
  2606.                     Veng_coords = self.mirror_rotate_vector_coords(Veng_coords)
  2607.  
  2608.                 Veng_coords,startx,starty = self.scale_vector_coords(Veng_coords,startx,starty)
  2609.                    
  2610.                 egv_inst.make_egv_data(
  2611.                                                 Veng_coords,                      \
  2612.                                                 startX=startx,                    \
  2613.                                                 startY=starty,                    \
  2614.                                                 Feed = Feed_Rate,                 \
  2615.                                                 board_name=self.board_name.get(), \
  2616.                                                 Raster_step = 0,                  \
  2617.                                                 update_gui=self.update_gui,       \
  2618.                                                 stop_calc=self.stop,              \
  2619.                                                 FlipXoffset=FlipXoffset
  2620.                                                 )
  2621.  
  2622.             if (operation_type=="Raster_Eng") and  (self.RengData.ecoords!=[]):
  2623.                 num_passes = int(self.Reng_passes.get())
  2624.                 Feed_Rate = float(self.Reng_feed.get())*feed_factor
  2625.                 Raster_step = self.get_raster_step_1000in()
  2626.                 if not self.engraveUP.get():
  2627.                     Raster_step = -Raster_step
  2628.                    
  2629.                 raster_startx = 0
  2630.                 raster_starty = float(self.LaserYscale.get())*starty
  2631.  
  2632.                 self.statusMessage.set("Generating EGV data...")
  2633.                 self.master.update()
  2634.                 egv_inst.make_egv_data(
  2635.                                                 self.RengData.ecoords,            \
  2636.                                                 startX=raster_startx,             \
  2637.                                                 startY=raster_starty,             \
  2638.                                                 Feed = Feed_Rate,                 \
  2639.                                                 board_name=self.board_name.get(), \
  2640.                                                 Raster_step = Raster_step,        \
  2641.                                                 update_gui=self.update_gui,       \
  2642.                                                 stop_calc=self.stop,              \
  2643.                                                 FlipXoffset=FlipXoffset
  2644.                                                 )
  2645.                
  2646.                 self.Reng=[]
  2647.  
  2648.             if (operation_type=="Gcode_Cut") and (self.GcodeData!=[]):
  2649.                 num_passes = int(self.Gcde_passes.get())
  2650.                 self.statusMessage.set("Generating EGV data...")
  2651.                 self.master.update()
  2652.  
  2653.                 Gcode_coords = self.GcodeData.ecoords
  2654.                 if self.mirror.get() or self.rotate.get():
  2655.                     Gcode_coords = self.mirror_rotate_vector_coords(Gcode_coords)
  2656.  
  2657.                 Gcode_coords,startx,starty = self.scale_vector_coords(Gcode_coords,startx,starty)
  2658.                
  2659.                 egv_inst.make_egv_data(
  2660.                                                 Gcode_coords,                     \
  2661.                                                 startX=startx,                    \
  2662.                                                 startY=starty,                    \
  2663.                                                 Feed = None,                      \
  2664.                                                 board_name=self.board_name.get(), \
  2665.                                                 Raster_step = 0,                  \
  2666.                                                 update_gui=self.update_gui,       \
  2667.                                                 stop_calc=self.stop,              \
  2668.                                                 FlipXoffset=FlipXoffset
  2669.                                                 )
  2670.                
  2671.             self.master.update()
  2672.             self.send_egv_data(data, num_passes)
  2673.             self.menu_View_Refresh()
  2674.         except MemoryError as e:
  2675.             raise StandardError("Memory Error:  Out of Memory.")
  2676.             debug_message(traceback.format_exc())
  2677.        
  2678.         except StandardError as e:
  2679.             msg1 = "Sending Data Stopped: "
  2680.             msg2 = "%s" %(e)
  2681.             if msg2 == "":
  2682.                 formatted_lines = traceback.format_exc().splitlines()
  2683.             self.statusMessage.set((msg1+msg2).split("\n")[0] )
  2684.             self.statusbar.configure( bg = 'red' )
  2685.             message_box(msg1, msg2)
  2686.             debug_message(traceback.format_exc())
  2687.  
  2688.     def send_egv_data(self,data,num_passes=1):
  2689.         pre_process_CRC        = self.pre_pr_crc.get()
  2690.         if self.k40 != None:
  2691.             self.k40.timeout       = int(self.t_timeout.get())  
  2692.             self.k40.n_timeouts    = int(self.n_timeouts.get())
  2693.             self.k40.send_data(data,self.update_gui,self.stop,num_passes,pre_process_CRC)
  2694.         else:
  2695.             self.master.update()
  2696.        
  2697.         if DEBUG:
  2698.             print "Saving Data to File...."
  2699.             self.write_egv_to_file(data)
  2700.         #self.set_gui("normal")
  2701.         self.menu_View_Refresh()
  2702.        
  2703.     ##########################################################################
  2704.     ##########################################################################
  2705.     def write_egv_to_file(self,data):
  2706.         try:
  2707.             fname = os.path.expanduser("~")+"/EGV_DATA.EGV"
  2708.             fout = open(fname,'w')
  2709.         except:
  2710.             self.statusMessage.set("Unable to open file for writing: %s" %(fname))
  2711.             return
  2712.         for char_val in data:
  2713.             char = chr(char_val)
  2714.             if char == "N":
  2715.                 fout.write("\n")
  2716.                 fout.write("%s" %(char))
  2717.             elif char == "E":
  2718.                 fout.write("%s" %(char))
  2719.                 fout.write("\n")
  2720.             else:
  2721.                 fout.write("%s" %(char))
  2722.         fout.write("\n")
  2723.         fout.close
  2724.        
  2725.     def Home(self):
  2726.         if self.k40 != None:
  2727.             self.k40.home_position()
  2728.         self.laserX  = 0.0
  2729.         self.laserY  = 0.0
  2730.         self.pos_offset = [0.0,0.0]
  2731.         self.menu_View_Refresh()
  2732.  
  2733.     def GoTo(self):
  2734.         xpos = float(self.gotoX.get())
  2735.         ypos = float(self.gotoY.get())
  2736.         if self.k40 != None:
  2737.             self.k40.home_position()
  2738.         self.laserX  = 0.0
  2739.         self.laserY  = 0.0
  2740.         self.Rapid_Move(xpos,ypos)
  2741.         self.menu_View_Refresh()  
  2742.        
  2743.     def Reset(self):
  2744.         if self.k40 != None:
  2745.             try:
  2746.                 self.k40.reset_usb()
  2747.                 self.statusMessage.set("USB Reset Succeeded")
  2748.             except:
  2749.                 debug_message(traceback.format_exc())
  2750.                 pass
  2751.            
  2752.     def Stop(self,event=None):
  2753.         line1 = "The K40 Whisperer is currently Paused."
  2754.         line2 = "Press \"OK\" to stop current action."
  2755.         line3 = "Press \"Cancel\" to resume."
  2756.         if message_ask_ok_cancel("Stop Laser Job.", "%s\n\n%s\n%s" %(line1,line2,line3)):
  2757.             self.stop[0]=True
  2758.  
  2759.     def Hide_Advanced(self,event=None):
  2760.         self.advanced.set(0)
  2761.         self.menu_View_Refresh()
  2762.  
  2763.     def Release_USB(self):
  2764.         if self.k40 != None:
  2765.             try:
  2766.                 self.k40.release_usb()
  2767.                 self.statusMessage.set("USB Release Succeeded")
  2768.             except:
  2769.                 debug_message(traceback.format_exc())
  2770.                 pass
  2771.             self.k40=None
  2772.        
  2773.     def Initialize_Laser(self,junk=None):
  2774.         self.stop[0]=False
  2775.         self.Release_USB()
  2776.         self.k40=None
  2777.         self.move_head_window_temporary([0.0,0.0])      
  2778.         self.k40=K40_CLASS()
  2779.         try:
  2780.             self.k40.initialize_device()
  2781.             self.k40.say_hello()
  2782.             if self.init_home.get():
  2783.                 self.Home()
  2784.             else:
  2785.                 self.Unlock()
  2786.            
  2787.         except StandardError as e:
  2788.             error_text = "%s" %(e)
  2789.             if "BACKEND" in error_text.upper():
  2790.                 error_text = error_text + " (libUSB driver not installed)"
  2791.             self.statusMessage.set("USB Error: %s" %(error_text))
  2792.             self.statusbar.configure( bg = 'red' )
  2793.             self.k40=None
  2794.             debug_message(traceback.format_exc())
  2795.  
  2796.         except:
  2797.             self.statusMessage.set("Unknown USB Error")
  2798.             self.statusbar.configure( bg = 'red' )
  2799.             self.k40=None
  2800.             debug_message(traceback.format_exc())
  2801.            
  2802.     def Unlock(self):
  2803.         if self.k40 != None:
  2804.             try:
  2805.                 self.k40.unlock_rail()
  2806.                 self.statusMessage.set("Rail Unlock Succeeded")
  2807.                 self.statusbar.configure( bg = 'white' )
  2808.             except:
  2809.                 self.statusMessage.set("Rail Unlock Failed.")
  2810.                 self.statusbar.configure( bg = 'red' )
  2811.                 debug_message(traceback.format_exc())
  2812.                 pass
  2813.    
  2814.     ##########################################################################
  2815.     ##########################################################################
  2816.            
  2817.     def menu_File_Quit(self):
  2818.         if message_ask_ok_cancel("Exit", "Exiting...."):
  2819.             self.Quit_Click(None)
  2820.  
  2821.     def menu_View_Mirror_Refresh_Callback(self, varName, index, mode):
  2822.         self.RengData.reset_path()
  2823.         self.SCALE = 0
  2824.         self.menu_View_Refresh()
  2825.  
  2826.     def menu_View_inputCSYS_Refresh_Callback(self, varName, index, mode):
  2827.         self.move_head_window_temporary([0.0,0.0])
  2828.         self.SCALE = 0
  2829.         self.menu_View_Refresh()
  2830.  
  2831.     def menu_View_Refresh_Callback(self, varName, index, mode):
  2832.         self.SCALE = 0
  2833.         self.menu_View_Refresh()
  2834.  
  2835.     def menu_View_Refresh(self):
  2836.         try:
  2837.             app.master.title(title_text+"   "+ self.DESIGN_FILE)
  2838.         except:
  2839.             pass
  2840.         dummy_event = Event()
  2841.         dummy_event.widget=self.master
  2842.         self.Master_Configure(dummy_event,1)
  2843.         self.Plot_Data()
  2844.         xmin,xmax,ymin,ymax = self.Get_Design_Bounds()
  2845.         W = xmax-xmin
  2846.         H = ymax-ymin
  2847.  
  2848.         if self.units.get()=="in":
  2849.             X_display = self.laserX + self.pos_offset[0]/1000.0
  2850.             Y_display = self.laserY + self.pos_offset[1]/1000.0
  2851.             W_display = W
  2852.             H_display = H
  2853.             U_display = self.units.get()
  2854.         else:
  2855.             X_display = (self.laserX + self.pos_offset[0]/1000.0)*self.units_scale
  2856.             Y_display = (self.laserY + self.pos_offset[1]/1000.0)*self.units_scale
  2857.             W_display = W*self.units_scale
  2858.             H_display = H*self.units_scale
  2859.             U_display = self.units.get()
  2860.         if self.HomeUR.get():
  2861.             X_display = -X_display
  2862.  
  2863.         self.statusMessage.set(" Current Position: X=%.3f Y=%.3f    ( W X H )=( %.3f%s X %.3f%s ) "
  2864.                                 %(X_display,
  2865.                                   Y_display,
  2866.                                   W_display,
  2867.                                   U_display,
  2868.                                   H_display,
  2869.                                   U_display))
  2870.  
  2871.         self.statusbar.configure( bg = 'white' )
  2872.        
  2873.     def menu_Mode_Change_Callback(self, varName, index, mode):
  2874.         self.menu_View_Refresh()
  2875.  
  2876.     def menu_Inside_First_Callback(self, varName, index, mode):
  2877.         if self.GcodeData.ecoords != []:
  2878.             if self.VcutData.sorted == True:
  2879.                 self.menu_Reload_Design()
  2880.             elif self.VengData.sorted == True:
  2881.                 self.menu_Reload_Design()
  2882.        
  2883.  
  2884.     def menu_Mode_Change(self):
  2885.         dummy_event = Event()
  2886.         dummy_event.widget=self.master
  2887.         self.Master_Configure(dummy_event,1)
  2888.  
  2889.     def menu_View_Recalculate(self):
  2890.         pass
  2891.  
  2892.     def menu_Help_About(self):
  2893.         about = "K40 Whisperer by Scorch.\n"
  2894.         about = about + "\163\143\157\162\143\150\100\163\143\157\162"
  2895.         about = about + "\143\150\167\157\162\153\163\056\143\157\155\n"
  2896.         about = about + "http://www.scorchworks.com/"
  2897.         message_box("About k40_whisperer",about)
  2898.  
  2899.     def menu_Help_Web(self):
  2900.         webbrowser.open_new(r"http://www.scorchworks.com/K40whisperer/k40whisperer.html")
  2901.  
  2902.     def KEY_F1(self, event):
  2903.         self.menu_Help_About()
  2904.  
  2905.     def KEY_F5(self, event):
  2906.         self.menu_View_Refresh()
  2907.  
  2908.     def bindConfigure(self, event):
  2909.         if not self.initComplete:
  2910.             self.initComplete = 1
  2911.             self.menu_Mode_Change()
  2912.  
  2913.     def Master_Configure(self, event, update=0):
  2914.         if event.widget != self.master:
  2915.             return
  2916.         x = int(self.master.winfo_x())
  2917.         y = int(self.master.winfo_y())
  2918.         w = int(self.master.winfo_width())
  2919.         h = int(self.master.winfo_height())
  2920.         if (self.x, self.y) == (-1,-1):
  2921.             self.x, self.y = x,y
  2922.         if abs(self.w-w)>10 or abs(self.h-h)>10 or update==1:
  2923.             ###################################################
  2924.             #  Form changed Size (resized) adjust as required #
  2925.             ###################################################
  2926.             self.w=w
  2927.             self.h=h
  2928.  
  2929.             if True:                
  2930.                 # Left Column #
  2931.                 w_label=90
  2932.                 w_entry=48
  2933.                 w_units=52
  2934.  
  2935.                 x_label_L=10
  2936.                 x_entry_L=x_label_L+w_label+20-5
  2937.                 x_units_L=x_entry_L+w_entry+2
  2938.  
  2939.                 Yloc=15
  2940.                 self.Initialize_Button.place (x=12, y=Yloc, width=100*2, height=23)
  2941.                 Yloc=Yloc+33
  2942.  
  2943.                 self.Open_Button.place (x=12, y=Yloc, width=100, height=40)
  2944.                 self.Reload_Button.place(x=12+100, y=Yloc, width=100, height=40)                
  2945.  
  2946.                 Yloc=Yloc+50
  2947.                 self.separator1.place(x=x_label_L, y=Yloc,width=w_label+75+40, height=2)
  2948.                 Yloc=Yloc+6
  2949.                 self.Label_Position_Control.place(x=x_label_L, y=Yloc, width=w_label*2, height=21)
  2950.  
  2951.                 Yloc=Yloc+25
  2952.                 self.Home_Button.place (x=12, y=Yloc, width=100, height=23)
  2953.                 self.UnLock_Button.place(x=12+100, y=Yloc, width=100, height=23)
  2954.  
  2955.                 Yloc=Yloc+33
  2956.                 self.Label_Step.place(x=x_label_L, y=Yloc, width=w_label, height=21)
  2957.                 self.Label_Step_u.place(x=x_units_L, y=Yloc, width=w_units, height=21)
  2958.                 self.Entry_Step.place(x=x_entry_L, y=Yloc, width=w_entry, height=23)
  2959.  
  2960.                 ###########################################################################
  2961.                 Yloc=Yloc+30
  2962.                 bsz=40
  2963.                 xoffst=35
  2964.                 self.UL_Button.place    (x=xoffst+12      ,  y=Yloc, width=bsz, height=bsz)
  2965.                 self.Up_Button.place    (x=xoffst+12+bsz  ,  y=Yloc, width=bsz, height=bsz)
  2966.                 self.UR_Button.place    (x=xoffst+12+bsz*2,  y=Yloc, width=bsz, height=bsz)
  2967.                 Yloc=Yloc+bsz
  2968.                 self.Left_Button.place  (x=xoffst+12      ,y=Yloc, width=bsz, height=bsz)
  2969.                 self.CC_Button.place    (x=xoffst+12+bsz  ,y=Yloc, width=bsz, height=bsz)
  2970.                 self.Right_Button.place (x=xoffst+12+bsz*2,y=Yloc, width=bsz, height=bsz)
  2971.                 Yloc=Yloc+bsz
  2972.                 self.LL_Button.place    (x=xoffst+12      ,  y=Yloc, width=bsz, height=bsz)
  2973.                 self.Down_Button.place  (x=xoffst+12+bsz  ,  y=Yloc, width=bsz, height=bsz)
  2974.                 self.LR_Button.place    (x=xoffst+12+bsz*2,  y=Yloc, width=bsz, height=bsz)
  2975.            
  2976.                
  2977.                 Yloc=Yloc+bsz
  2978.                 ###########################################################################
  2979.                 self.Label_GoToX.place(x=x_entry_L, y=Yloc, width=w_entry, height=23)
  2980.                 self.Label_GoToY.place(x=x_units_L, y=Yloc, width=w_entry, height=23)
  2981.                 Yloc=Yloc+25
  2982.                 self.GoTo_Button.place (x=12, y=Yloc, width=100, height=23)
  2983.                 self.Entry_GoToX.place(x=x_entry_L, y=Yloc, width=w_entry, height=23)
  2984.                 self.Entry_GoToY.place(x=x_units_L, y=Yloc, width=w_entry, height=23)
  2985.                 ###########################################################################
  2986.                            
  2987.  
  2988.                 #From Bottom up
  2989.                 BUinit = self.h-70
  2990.                 Yloc = BUinit
  2991.                 self.Stop_Button.place (x=12, y=Yloc, width=100*2, height=30)
  2992.                
  2993.                 self.Stop_Button.configure(bg='light coral')
  2994.                 Yloc=Yloc-10
  2995.  
  2996.                 wadv       = 220 #200
  2997.                 wadv_use   = wadv-20
  2998.                 Xvert_sep  = 220
  2999.                 Xadvanced  = Xvert_sep+10
  3000.                 w_label_adv= wadv-80 #  110 w_entry
  3001.  
  3002.                 if self.GcodeData.ecoords == []:
  3003.                     self.Grun_Button.place_forget()
  3004.                    
  3005.                     Yloc=Yloc-30
  3006.                     self.Vcut_Button.place  (x=12, y=Yloc, width=100, height=23)
  3007.                     self.Entry_Vcut_feed.place(  x=x_entry_L, y=Yloc, width=w_entry, height=23)
  3008.                     self.Label_Vcut_feed_u.place(x=x_units_L, y=Yloc, width=w_units, height=23)
  3009.  
  3010.                     Yloc=Yloc-30
  3011.                     self.Veng_Button.place  (x=12, y=Yloc, width=100, height=23)
  3012.                     self.Entry_Veng_feed.place(  x=x_entry_L, y=Yloc, width=w_entry, height=23)
  3013.                     self.Label_Veng_feed_u.place(x=x_units_L, y=Yloc, width=w_units, height=23)
  3014.                        
  3015.                     Yloc=Yloc-30
  3016.                     self.Reng_Button.place  (x=12, y=Yloc, width=100, height=23)
  3017.                     self.Entry_Reng_feed.place(  x=x_entry_L, y=Yloc, width=w_entry, height=23)
  3018.                     self.Label_Reng_feed_u.place(x=x_units_L, y=Yloc, width=w_units, height=23)  
  3019.                    
  3020.                 else:
  3021.                     self.Vcut_Button.place_forget()
  3022.                     self.Entry_Vcut_feed.place_forget()
  3023.                     self.Label_Vcut_feed_u.place_forget()
  3024.                    
  3025.                     self.Veng_Button.place_forget()
  3026.                     self.Entry_Veng_feed.place_forget()
  3027.                     self.Label_Veng_feed_u.place_forget()
  3028.                    
  3029.                     self.Reng_Button.place_forget()
  3030.                     self.Entry_Reng_feed.place_forget()
  3031.                     self.Label_Reng_feed_u.place_forget()
  3032.                    
  3033.                     Yloc=Yloc-30
  3034.                     self.Grun_Button.place  (x=12, y=Yloc, width=100*2, height=23)
  3035.                    
  3036.                
  3037.                 Yloc=Yloc-15
  3038.                 self.separator2.place(x=x_label_L, y=Yloc,width=w_label+75+40, height=2)
  3039.                 # End Left Column #
  3040.  
  3041.                 if self.advanced.get():
  3042.                    
  3043.                     self.PreviewCanvas.configure( width = self.w-240-wadv, height = self.h-50 )
  3044.                     self.PreviewCanvas_frame.place(x=220+wadv, y=10)
  3045.                     self.separator_vert.place(x=220, y=10,width=2, height=self.h-50)
  3046.  
  3047.                     adv_Yloc=15
  3048.                     self.Label_Advanced_column.place(x=Xadvanced, y=adv_Yloc, width=wadv_use, height=21)
  3049.                     adv_Yloc=adv_Yloc+25
  3050.                     self.separator_adv.place(x=Xadvanced, y=adv_Yloc,width=wadv_use, height=2)
  3051.  
  3052.                     adv_Yloc=adv_Yloc+15
  3053.                     self.Label_Halftone_adv.place(x=Xadvanced, y=adv_Yloc, width=w_label_adv, height=21)
  3054.                     self.Checkbutton_Halftone_adv.place(x=Xadvanced+w_label_adv+2, y=adv_Yloc, width=25, height=23)
  3055.  
  3056.                     adv_Yloc=adv_Yloc+25
  3057.                     self.Label_Mirror_adv.place(x=Xadvanced, y=adv_Yloc, width=w_label_adv, height=21)
  3058.                     self.Checkbutton_Mirror_adv.place(x=Xadvanced+w_label_adv+2, y=adv_Yloc, width=25, height=23)
  3059.  
  3060.                     adv_Yloc=adv_Yloc+25
  3061.                     self.Label_Rotate_adv.place(x=Xadvanced, y=adv_Yloc, width=w_label_adv, height=21)
  3062.                     self.Checkbutton_Rotate_adv.place(x=Xadvanced+w_label_adv+2, y=adv_Yloc, width=25, height=23)
  3063.  
  3064.                     adv_Yloc=adv_Yloc+25
  3065.                     self.Label_inputCSYS_adv.place(x=Xadvanced, y=adv_Yloc, width=w_label_adv, height=21)
  3066.                     self.Checkbutton_inputCSYS_adv.place(x=Xadvanced+w_label_adv+2, y=adv_Yloc, width=25, height=23)
  3067.  
  3068.                     adv_Yloc=adv_Yloc+25
  3069.                     self.Label_Inside_First_adv.place(x=Xadvanced, y=adv_Yloc, width=w_label_adv, height=21)
  3070.                     self.Checkbutton_Inside_First_adv.place(x=Xadvanced+w_label_adv+2, y=adv_Yloc, width=25, height=23)
  3071.  
  3072.                     adv_Yloc = BUinit
  3073.                     self.Hide_Adv_Button.place (x=Xadvanced, y=adv_Yloc, width=wadv_use, height=30)
  3074.  
  3075.                     if self.RengData.image != None:
  3076.                         self.Label_inputCSYS_adv.configure(state="disabled")
  3077.                         self.Checkbutton_inputCSYS_adv.place_forget()              
  3078.                     else:
  3079.                         self.Label_inputCSYS_adv.configure(state="normal")
  3080.                        
  3081.                     if self.GcodeData.ecoords == []:
  3082.                         adv_Yloc = adv_Yloc-40
  3083.                         self.Label_Vcut_passes.place(x=Xadvanced, y=adv_Yloc, width=w_label_adv, height=21)
  3084.                         self.Entry_Vcut_passes.place(x=Xadvanced+w_label_adv+2, y=adv_Yloc, width=w_entry, height=23)
  3085.                         adv_Yloc=adv_Yloc-30
  3086.                         self.Label_Veng_passes.place(x=Xadvanced, y=adv_Yloc, width=w_label_adv, height=21)
  3087.                         self.Entry_Veng_passes.place(x=Xadvanced+w_label_adv+2, y=adv_Yloc, width=w_entry, height=23)
  3088.                         adv_Yloc=adv_Yloc-30
  3089.                         self.Label_Reng_passes.place(x=Xadvanced, y=adv_Yloc, width=w_label_adv, height=21)
  3090.                         self.Entry_Reng_passes.place(x=Xadvanced+w_label_adv+2, y=adv_Yloc, width=w_entry, height=23)
  3091.                         self.Label_Gcde_passes.place_forget()
  3092.                         self.Entry_Gcde_passes.place_forget()
  3093.                     else:
  3094.                         adv_Yloc=adv_Yloc-40
  3095.                         self.Label_Gcde_passes.place(x=Xadvanced, y=adv_Yloc, width=w_label_adv, height=21)
  3096.                         self.Entry_Gcde_passes.place(x=Xadvanced+w_label_adv+2, y=adv_Yloc, width=w_entry, height=23)
  3097.                         self.Label_Vcut_passes.place_forget()
  3098.                         self.Entry_Vcut_passes.place_forget()
  3099.                         self.Label_Veng_passes.place_forget()
  3100.                         self.Entry_Veng_passes.place_forget()
  3101.                         self.Label_Reng_passes.place_forget()
  3102.                         self.Entry_Reng_passes.place_forget()
  3103.  
  3104.                 else:
  3105.                     self.PreviewCanvas_frame.place_forget()
  3106.                     self.separator_vert.place_forget()
  3107.                     self.Label_Advanced_column.place_forget()
  3108.                     self.separator_adv.place_forget()
  3109.                     self.Label_Halftone_adv.place_forget()
  3110.                     self.Checkbutton_Halftone_adv.place_forget()
  3111.                     self.Label_Mirror_adv.place_forget()
  3112.                     self.Checkbutton_Mirror_adv.place_forget()
  3113.                     self.Label_Rotate_adv.place_forget()
  3114.                     self.Checkbutton_Rotate_adv.place_forget()
  3115.                     self.Label_inputCSYS_adv.place_forget()
  3116.                     self.Checkbutton_inputCSYS_adv.place_forget()
  3117.                    
  3118.                     self.Label_Inside_First_adv.place_forget()
  3119.                     self.Checkbutton_Inside_First_adv.place_forget()
  3120.  
  3121.                     self.Entry_Vcut_passes.place_forget()
  3122.                     self.Label_Vcut_passes.place_forget()
  3123.                     self.Entry_Veng_passes.place_forget()
  3124.                     self.Label_Veng_passes.place_forget()
  3125.                     self.Entry_Reng_passes.place_forget()
  3126.                     self.Label_Reng_passes.place_forget()
  3127.                     self.Label_Gcde_passes.place_forget()
  3128.                     self.Entry_Gcde_passes.place_forget()
  3129.                     self.Hide_Adv_Button.place_forget()
  3130.                    
  3131.                     self.PreviewCanvas.configure( width = self.w-240, height = self.h-50 )
  3132.                     self.PreviewCanvas_frame.place(x=Xvert_sep, y=10)
  3133.                     self.separator_vert.place_forget()
  3134.  
  3135.                 self.Set_Input_States()
  3136.                
  3137.             self.Plot_Data()
  3138.            
  3139.     def Recalculate_RQD_Click(self, event):
  3140.         self.menu_View_Refresh()
  3141.  
  3142.     def Set_Input_States(self):
  3143.         pass
  3144.            
  3145.     def Set_Input_States_Event(self,event):
  3146.         self.Set_Input_States()
  3147.  
  3148.     def Set_Input_States_RASTER(self):
  3149.         if self.halftone.get():
  3150.             self.Label_Halftone_DPI.configure(state="normal")
  3151.             self.Halftone_DPI_OptionMenu.configure(state="normal")
  3152.             self.Label_Halftone_u.configure(state="normal")
  3153.             self.Label_bezier_M1.configure(state="normal")
  3154.             self.bezier_M1_Slider.configure(state="normal")
  3155.             self.Label_bezier_M2.configure(state="normal")
  3156.             self.bezier_M2_Slider.configure(state="normal")
  3157.             self.Label_bezier_weight.configure(state="normal")
  3158.             self.bezier_weight_Slider.configure(state="normal")
  3159.         else:
  3160.             self.Label_Halftone_DPI.configure(state="disabled")
  3161.             self.Halftone_DPI_OptionMenu.configure(state="disabled")
  3162.             self.Label_Halftone_u.configure(state="disabled")
  3163.             self.Label_bezier_M1.configure(state="disabled")
  3164.             self.bezier_M1_Slider.configure(state="disabled")
  3165.             self.Label_bezier_M2.configure(state="disabled")
  3166.             self.bezier_M2_Slider.configure(state="disabled")
  3167.             self.Label_bezier_weight.configure(state="disabled")
  3168.             self.bezier_weight_Slider.configure(state="disabled")
  3169.  
  3170.            
  3171.     def Set_Input_States_RASTER_Event(self,event):
  3172.         self.Set_Input_States_RASTER()
  3173.  
  3174.     def Imaging_Free(self,image_in,bg="#ffffff"):
  3175.         image_in = image_in.convert('L')
  3176.         wim,him = image_in.size
  3177.         image_out=PhotoImage(width=wim,height=him)
  3178.         pixel=image_in.load()
  3179.         if bg!=None:
  3180.             image_out.put(bg, to=(0,0,wim,him))
  3181.         for y in range(0,him):
  3182.             for x in range(0,wim):
  3183.                 val=pixel[x,y]
  3184.                 if val!=255:
  3185.                     image_out.put("#%02x%02x%02x" %(val,val,val),(x,y))
  3186.         return image_out
  3187.  
  3188.     ##########################################
  3189.     #        CANVAS PLOTTING STUFF           #
  3190.     ##########################################
  3191.     def Plot_Data(self):
  3192.         self.PreviewCanvas.delete(ALL)
  3193.         if (self.Check_All_Variables() > 0):
  3194.             return
  3195.  
  3196.         for seg in self.segID:
  3197.             self.PreviewCanvas.delete(seg)
  3198.         self.segID = []
  3199.        
  3200.         cszw = int(self.PreviewCanvas.cget("width"))
  3201.         cszh = int(self.PreviewCanvas.cget("height"))
  3202.         buff=10
  3203.         wc = float(cszw/2)
  3204.         hc = float(cszh/2)        
  3205.        
  3206.         maxx = float(self.LaserXsize.get()) / self.units_scale
  3207.         minx = 0.0
  3208.         maxy = 0.0
  3209.         miny = -float(self.LaserYsize.get()) / self.units_scale
  3210.         midx=(maxx+minx)/2
  3211.         midy=(maxy+miny)/2
  3212.        
  3213.         self.PlotScale = max((maxx-minx)/(cszw-buff), (maxy-miny)/(cszh-buff))
  3214.        
  3215.         x_lft = cszw/2 + (minx-midx) / self.PlotScale
  3216.         x_rgt = cszw/2 + (maxx-midx) / self.PlotScale
  3217.         y_bot = cszh/2 + (maxy-midy) / self.PlotScale
  3218.         y_top = cszh/2 + (miny-midy) / self.PlotScale
  3219.         self.segID.append( self.PreviewCanvas.create_rectangle(
  3220.                     x_lft, y_bot, x_rgt, y_top, fill="gray80", outline="gray80", width = 0) )
  3221.  
  3222.         if self.inputCSYS.get() and self.RengData.image == None:
  3223.             xmin,xmax,ymin,ymax = 0.0,0.0,0.0,0.0
  3224.         else:
  3225.             xmin,xmax,ymin,ymax = self.Get_Design_Bounds()          
  3226.                
  3227.         if (self.HomeUR.get()):
  3228.             XlineShift = maxx - self.laserX - (xmax-xmin)
  3229.         else:
  3230.             XlineShift = self.laserX
  3231.         YlineShift = self.laserY    
  3232.  
  3233.         ######################################
  3234.         ###       Plot Raster Image        ###
  3235.         ######################################
  3236.         if self.RengData.image != None:
  3237.             if self.include_Reng.get():  
  3238.                 try:
  3239.                     new_SCALE = (1.0/self.PlotScale)/self.input_dpi
  3240.                     if new_SCALE != self.SCALE:
  3241.                         self.SCALE = new_SCALE
  3242.                         nw=int(self.SCALE*self.wim)
  3243.                         nh=int(self.SCALE*self.him)
  3244.                         #PIL_im = PIL_im.convert("1") #"1"=1BBP, "L"=grey
  3245.                         if self.halftone.get() == False:
  3246.                             plot_im = self.RengData.image.convert("L")
  3247.                             plot_im = plot_im.point(lambda x: 0 if x<128 else 255, '1')
  3248.                         else:
  3249.                             plot_im = self.RengData.image
  3250.  
  3251.                         if self.mirror.get():
  3252.                             plot_im = ImageOps.mirror(plot_im)
  3253.  
  3254.                         if self.rotate.get():
  3255.                             plot_im = plot_im.rotate(90,expand=True)
  3256.                             nh=int(self.SCALE*self.wim)
  3257.                             nw=int(self.SCALE*self.him)
  3258.                            
  3259.                         try:
  3260.                             self.UI_image = ImageTk.PhotoImage(plot_im.resize((nw,nh), Image.ANTIALIAS))
  3261.                         except:
  3262.                             debug_message("Imaging_Free Used.")
  3263.                             self.UI_image = self.Imaging_Free(plot_im.resize((nw,nh), Image.ANTIALIAS))
  3264.                 except:
  3265.                     self.SCALE = 1
  3266.                     debug_message(traceback.format_exc())
  3267.                    
  3268.                 self.Plot_Raster(self.laserX, self.laserY, x_lft,y_top,self.PlotScale,im=self.UI_image)
  3269.         else:
  3270.             self.UI_image = None
  3271.  
  3272.  
  3273.         ######################################
  3274.         ###       Plot Reng Coords         ###
  3275.         ######################################
  3276.         if self.include_Rpth.get() and self.RengData.ecoords!=[]:
  3277.             loop_old = -1
  3278.             scale = 1
  3279.  
  3280.             for line in self.RengData.ecoords:
  3281.                 XY    = line
  3282.                 x1    = (XY[0]-xmin)*scale
  3283.                 y1    = (XY[1]-ymax)*scale
  3284.  
  3285.                 loop  = XY[2]
  3286.                 color = "black"
  3287.                 # check and see if we need to move to a new discontinuous start point
  3288.                 if (loop == loop_old):
  3289.                     self.Plot_Line(xold, yold, x1, y1, x_lft, y_top, XlineShift, YlineShift, self.PlotScale, color)
  3290.                 loop_old = loop
  3291.                 xold=x1
  3292.                 yold=y1
  3293.  
  3294.            
  3295.         ######################################
  3296.         ###       Plot Veng Coords         ###
  3297.         ######################################
  3298.         if self.include_Veng.get():
  3299.             loop_old = -1
  3300.             scale=1
  3301.  
  3302.             plot_coords = self.VengData.ecoords
  3303.             if self.mirror.get() or self.rotate.get():
  3304.                 plot_coords = self.mirror_rotate_vector_coords(plot_coords)
  3305.                
  3306.             for line in plot_coords:
  3307.                 XY    = line
  3308.                 x1    = (XY[0]-xmin)*scale
  3309.                 y1    = (XY[1]-ymax)*scale
  3310.                 loop  = XY[2]
  3311.                 # check and see if we need to move to a new discontinuous start point
  3312.                 if (loop == loop_old):
  3313.                     self.Plot_Line(xold, yold, x1, y1, x_lft, y_top, XlineShift, YlineShift, self.PlotScale, "blue")
  3314.                 loop_old = loop
  3315.                 xold=x1
  3316.                 yold=y1
  3317.  
  3318.         ######################################
  3319.         ###       Plot Vcut Coords         ###
  3320.         ######################################
  3321.         if self.include_Vcut.get():
  3322.             loop_old = -1
  3323.             scale=1
  3324.  
  3325.             plot_coords = self.VcutData.ecoords
  3326.             if self.mirror.get() or self.rotate.get():
  3327.                     plot_coords = self.mirror_rotate_vector_coords(plot_coords)
  3328.                
  3329.             for line in plot_coords:
  3330.                 XY    = line
  3331.                 x1    = (XY[0]-xmin)*scale
  3332.                 y1    = (XY[1]-ymax)*scale
  3333.  
  3334.                 loop  = XY[2]
  3335.                 # check and see if we need to move to a new discontinuous start point
  3336.                 if (loop == loop_old):
  3337.                     self.Plot_Line(xold, yold, x1, y1, x_lft, y_top, XlineShift, YlineShift, self.PlotScale, "red")
  3338.                        
  3339.                    
  3340.                 loop_old = loop
  3341.                 xold=x1
  3342.                 yold=y1
  3343.  
  3344.         ######################################
  3345.         ###       Plot Gcode Coords        ###
  3346.         ######################################
  3347.         if self.include_Gcde.get():  
  3348.             loop_old = -1
  3349.             scale=1
  3350.  
  3351.             plot_coords = self.GcodeData.ecoords
  3352.             if self.mirror.get() or self.rotate.get():
  3353.                     plot_coords = self.mirror_rotate_vector_coords(plot_coords)
  3354.                
  3355.             for line in plot_coords:
  3356.                 XY    = line
  3357.                 x1    = (XY[0]-xmin)*scale
  3358.                 y1    = (XY[1]-ymax)*scale
  3359.  
  3360.                 loop  = XY[2]
  3361.                 # check and see if we need to move to a new discontinuous start point
  3362.                 if (loop == loop_old):
  3363.                     self.Plot_Line(xold, yold, x1, y1, x_lft, y_top, XlineShift, YlineShift, self.PlotScale, "white")
  3364.                 loop_old = loop
  3365.                 xold=x1
  3366.                 yold=y1
  3367.                
  3368.  
  3369.  
  3370.         ######################################            
  3371.         self.refreshTime()
  3372.         dot_col = "grey50"
  3373.         xoff = self.pos_offset[0]/1000.0
  3374.         yoff = self.pos_offset[1]/1000.0    
  3375.         self.Plot_circle(self.laserX+xoff,self.laserY+yoff,x_lft,y_top,self.PlotScale,dot_col,radius=5)
  3376.        
  3377.     def Plot_Raster(self, XX, YY, Xleft, Ytop, PlotScale, im):
  3378.         if (self.HomeUR.get()):
  3379.             maxx = float(self.LaserXsize.get()) / self.units_scale
  3380.             xmin,xmax,ymin,ymax = self.Get_Design_Bounds()
  3381.             xplt = Xleft + ( maxx-XX-(xmax-xmin) )/PlotScale
  3382.         else:
  3383.             xplt = Xleft +  XX/PlotScale
  3384.            
  3385.         yplt = Ytop  - YY/PlotScale
  3386.         self.segID.append(
  3387.             self.PreviewCanvas.create_image(xplt, yplt, anchor=NW, image=self.UI_image,tags='LaserTag')
  3388.             )
  3389.        
  3390.     def Plot_circle(self, XX, YY, Xleft, Ytop, PlotScale, col, radius=0):
  3391.         if (self.HomeUR.get()):
  3392.             maxx = float(self.LaserXsize.get()) / self.units_scale
  3393.             xplt = Xleft + maxx/PlotScale - XX/PlotScale
  3394.         else:
  3395.             xplt = Xleft + XX/PlotScale
  3396.         yplt = Ytop  - YY/PlotScale
  3397.         self.segID.append(
  3398.             self.PreviewCanvas.create_oval(
  3399.                                             xplt-radius,
  3400.                                             yplt-radius,
  3401.                                             xplt+radius,
  3402.                                             yplt+radius,
  3403.                                             fill=col, outline=col, width = 0,tags='LaserTag') )
  3404.  
  3405.     def Plot_Line(self, XX1, YY1, XX2, YY2, Xleft, Ytop, XlineShift, YlineShift, PlotScale, col, thick=0):
  3406.         xplt1 = Xleft + (XX1 + XlineShift )/PlotScale
  3407.         xplt2 = Xleft + (XX2 + XlineShift )/PlotScale
  3408.         yplt1 = Ytop  - (YY1 + YlineShift )/PlotScale
  3409.         yplt2 = Ytop  - (YY2 + YlineShift )/PlotScale
  3410.        
  3411.         self.segID.append(
  3412.             self.PreviewCanvas.create_line( xplt1,
  3413.                                             yplt1,
  3414.                                             xplt2,
  3415.                                             yplt2,
  3416.                                             fill=col, capstyle="round", width = thick, tags='LaserTag') )
  3417.        
  3418.     ################################################################################
  3419.     #                         Temporary Move Window                                #
  3420.     ################################################################################
  3421.     def move_head_window_temporary(self,new_pos_offset):
  3422.         if self.inputCSYS.get() and self.RengData.image == None:
  3423.             new_pos_offset = [0,0]
  3424.             xdist = -self.pos_offset[0]
  3425.             ydist = -self.pos_offset[1]
  3426.         else:
  3427.             xdist = -self.pos_offset[0] + new_pos_offset[0]
  3428.             ydist = -self.pos_offset[1] + new_pos_offset[1]
  3429.  
  3430.         if self.k40 != None:
  3431.             self.Send_Rapid_Move( xdist,ydist )
  3432.  
  3433.         self.pos_offset = new_pos_offset
  3434.         self.menu_View_Refresh()
  3435.    
  3436.     ################################################################################
  3437.     #                         General Settings Window                              #
  3438.     ################################################################################
  3439.     def GEN_Settings_Window(self):
  3440.         gen_settings = Toplevel(width=560, height=460)
  3441.         gen_settings.grab_set() # Use grab_set to prevent user input in the main window during calculations
  3442.         gen_settings.resizable(0,0)
  3443.         gen_settings.title('Settings')
  3444.         gen_settings.iconname("Settings")
  3445.  
  3446.         try:
  3447.             gen_settings.iconbitmap(bitmap="@emblem64")
  3448.         except:
  3449.             debug_message(traceback.format_exc())
  3450.             pass
  3451.  
  3452.         D_Yloc  = 6
  3453.         D_dY = 26
  3454.         xd_label_L = 12
  3455.  
  3456.         w_label=150
  3457.         w_entry=40
  3458.         w_units=35
  3459.         xd_entry_L=xd_label_L+w_label+10
  3460.         xd_units_L=xd_entry_L+w_entry+5
  3461.  
  3462.         #Radio Button
  3463.         D_Yloc=D_Yloc+D_dY
  3464.         self.Label_Units = Label(gen_settings,text="Units")
  3465.         self.Label_Units.place(x=xd_label_L, y=D_Yloc, width=113, height=21)
  3466.         self.Radio_Units_IN = Radiobutton(gen_settings,text="inch", value="in",
  3467.                                          width="100", anchor=W)
  3468.         self.Radio_Units_IN.place(x=w_label+22, y=D_Yloc, width=75, height=23)
  3469.         self.Radio_Units_IN.configure(variable=self.units, command=self.Entry_units_var_Callback )
  3470.         self.Radio_Units_MM = Radiobutton(gen_settings,text="mm", value="mm",
  3471.                                          width="100", anchor=W)
  3472.         self.Radio_Units_MM.place(x=w_label+110, y=D_Yloc, width=75, height=23)
  3473.         self.Radio_Units_MM.configure(variable=self.units, command=self.Entry_units_var_Callback )
  3474.  
  3475.         D_Yloc=D_Yloc+D_dY
  3476.         self.Label_init_home = Label(gen_settings,text="Home Upon Initialize")
  3477.         self.Label_init_home.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3478.         self.Checkbutton_init_home = Checkbutton(gen_settings,text="", anchor=W)
  3479.         self.Checkbutton_init_home.place(x=xd_entry_L, y=D_Yloc, width=75, height=23)
  3480.         self.Checkbutton_init_home.configure(variable=self.init_home)
  3481.  
  3482.         D_Yloc=D_Yloc+D_dY
  3483.         self.Label_Preprocess_CRC = Label(gen_settings,text="Preprocess CRC Data")
  3484.         self.Label_Preprocess_CRC.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3485.         self.Checkbutton_Preprocess_CRC = Checkbutton(gen_settings,text="", anchor=W)
  3486.         self.Checkbutton_Preprocess_CRC.place(x=xd_entry_L, y=D_Yloc, width=75, height=23)
  3487.         self.Checkbutton_Preprocess_CRC.configure(variable=self.pre_pr_crc)
  3488.  
  3489.  
  3490.         D_Yloc=D_Yloc+D_dY
  3491.         self.Label_Timeout = Label(gen_settings,text="USB Timeout")
  3492.         self.Label_Timeout.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3493.         self.Label_Timeout_u = Label(gen_settings,text="ms", anchor=W)
  3494.         self.Label_Timeout_u.place(x=xd_units_L, y=D_Yloc, width=w_units, height=21)
  3495.         self.Entry_Timeout = Entry(gen_settings,width="15")
  3496.         self.Entry_Timeout.place(x=xd_entry_L, y=D_Yloc, width=w_entry, height=23)
  3497.         self.Entry_Timeout.configure(textvariable=self.t_timeout)
  3498.         self.t_timeout.trace_variable("w", self.Entry_Timeout_Callback)
  3499.         self.entry_set(self.Entry_Timeout,self.Entry_Timeout_Check(),2)
  3500.  
  3501.         D_Yloc=D_Yloc+D_dY
  3502.         self.Label_N_Timeouts = Label(gen_settings,text="Number of Timeouts")
  3503.         self.Label_N_Timeouts.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3504.         self.Entry_N_Timeouts = Entry(gen_settings,width="15")
  3505.         self.Entry_N_Timeouts.place(x=xd_entry_L, y=D_Yloc, width=w_entry, height=23)
  3506.         self.Entry_N_Timeouts.configure(textvariable=self.n_timeouts)
  3507.         self.n_timeouts.trace_variable("w", self.Entry_N_Timeouts_Callback)
  3508.         self.entry_set(self.Entry_N_Timeouts,self.Entry_N_Timeouts_Check(),2)
  3509.  
  3510.         D_Yloc=D_Yloc+D_dY
  3511.         font_entry_width=215
  3512.         self.Label_Inkscape_Path = Label(gen_settings,text="Inkscape Executable")
  3513.         self.Label_Inkscape_Path.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3514.         self.Entry_Inkscape_Path = Entry(gen_settings,width="15")
  3515.         self.Entry_Inkscape_Path.place(x=xd_entry_L, y=D_Yloc, width=font_entry_width, height=23)
  3516.         self.Entry_Inkscape_Path.configure(textvariable=self.inkscape_path)
  3517.         self.Inkscape_Path = Button(gen_settings,text="Find Inkscape")
  3518.         self.Inkscape_Path.place(x=xd_entry_L+font_entry_width+10, y=D_Yloc, width=110, height=23)
  3519.         self.Inkscape_Path.bind("<ButtonRelease-1>", self.Inkscape_Path_Click)
  3520.  
  3521.         D_Yloc=D_Yloc+D_dY
  3522.         self.Label_no_com = Label(gen_settings,text="Home in Upper Right")
  3523.         self.Label_no_com.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3524.         self.Checkbutton_no_com = Checkbutton(gen_settings,text="", anchor=W)
  3525.         self.Checkbutton_no_com.place(x=xd_entry_L, y=D_Yloc, width=75, height=23)
  3526.         self.Checkbutton_no_com.configure(variable=self.HomeUR)
  3527.         self.HomeUR.trace_variable("w",self.menu_View_Refresh_Callback)        
  3528.  
  3529.         D_Yloc=D_Yloc+D_dY
  3530.         self.Label_Board_Name      = Label(gen_settings,text="Board Name", anchor=CENTER )
  3531.         self.Board_Name_OptionMenu = OptionMenu(gen_settings, self.board_name,
  3532.                                             "LASER-M2",
  3533.                                             "LASER-M1",
  3534.                                             "LASER-M",
  3535.                                             "LASER-B2",
  3536.                                             "LASER-B1",
  3537.                                             "LASER-B",
  3538.                                             "LASER-A")
  3539.         self.Label_Board_Name.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3540.         self.Board_Name_OptionMenu.place(x=xd_entry_L, y=D_Yloc, width=w_entry*3, height=23)
  3541.  
  3542.         D_Yloc=D_Yloc+D_dY
  3543.         self.Label_Laser_Area_Width = Label(gen_settings,text="Laser Area Width")
  3544.         self.Label_Laser_Area_Width.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3545.         self.Label_Laser_Area_Width_u = Label(gen_settings,textvariable=self.units, anchor=W)
  3546.         self.Label_Laser_Area_Width_u.place(x=xd_units_L, y=D_Yloc, width=w_units, height=21)
  3547.         self.Entry_Laser_Area_Width = Entry(gen_settings,width="15")
  3548.         self.Entry_Laser_Area_Width.place(x=xd_entry_L, y=D_Yloc, width=w_entry, height=23)
  3549.         self.Entry_Laser_Area_Width.configure(textvariable=self.LaserXsize)
  3550.         self.LaserXsize.trace_variable("w", self.Entry_Laser_Area_Width_Callback)
  3551.         self.entry_set(self.Entry_Laser_Area_Width,self.Entry_Laser_Area_Width_Check(),2)
  3552.  
  3553.         D_Yloc=D_Yloc+D_dY
  3554.         self.Label_Laser_Area_Height = Label(gen_settings,text="Laser Area Height")
  3555.         self.Label_Laser_Area_Height.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3556.         self.Label_Laser_Area_Height_u = Label(gen_settings,textvariable=self.units, anchor=W)
  3557.         self.Label_Laser_Area_Height_u.place(x=xd_units_L, y=D_Yloc, width=w_units, height=21)
  3558.         self.Entry_Laser_Area_Height = Entry(gen_settings,width="15")
  3559.         self.Entry_Laser_Area_Height.place(x=xd_entry_L, y=D_Yloc, width=w_entry, height=23)
  3560.         self.Entry_Laser_Area_Height.configure(textvariable=self.LaserYsize)
  3561.         self.LaserYsize.trace_variable("w", self.Entry_Laser_Area_Height_Callback)
  3562.         self.entry_set(self.Entry_Laser_Area_Height,self.Entry_Laser_Area_Height_Check(),2)
  3563.  
  3564.         D_Yloc=D_Yloc+D_dY
  3565.         self.Label_Laser_X_Scale = Label(gen_settings,text="X Scale Factor")
  3566.         self.Label_Laser_X_Scale.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3567.         self.Entry_Laser_X_Scale = Entry(gen_settings,width="15")
  3568.         self.Entry_Laser_X_Scale.place(x=xd_entry_L, y=D_Yloc, width=w_entry, height=23)
  3569.         self.Entry_Laser_X_Scale.configure(textvariable=self.LaserXscale)
  3570.         self.LaserXscale.trace_variable("w", self.Entry_Laser_X_Scale_Callback)
  3571.         self.entry_set(self.Entry_Laser_X_Scale,self.Entry_Laser_X_Scale_Check(),2)
  3572.  
  3573.         D_Yloc=D_Yloc+D_dY
  3574.         self.Label_Laser_Y_Scale = Label(gen_settings,text="Y Scale Factor")
  3575.         self.Label_Laser_Y_Scale.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3576.         self.Entry_Laser_Y_Scale = Entry(gen_settings,width="15")
  3577.         self.Entry_Laser_Y_Scale.place(x=xd_entry_L, y=D_Yloc, width=w_entry, height=23)
  3578.         self.Entry_Laser_Y_Scale.configure(textvariable=self.LaserYscale)
  3579.         self.LaserYscale.trace_variable("w", self.Entry_Laser_Y_Scale_Callback)
  3580.         self.entry_set(self.Entry_Laser_Y_Scale,self.Entry_Laser_Y_Scale_Check(),2)
  3581.        
  3582.  
  3583.         D_Yloc=D_Yloc+D_dY+10
  3584.         self.Label_SaveConfig = Label(gen_settings,text="Configuration File")
  3585.         self.Label_SaveConfig.place(x=xd_label_L, y=D_Yloc, width=113, height=21)
  3586.  
  3587.         self.GEN_SaveConfig = Button(gen_settings,text="Save")
  3588.         self.GEN_SaveConfig.place(x=xd_entry_L, y=D_Yloc, width=w_entry, height=21, anchor="nw")
  3589.         self.GEN_SaveConfig.bind("<ButtonRelease-1>", self.Write_Config_File)
  3590.        
  3591.         ## Buttons ##
  3592.         gen_settings.update_idletasks()
  3593.         Ybut=int(gen_settings.winfo_height())-30
  3594.         Xbut=int(gen_settings.winfo_width()/2)
  3595.  
  3596.         self.GEN_Close = Button(gen_settings,text="Close",command=self.Close_Current_Window_Click)
  3597.         self.GEN_Close.place(x=Xbut, y=Ybut, width=130, height=30, anchor="center")
  3598.  
  3599.     ################################################################################
  3600.     #                          Raster Settings Window                              #
  3601.     ################################################################################
  3602.     def RASTER_Settings_Window(self):
  3603.         Wset=425+280
  3604.         Hset=330 #260
  3605.         raster_settings = Toplevel(width=Wset, height=Hset)
  3606.         raster_settings.grab_set() # Use grab_set to prevent user input in the main window during calculations
  3607.         raster_settings.resizable(0,0)
  3608.         raster_settings.title('Raster Settings')
  3609.         raster_settings.iconname("Raster Settings")
  3610.  
  3611.         try:
  3612.             raster_settings.iconbitmap(bitmap="@emblem64")
  3613.         except:
  3614.             debug_message(traceback.format_exc())
  3615.             pass
  3616.  
  3617.         D_Yloc  = 6
  3618.         D_dY = 24
  3619.         xd_label_L = 12
  3620.  
  3621.         w_label=155
  3622.         w_entry=60
  3623.         w_units=35
  3624.         xd_entry_L=xd_label_L+w_label+10
  3625.         xd_units_L=xd_entry_L+w_entry+5
  3626.  
  3627.  
  3628.  
  3629.         D_Yloc=D_Yloc+D_dY
  3630.         self.Label_Rstep   = Label(raster_settings,text="Scanline Step", anchor=CENTER )
  3631.         self.Label_Rstep.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3632.         self.Label_Rstep_u = Label(raster_settings,text="in", anchor=W)
  3633.         self.Label_Rstep_u.place(x=xd_units_L, y=D_Yloc, width=w_units, height=21)
  3634.         self.Entry_Rstep   = Entry(raster_settings,width="15")
  3635.         self.Entry_Rstep.place(x=xd_entry_L, y=D_Yloc, width=w_entry, height=23)
  3636.         self.Entry_Rstep.configure(textvariable=self.rast_step)
  3637.         self.rast_step.trace_variable("w", self.Entry_Rstep_Callback)
  3638.  
  3639.         D_Yloc=D_Yloc+D_dY
  3640.         self.Label_EngraveUP = Label(raster_settings,text="Engrave Bottom Up")
  3641.         self.Checkbutton_EngraveUP = Checkbutton(raster_settings,text=" ", anchor=W)
  3642.         self.Checkbutton_EngraveUP.configure(variable=self.engraveUP)
  3643.         self.Label_EngraveUP.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3644.         self.Checkbutton_EngraveUP.place(x=w_label+22, y=D_Yloc, width=75, height=23)
  3645.        
  3646.         D_Yloc=D_Yloc+D_dY
  3647.         self.Label_Halftone = Label(raster_settings,text="Halftone (Dither)")
  3648.         self.Label_Halftone.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3649.         self.Checkbutton_Halftone = Checkbutton(raster_settings,text=" ", anchor=W, command=self.Set_Input_States_RASTER)
  3650.         self.Checkbutton_Halftone.place(x=w_label+22, y=D_Yloc, width=75, height=23)
  3651.         self.Checkbutton_Halftone.configure(variable=self.halftone)
  3652.         self.halftone.trace_variable("w", self.menu_View_Refresh_Callback)
  3653.  
  3654.         ############
  3655.         D_Yloc=D_Yloc+D_dY
  3656.         self.Label_Halftone_DPI      = Label(raster_settings,text="Halftone Resolution", anchor=CENTER )
  3657.         self.Halftone_DPI_OptionMenu = OptionMenu(raster_settings, self.ht_size,
  3658.                                             "1000",
  3659.                                             "500",
  3660.                                             "333",
  3661.                                             "250",
  3662.                                             "200",
  3663.                                             "167",
  3664.                                             "143",
  3665.                                             "125")
  3666.         self.Label_Halftone_DPI.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3667.         self.Halftone_DPI_OptionMenu.place(x=xd_entry_L, y=D_Yloc, width=w_entry+30, height=23)
  3668.  
  3669.  
  3670.         self.Label_Halftone_u = Label(raster_settings,text="dpi", anchor=W)
  3671.         self.Label_Halftone_u.place(x=xd_units_L+30, y=D_Yloc, width=w_units, height=21)
  3672.  
  3673.         ############
  3674.         D_Yloc=D_Yloc+D_dY+5
  3675.         self.Label_bezier_M1  = Label(raster_settings,
  3676.                                 text="Slope, Black (%.1f)"%(self.bezier_M1_default),
  3677.                                 anchor=CENTER )
  3678.         self.bezier_M1_Slider = Scale(raster_settings, from_=1, to=50, resolution=0.1, \
  3679.                                 orient=HORIZONTAL, variable=self.bezier_M1)
  3680.         self.bezier_M1_Slider.place(x=xd_entry_L, y=D_Yloc, width=(Wset-xd_entry_L-25-280 ))
  3681.         D_Yloc=D_Yloc+21
  3682.         self.Label_bezier_M1.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3683.         self.bezier_M1.trace_variable("w", self.bezier_M1_Callback)
  3684.        
  3685.         D_Yloc=D_Yloc+D_dY-8
  3686.         self.Label_bezier_M2  = Label(raster_settings,
  3687.                                 text="Slope, White (%.2f)"%(self.bezier_M2_default),
  3688.                                 anchor=CENTER )
  3689.         self.bezier_M2_Slider = Scale(raster_settings, from_=0.0, to=1, \
  3690.                                 orient=HORIZONTAL,resolution=0.01, variable=self.bezier_M2)
  3691.         self.bezier_M2_Slider.place(x=xd_entry_L, y=D_Yloc, width=(Wset-xd_entry_L-25-280 ))
  3692.         D_Yloc=D_Yloc+21
  3693.         self.Label_bezier_M2.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3694.         self.bezier_M2.trace_variable("w", self.bezier_M2_Callback)
  3695.  
  3696.         D_Yloc=D_Yloc+D_dY-8
  3697.         self.Label_bezier_weight   = Label(raster_settings,
  3698.                                      text="Transition (%.1f)"%(self.bezier_M1_default),
  3699.                                      anchor=CENTER )
  3700.         self.bezier_weight_Slider = Scale(raster_settings, from_=0, to=10, resolution=0.1, \
  3701.                                     orient=HORIZONTAL, variable=self.bezier_weight)
  3702.         self.bezier_weight_Slider.place(x=xd_entry_L, y=D_Yloc, width=(Wset-xd_entry_L-25-280 ))
  3703.         D_Yloc=D_Yloc+21
  3704.         self.Label_bezier_weight.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21)
  3705.         self.bezier_weight.trace_variable("w", self.bezier_weight_Callback)
  3706.  
  3707.  
  3708.         # Bezier Canvas
  3709.         self.Bezier_frame = Frame(raster_settings, bd=1, relief=SUNKEN)
  3710.         self.Bezier_frame.place(x=Wset-280, y=10, height=265, width=265)
  3711.         self.BezierCanvas = Canvas(self.Bezier_frame, background="white")
  3712.         self.BezierCanvas.pack(side=LEFT, fill=BOTH, expand=1)
  3713.         self.BezierCanvas.create_line( 5,260-0,260,260-255,fill="grey", capstyle="round", width = 2, tags='perm')
  3714.  
  3715.  
  3716.         M1 = self.bezier_M1_default
  3717.         M2 = self.bezier_M2_default
  3718.         w  = self.bezier_weight_default
  3719.         num = 10
  3720.         x,y = self.generate_bezier(M1,M2,w,n=num)
  3721.         for i in range(0,num):
  3722.             self.BezierCanvas.create_line( 5+x[i],260-y[i],5+x[i+1],260-y[i+1],fill="lightgrey", stipple='gray25',\
  3723.                                            capstyle="round", width = 2, tags='perm')
  3724.        
  3725.  
  3726.         ## Buttons ##
  3727.         raster_settings.update_idletasks()
  3728.         Ybut=int(raster_settings.winfo_height())-30
  3729.         Xbut=int(raster_settings.winfo_width()/2)
  3730.  
  3731.         self.RASTER_Close = Button(raster_settings,text="Close",command=self.Close_Current_Window_Click)
  3732.         self.RASTER_Close.place(x=Xbut, y=Ybut, width=130, height=30, anchor="center")
  3733.  
  3734.         self.bezier_M1_Callback()
  3735.         self.Set_Input_States_RASTER()
  3736.  
  3737.  
  3738.        
  3739. ################################################################################
  3740. #             Function for outputting messages to different locations          #
  3741. #            depending on what options are enabled                             #
  3742. ################################################################################
  3743. def fmessage(text,newline=True):
  3744.     global QUIET
  3745.     if (not QUIET):
  3746.         if newline==True:
  3747.             try:
  3748.                 sys.stdout.write(text)
  3749.                 sys.stdout.write("\n")
  3750.                 debug_message(traceback.format_exc())
  3751.             except:
  3752.                 debug_message(traceback.format_exc())
  3753.                 pass
  3754.         else:
  3755.             try:
  3756.                 sys.stdout.write(text)
  3757.                 debug_message(traceback.format_exc())
  3758.             except:
  3759.                 debug_message(traceback.format_exc())
  3760.                 pass
  3761.  
  3762. ################################################################################
  3763. #                               Message Box                                    #
  3764. ################################################################################
  3765. def message_box(title,message):
  3766.     title = "%s (K40 Whisperer V%s)" %(title,version)
  3767.     if VERSION == 3:
  3768.         tkinter.messagebox.showinfo(title,message)
  3769.     else:
  3770.         tkMessageBox.showinfo(title,message)
  3771.         pass
  3772.  
  3773. ################################################################################
  3774. #                          Message Box ask OK/Cancel                           #
  3775. ################################################################################
  3776. def message_ask_ok_cancel(title, mess):
  3777.     if VERSION == 3:
  3778.         result=tkinter.messagebox.askokcancel(title, mess)
  3779.     else:
  3780.         result=tkMessageBox.askokcancel(title, mess)
  3781.     return result
  3782.  
  3783. ################################################################################
  3784. #                         Debug Message Box                                    #
  3785. ################################################################################
  3786. def debug_message(message):
  3787.     global DEBUG
  3788.     title = "Debug Message"
  3789.     if DEBUG:
  3790.         if VERSION == 3:
  3791.             tkinter.messagebox.showinfo(title,message)
  3792.         else:
  3793.             tkMessageBox.showinfo(title,message)
  3794.             pass
  3795.  
  3796. ################################################################################
  3797. #                         Choose Units Dialog                                  #
  3798. ################################################################################
  3799. import tkSimpleDialog
  3800. class UnitsDialog(tkSimpleDialog.Dialog):
  3801.     def body(self, master):
  3802.         self.resizable(0,0)
  3803.         self.title('Units')
  3804.         self.iconname("Units")
  3805.  
  3806.         try:
  3807.             self.iconbitmap(bitmap="@emblem64")
  3808.         except:
  3809.             pass
  3810.        
  3811.         self.uom = StringVar()
  3812.         self.uom.set("Millimeters")
  3813.  
  3814.         Label(master, text="Select DXF Import Units:").grid(row=0)
  3815.         Radio_Units_IN = Radiobutton(master,text="Inches",        value="Inches")
  3816.         Radio_Units_MM = Radiobutton(master,text="Millimeters",   value="Millimeters")
  3817.         Radio_Units_CM = Radiobutton(master,text="Centimeters",   value="Centimeters")
  3818.        
  3819.         Radio_Units_IN.grid(row=1, sticky=W)
  3820.         Radio_Units_MM.grid(row=2, sticky=W)
  3821.         Radio_Units_CM.grid(row=3, sticky=W)
  3822.  
  3823.         Radio_Units_IN.configure(variable=self.uom)
  3824.         Radio_Units_MM.configure(variable=self.uom)
  3825.         Radio_Units_CM.configure(variable=self.uom)
  3826.  
  3827.     def apply(self):
  3828.         self.result = self.uom.get()
  3829.         return
  3830.  
  3831.  
  3832.  
  3833. ################################################################################
  3834. #                          Startup Application                                 #
  3835. ################################################################################
  3836.  
  3837.  
  3838. root = Tk()
  3839. app = Application(root)
  3840. app.master.title(title_text)
  3841. app.master.iconname("K40")
  3842. app.master.minsize(800,560) #800x600 min
  3843.  
  3844. try:
  3845.     app.master.iconbitmap(bitmap="@emblem64")
  3846. except:
  3847.     pass
  3848.  
  3849. if LOAD_MSG != "":
  3850.     message_box("K40 Whisperer",LOAD_MSG)
  3851. debug_message("Debuging is turned on.")
  3852.  
  3853. root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement