Advertisement
senj0h

k40_whisperer with CLI in dev in progress

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