Import LinuxCNC source tree

This commit is contained in:
Wang Dequan
2026-08-20 06:17:39 +08:00
commit 2c814634c3
9429 changed files with 10556013 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,129 @@
# This is a component of LinuxCNC
# Copyright 2013, 2014 Chris Morley <chrisinnanaimo@hotmail.com>,
# Chris Radek <chris@timeguy.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# This is a handler file for using Gscreen's infrastructure
# to load a completely custom glade screen
# The only things that really matters is that it's saved as a GTK builder project,
# the toplevel window is caller window1 (The default name) and you connect a destroy
# window signal else you can't close down linuxcnc
class HandlerClass:
# this will be pretty standard to gain access to everything
# emc is for control and status of linuxcnc
# data is important data from gscreen and linuxcnc
# widgets is all the widgets from the glade files
# gscreen is for access to gscreens methods
#
# we added setting the gremlin DRO on from the startup,
# a global variable for the number of key presses,
# and make only the active axis buttons visible
def __init__(self, halcomp,builder,useropts,gscreen):
self.emc = gscreen.emc
self.data = gscreen.data
self.widgets = gscreen.widgets
self.gscreen = gscreen
self.nhits = 0
self.widgets.gremlin.set_property('enable_dro',True)
for i in ("x","y","z","a","b","c","u","v","w","s"):
if i in self.data.axis_list:
self.widgets["axis_%s"%i].set_visible(True)
self.widgets.offsetpage1.set_row_visible("1",False)
# This is a new method for a couple of widgets we added callbacks to.
# The argument 'widget' is a reference to the actual widget that called.
# In this way we can use this method on a bunch of widgets without knowing
# their name ahead of time.
def on_button_press(self,widget,data=None):
global nhits
self.nhits += 1
widget.set_label("hits: %d" % self.nhits)
# This is a new method that calls a gscreen method to toggle the DRO units
# Gscreen's regular unit button saves the state
# for startup, This one just changes it for the session
def on_metric_select_clicked(self,widget):
data = (self.data.dro_units -1) * -1
self.gscreen.set_dro_units(data,False)
for i in ("1","2","3"):
for letter in self.data.axis_list:
axis = "dro_%s%s"% (letter,i)
try:
self.widgets[axis].set_property("display_units_mm",data)
except:
pass
# This method is overridden from gscreen
# We selected this method name in the glade file as a callback.
# Since this method name is the same as one in gscreen,
# gscreen won't connect a callback to it's method.
# Meaning this is the only one called.
def on_estop_clicked(self,*args):
print("estop")
if self.data.estopped:
self.emc.estop_reset(1)
else:
self.emc.machine_off(1)
self.emc.estop(1)
self.widgets.on_label.set_text("Machine Off")
return True
# This is a new method for our new button
# we selected this method name in the glade file as a callback
def on_machine_state_clicked(self,*args):
if self.data.estopped:
return
elif not self.data.machine_on:
self.emc.machine_on(1)
self.widgets.on_label.set_text("Machine On")
else:
self.emc.machine_off(1)
self.widgets.on_label.set_text("Machine Off")
# here we override gscreen's method of hiding the cursor
# by writing a method with the same name that gscreen connects a signal to.
# and our new method in fact calls a sound method and then the hide cursor method
# that are both in gscreen
# So now we get a sound when we hide and show the pointer
def on_hide_cursor(self,widget):
self.gscreen.audio.set_sound(self.data.alert_sound)
self.gscreen.audio.run()
self.gscreen.on_hide_cursor(None)
# every 100 milli seconds this gets called
# we add calls to the regular functions for the widgets we are using.
# and add any extra calls/code
def periodic(self):
self.gscreen.update_mdi_spindle_button()
self.gscreen.update_spindle_bar()
self.gscreen.update_active_gcodes()
self.gscreen.update_active_mcodes()
self.gscreen.update_aux_coolant_pins()
self.gscreen.update_feed_speed_label()
self.gscreen.update_tool_label()
self.gscreen.update_coolant_leds()
self.gscreen.update_estop_led()
self.gscreen.update_machine_on_led()
self.gscreen.update_limit_override()
self.gscreen.update_override_label()
self.gscreen.update_jog_rate_label()
self.gscreen.update_mode_label()
self.gscreen.update_units_button_label()
def get_handlers(halcomp,builder,useropts,gscreen):
return [HandlerClass(halcomp,builder,useropts,gscreen)]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,239 @@
# This is a component of LinuxCNC
# Copyright 2013, 2014 Chris Morley <chrisinnanaimo@hotmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
import hal
from gi.repository import Gtk as gtk
_X = 0;_Y = 1;_Z = 2;_A = 3;_B = 4;_C = 5;_U = 6;_V = 7;_W = 8
# This is a handler file for using Gscreen's infrastructure
# to load a completely custom glade screen
# The only things that really matters is that it's saved as a GTK builder project,
# the toplevel window is caller window1 (The default name) and you connect a destroy
# window signal else you can't close down linuxcnc
class HandlerClass:
# This will be pretty standard to gain access to everything
# emc is for control and status of linuxcnc
# data is important data from gscreen and linuxcnc
# widgets is all the widgets from the glade files
# gscreen is for access to gscreens methods
def __init__(self, halcomp,builder,useropts,gscreen):
self.emc = gscreen.emc
self.data = gscreen.data
self.widgets = gscreen.widgets
self.gscreen = gscreen
def jog_x(self,widget,direction,state):
self.gscreen.do_key_jog(_X,direction,state)
def jog_y(self,widget,direction,state):
self.gscreen.do_key_jog(_Y,direction,state)
def jog_z(self,widget,direction,state):
self.gscreen.do_key_jog(_Z,direction,state)
def on_scale_jog_value_changed(self,widget):
self.gscreen.set_jog_rate(absolute=widget.get_value())
def on_jog_speed_changed(self,widget):
self.data.current_jogincr_index = widget.get_active()
def on_show_alarm_page(self,widget):
self.widgets.notebook_debug.set_show_tabs(self.widgets.menuitem5.get_active())
self.widgets.notebook_debug.set_current_page(0)
def on_gremlin_radiobutton_toggled(self,widget):
data = widget.get_active()
if data:
if widget == self.widgets.show_dro:
state = dro = True
offsets = False
elif widget == self.widgets.show_offsets:
dro = offsets = True
state = False
else:
offsets = dro = False
state = True
self.widgets.gremlin.set_property('enable_dro', dro)
self.widgets.gremlin.set_property('show_program', state)
self.widgets.gremlin.set_property('show_limits', state)
self.widgets.gremlin.set_property('show_extents_option', state)
self.widgets.gremlin.set_property('show_live_plot', state)
self.widgets.gremlin.set_property('show_tool', state)
self.widgets.gremlin.show_offsets = offsets
def on_gremlin_view_toggled(self,widget):
self.gscreen.toggle_view()
label = self.data.plot_view[0].upper()
widget.set_label('View %s'% label)
# erase the ready-to-home message on statusbar
def on_hal_status_all_homed(self,widget):
self.data.all_homed = True
self.widgets.statusbar1.remove_message(self.gscreen.statusbar_id,self.gscreen.homed_status_message)
# when run is pressed, destroy the restart dialog if it's showing
def on_toolbutton_run_toggled(self,widget):
if not self.data.restart_dialog == None:
self.data.restart_dialog.destroy()
self.data.restart_dialog = None
# This connects signals without using glade's autoconnect method
def connect_signals(self,handlers):
signal_list = [ ["window1","destroy", "on_window1_destroy"],
["restart","clicked", "launch_restart_dialog"],
["metric_select","clicked","on_metric_select_clicked"],
["s_run","clicked","on_button_spindle_controls_clicked"],
["spindle_control","clicked", "on_spindle_control_clicked"],
["spindle_preset","clicked", "on_preset_spindle"],
["spindle_increase","clicked", "on_spindle_speed_adjust"],
["spindle_decrease","clicked", "on_spindle_speed_adjust"],
["run_halshow","clicked", "on_halshow"],
["run_calibration","clicked", "on_calibration"],
["run_status","clicked", "on_status"],
["run_halmeter","clicked", "on_halmeter"],
["run_halscope","clicked", "on_halscope"],
["run_ladder","clicked", "on_ladder"],
]
for i in signal_list:
if len(i) == 3:
self.widgets[i[0]].connect(i[1], self.gscreen[i[2]])
elif len(i) == 4:
self.widgets[i[0]].connect(i[1], self.gscreen[i[2]],i[3])
self.widgets.toolbutton_run.connect("toggled",self.on_toolbutton_run_toggled)
self.widgets.scale_jog.connect("value_changed",self.on_scale_jog_value_changed)
self.widgets.menuitem5.connect("activate",self.on_show_alarm_page)
self.widgets.show_dro.connect('toggled',self.on_gremlin_radiobutton_toggled)
self.widgets.show_offsets.connect('toggled',self.on_gremlin_radiobutton_toggled)
self.widgets.show_clean.connect('toggled',self.on_gremlin_radiobutton_toggled)
self.widgets.view.connect('clicked',self.on_gremlin_view_toggled)
self.widgets.zoom_in.connect("clicked",lambda i:self.gscreen.zoom_in())
self.widgets.zoom_out.connect("clicked",lambda i:self.gscreen.zoom_out())
self.widgets.jog_speed.connect("changed",self.on_jog_speed_changed)
self.widgets.sneg.connect("clicked",lambda i:self.gscreen.spindle_adjustment(False,True))
self.widgets.spos.connect("clicked",lambda i:self.gscreen.spindle_adjustment(True,True))
for i in('x','y','z'):
self.widgets['touch_off'+i].connect("clicked", self.on_touch_off_clicked,i)
self.widgets[i+'neg'].connect("pressed", self['jog_'+i],0,True)
self.widgets[i+'neg'].connect("released", self['jog_'+i],0,False)
self.widgets[i+'pos'].connect("pressed", self['jog_'+i],1,True)
self.widgets[i+'pos'].connect("released", self['jog_'+i],1,False)
# We don't want Gscreen to initialize it's regular widgets because this custom
# screen doesn't have most of them. So we add this function call.
# Since this custom screen uses gladeVCP magic for its interaction with linuxcnc
# We don't add much to this function, but we do want to be able to change the theme so:
# We change the GTK theme to what's in gscreen's preference file.
# gscreen.change_theme() is a method in gscreen that changes the GTK theme of window1
# gscreen.data.theme_name is the name of the theme from the preference file
# To truely be friendly, we should add a way to change the theme directly in the custom screen.
# we also set up the statusbar and add a ready-to-home message
def initialize_widgets(self):
self.gscreen.init_show_windows()
self.gscreen.init_dynamic_tabs()
self.gscreen.init_embeded_terminal()
#self.gscreen.change_theme(self.data.theme_name)
settings = gtk.Settings.get_default()
settings.set_string_property("gtk-theme-name", 'Link to gaxis_theme', "")
self.gscreen.statusbar_id = self.widgets.statusbar1.get_context_id("Statusbar1")
self.gscreen.homed_status_message = self.widgets.statusbar1.push(1,"Ready For Homing")
model = self.widgets.jog_speed.get_model()
for num,i in enumerate(self.data.jog_increments):
model.append([i])
if i == "continuous":
self.data.current_jogincr_index = num
self.widgets.jog_speed.set_active(num)
self.gscreen.set_dro_units(self.data.dro_units)
self.widgets.adjustment_jog.set_upper(self.data.jog_rate_max)
self.widgets.adjustment_jog.set_value(self.data.jog_rate)
self.widgets.notebook_debug.set_show_tabs(False)
#self.gscreen.keylookup.add_conversion('F4','TEST2','on_keycall_POWER')
self.widgets.show_dro.set_active(True)
# name widgets for theme visual control
# with a modified theme gtkrc file these widgets can be visually modified
self.widgets.button_estop.get_child().set_name('button_estop')
self.widgets.button_machine_on.get_child().set_name('button_machine_on')
# If we need extra HAL pins here is where we do it.
# Note you must import hal at the top of this script to build the pins here. or:
# For gaxis there is only jog pins so we call gscreen to
# add it's default jog pins
def initialize_pins(self):
self.gscreen.init_jog_pins()
# checks the current operating mode according to the UI
def check_mode(self):
string = []
if self.data.mode_order[0] == self.data._MAN and self.widgets.notebook_main.get_current_page() == 1:
string.append( self.data._MAN)
string.append(self.data._JOG)
return string
# keybinding calls
def on_keycall_ESTOP(self,state,SHIFT,CNTRL,ALT):
if state: # only activate when pushed not when released
self.widgets.emc_toggle_estop.emit('activate')
return True
def on_keycall_POWER(self,state,SHIFT,CNTRL,ALT):
if state:
self.widgets.emc_toggle_power.emit('activate')
return True
def on_keycall_INCREMENTS(self,state,SHIFT,CNTRL,ALT):
if state and self.data._MAN in self.check_mode(): # manual mode required
if SHIFT:
self.gscreen.set_jog_increments(index_dir = -1)
else:
self.gscreen.set_jog_increments(index_dir = 1)
# update the combo box
self.widgets.jog_speed.set_active(self.data.current_jogincr_index)
return True
def on_touch_off_clicked(self,widget,axis):
self.gscreen.launch_numerical_input("on_offset_origin_entry_return",axis,None,"Touch off %s"% axis.upper())
def on_offset_origin_entry_return(self,widget,result,calc,axis,userdata2):
value = calc.get_value()
if result == gtk.ResponseType.ACCEPT:
if value == None:
return
if not axis == "s":
if axis in('a','b','c'):
pos = self.gscreen.get_qualified_input(value,switch=_DEGREE_INPUT)
else:
pos = self.gscreen.get_qualified_input(value)
self.gscreen.mdi_control.set_axis(axis,pos)
self.gscreen.reload_plot()
widget.destroy()
self.data.entry_dialog = None
def on_gremlin_line_clicked(self,widget,line):
self.widgets.gcode_view.set_line_number(line)
# every 100 milli seconds this gets called
# add pass so gscreen doesn't try to update it's regular widgets or
# add the individual function names that you would like to call.
# In this case we wish to call Gscreen's default function for units button update
def periodic(self):
self.gscreen.update_units_button_label()
def __getitem__(self, item):
return getattr(self, item)
def __setitem__(self, item, value):
return setattr(self, item, value)
# standard handler call
def get_handlers(halcomp,builder,useropts,gscreen):
return [HandlerClass(halcomp,builder,useropts,gscreen)]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,216 @@
# Copyright: 2014
# Author: Chris Morley <chrisinnanaimo@hotmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import hal
import gtk
_X = 0;_Y = 1;_Z = 2;_A = 3;_B = 4;_C = 5;_U = 6;_V = 7;_W = 8
# This is a handler file for using Gscreen's infrastructure
# to load a completely custom glade screen
# The only things that really matters is that it's saved as a GTK builder project,
# the toplevel window is caller window1 (The default name) and you connect a destroy
# window signal else you can't close down linuxcnc
class HandlerClass:
# This will be pretty standard to gain access to everything
# emc is for control and status of linuxcnc
# data is important data from gscreen and linuxcnc
# widgets is all the widgets from the glade files
# gscreen is for access to gscreens methods
def __init__(self, halcomp,builder,useropts,gscreen):
self.emc = gscreen.emc
self.data = gscreen.data
self.widgets = gscreen.widgets
self.gscreen = gscreen
def jog_x(self,widget,direction,state):
self.gscreen.do_key_jog(_X,direction,state)
def jog_y(self,widget,direction,state):
self.gscreen.do_key_jog(_Y,direction,state)
def jog_z(self,widget,direction,state):
self.gscreen.do_key_jog(_Z,direction,state)
def on_scale_jog_value_changed(self,widget):
self.gscreen.set_jog_rate(absolute=widget.get_value())
def on_scale_fo_value_changed(self,widget):
self.gscreen.set_feed_override((widget.get_value()/100),True)
def on_scale_so_value_changed(self,widget):
self.gscreen.set_spindle_override((widget.get_value()/100),True)
def on_scale_mv_value_changed(self,widget):
self.gscreen.set_velocity_override((widget.get_value()/100),True)
def on_jog_speed_changed(self,widget):
self.data.current_jogincr_index = widget.get_active()
def on_show_alarm_page(self,widget):
self.widgets.notebook_debug.set_show_tabs(self.widgets.menuitem5.get_active())
self.widgets.notebook_debug.set_current_page(0)
# erase the ready-to-home message on statusbar
def on_hal_status_all_homed(self,widget):
print("all-homed")
self.data.all_homed = True
self.widgets.statusbar1.remove_message(self.gscreen.statusbar_id,self.gscreen.homed_status_message)
# when run is pressed, destroy the restart dialog if it's showing
def on_toolbutton_run_toggled(self,widget):
if not self.data.restart_dialog == None:
self.data.restart_dialog.destroy()
self.data.restart_dialog = None
# This connects signals without using glade's autoconnect method
def connect_signals(self,handlers):
signal_list = [ ["window1","destroy", "on_window1_destroy"],
["restart","clicked", "launch_restart_dialog"],
["metric_select","clicked","on_metric_select_clicked"],
["s_run","clicked","on_button_spindle_controls_clicked"],
["spindle_control","clicked", "on_spindle_control_clicked"],
["spindle_preset","clicked", "on_preset_spindle"],
["spindle_increase","clicked", "on_spindle_speed_adjust"],
["spindle_decrease","clicked", "on_spindle_speed_adjust"],
["run_halshow","clicked", "on_halshow"],
["run_calibration","clicked", "on_calibration"],
["run_status","clicked", "on_status"],
["run_halmeter","clicked", "on_halmeter"],
["run_halscope","clicked", "on_halscope"],
["run_ladder","clicked", "on_ladder"],
]
for i in signal_list:
if len(i) == 3:
self.widgets[i[0]].connect(i[1], self.gscreen[i[2]])
elif len(i) == 4:
self.widgets[i[0]].connect(i[1], self.gscreen[i[2]],i[3])
self.widgets.toolbutton_run.connect("toggled",self.on_toolbutton_run_toggled)
self.widgets.scale_jog.connect("value_changed",self.on_scale_jog_value_changed)
self.widgets.scale_fo.connect("value_changed",self.on_scale_fo_value_changed)
self.widgets.scale_so.connect("value_changed",self.on_scale_so_value_changed)
self.widgets.scale_mv.connect("value_changed",self.on_scale_mv_value_changed)
self.widgets.menuitem5.connect("activate",self.on_show_alarm_page)
self.widgets.jog_speed.connect("changed",self.on_jog_speed_changed)
self.widgets.sneg.connect("clicked",lambda i:self.gscreen.spindle_adjustment(False,True))
self.widgets.spos.connect("clicked",lambda i:self.gscreen.spindle_adjustment(True,True))
for i in('x','y','z'):
self.widgets['touch_off'+i].connect("clicked", self.on_touch_off_clicked,i)
self.widgets[i+'neg'].connect("pressed", self['jog_'+i],0,True)
self.widgets[i+'neg'].connect("released", self['jog_'+i],0,False)
self.widgets[i+'pos'].connect("pressed", self['jog_'+i],1,True)
self.widgets[i+'pos'].connect("released", self['jog_'+i],1,False)
# We don't want Gscreen to initialize it's regular widgets because this custom
# screen doesn't have most of them. So we add this function call.
# Since this custom screen uses gladeVCP magic for its interaction with linuxcnc
# We don't add much to this function, but we do want to be able to change the theme so:
# We change the GTK theme to what's in gscreen's preference file.
# gscreen.change_theme() is a method in gscreen that changes the GTK theme of window1
# gscreen.data.theme_name is the name of the theme from the preference file
# To truely be friendly, we should add a way to change the theme directly in the custom screen.
# we also set up the statusbar and add a ready-to-home message
def initialize_widgets(self):
self.gscreen.init_show_windows()
self.gscreen.init_dynamic_tabs()
self.gscreen.init_embeded_terminal()
self.gscreen.change_theme(self.data.theme_name)
self.gscreen.statusbar_id = self.widgets.statusbar1.get_context_id("Statusbar1")
self.gscreen.homed_status_message = self.widgets.statusbar1.push(1,"Ready For Homing")
model = self.widgets.jog_speed.get_model()
for num,i in enumerate(self.data.jog_increments):
model.append([i])
if i == "continuous":
self.data.current_jogincr_index = num
self.widgets.jog_speed.set_active(num)
# self.gscreen.set_dro_units(self.data.dro_units)
self.widgets.adjustment_mv.set_value(self.data.maxvelocity*100)
self.widgets.adjustment_jog.set_upper(self.data.jog_rate_max)
self.widgets.adjustment_jog.set_value(self.data.jog_rate)
self.widgets.adjustment_fo.set_upper(self.data.feed_override_max*100)
self.widgets.adjustment_fo.set_value(self.data.feed_override*100)
self.widgets.adjustment_so.set_upper(self.data.spindle_override_max*100)
self.widgets.adjustment_so.set_value(self.data.spindle_override*100)
self.widgets.notebook_debug.set_show_tabs(False)
#self.gscreen.keylookup.add_conversion('F4','TEST2','on_keycall_POWER')
# If we need extra HAL pins here is where we do it.
# Note you must import hal at the top of this script to build the pins here. or:
# For gaxis there is only jog pins so we call gscreen to
# add it's default jog pins
def initialize_pins(self):
self.gscreen.init_jog_pins()
# checks the current operating mode according to the UI
def check_mode(self):
string = []
if self.data.mode_order[0] == self.data._MAN and self.widgets.notebook_main.get_current_page() == 1:
string.append( self.data._MAN)
string.append(self.data._JOG)
return string
# keybinding calls
def on_keycall_ESTOP(self,state,SHIFT,CNTRL,ALT):
if state:
self.widgets.emc_toggle_estop.emit('activate')
return True
def on_keycall_POWER(self,state,SHIFT,CNTRL,ALT):
if state:
self.widgets.emc_toggle_power.emit('activate')
return True
def on_keycall_INCREMENTS(self,state,SHIFT,CNTRL,ALT):
if state and self.data._MAN in self.check_mode(): # manual mode required
print('hi')
if SHIFT:
self.gscreen.set_jog_increments(index_dir = -1)
else:
self.gscreen.set_jog_increments(index_dir = 1)
# update the combo box
self.widgets.jog_speed.set_active(self.data.current_jogincr_index)
return True
def on_touch_off_clicked(self,widget,axis):
self.gscreen.launch_numerical_input("on_offset_origin_entry_return",axis,None,"Touch off %s"% axis.upper())
def on_offset_origin_entry_return(self,widget,result,calc,axis,userdata2):
value = calc.get_value()
if result == gtk.ResponseType.ACCEPT:
if value == None:
return
if not axis == "s":
if axis in('a','b','c'):
pos = self.gscreen.get_qualified_input(value,switch=_DEGREE_INPUT)
else:
pos = self.gscreen.get_qualified_input(value)
self.gscreen.mdi_control.set_axis(axis,pos)
self.gscreen.reload_plot()
widget.destroy()
self.data.entry_dialog = None
# every 100 milli seconds this gets called
# add pass so gscreen doesn't try to update it's regular widgets or
# add the individual function names that you would like to call.
# In this case we wish to call Gscreen's default function for units button update
def periodic(self):
self.gscreen.update_units_button_label()
def __getitem__(self, item):
return getattr(self, item)
def __setitem__(self, item, value):
return setattr(self, item, value)
# standard handler call
def get_handlers(halcomp,builder,useropts,gscreen):
return [HandlerClass(halcomp,builder,useropts,gscreen)]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.16"/>
<requires lib="gladevcp" version="0.0"/>
<object class="GtkWindow" id="window2">
<property name="height-request">600</property>
<property name="can-focus">False</property>
<child>
<object class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="n-rows">3</property>
<property name="n-columns">3</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<object class="HAL_Meter" id="s_display2">
<property name="width-request">200</property>
<property name="height-request">200</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="bg-color">#ffffffffffff</property>
<property name="label">Spindle</property>
<property name="majorscale">200</property>
<property name="max">2000</property>
<property name="sublabel">RPM</property>
<property name="z0-color">#0000ffff0000</property>
<property name="z1-color">#ffffffff0000</property>
<property name="z2-color">#ffff00000000</property>
</object>
<packing>
<property name="left-attach">2</property>
<property name="right-attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">screen 2</property>
</object>
<packing>
<property name="left-attach">2</property>
<property name="right-attach">3</property>
<property name="top-attach">1</property>
<property name="bottom-attach">2</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">Custom
Button</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_button_press" swapped="no"/>
</object>
<packing>
<property name="left-attach">2</property>
<property name="right-attach">3</property>
<property name="top-attach">2</property>
<property name="bottom-attach">3</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -0,0 +1,430 @@
# This is a component of LinuxCNC
# Copyright 2013 Chris Morley <chrisinnanaimo@hotmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
import gi
from gi.repository import Gtk as gtk
from gi.repository import Gdk
from gi.repository import Pango as pango
import hal
import gladevcp.makepins # needed for the dialog's calulator widget
_MAN = 0;_MDI = 1;_AUTO = 2;_LOCKTOGGLE = 1
# This is a handler file for using Gscreen's infrastructure
# to load a completely custom glade screen
# The only things that really matters is that it's saved as a GTK builder project,
# the toplevel window is caller window1 (The default name) and you connect a destroy
# window signal else you can't close down linuxcnc
class HandlerClass:
# This will be pretty standard to gain access to everything
# emc is for control and status of linuxcnc
# data is important data from gscreen and linuxcnc
# widgets is all the widgets from the glade files
# gscreen is for access to gscreens methods
def __init__(self, halcomp,builder,useropts,gscreen):
self.emc = gscreen.emc
self.data = gscreen.data
self.widgets = gscreen.widgets
self.gscreen = gscreen
# This is a new method that calls a gscreen method to toggle the DRO units
# Gscreen's regular unit button saves the state
# for startup, This one just changes it for the session
def on_metric_select_clicked(self,widget):
data = (self.data.dro_units -1) * -1
self.gscreen.set_dro_units(data,False)
for i in ("1","2","3"):
for letter in self.data.axis_list:
axis = "dro_%s%s"% (letter,i)
try:
self.widgets[axis].set_property("display_units_mm",data)
except:
pass
def on_diameter_mode_pressed(self, widget):
data = widget.get_active()
print("switch diam mode",data)
self.gscreen.set_diameter_mode(data)
for i in ("1","2","3"):
axis = "dro_x%s"% (i)
if data:
self.widgets[axis].set_to_diameter()
else:
self.widgets[axis].set_to_radius()
# This is a new method for our button
# we selected this method name in the glade file as a signal callback
def on_estop_clicked(self,*args):
print("estop")
if self.data.estopped:
self.emc.estop_reset(1)
self.gscreen.add_alarm_entry("Machine Estop Reset")
else:
self.emc.machine_off(1)
self.emc.estop(1)
self.widgets.on_label.set_text("Machine Off")
self.gscreen.add_alarm_entry("Machine Estopped and Powered Off")
return True
# This is a new method for our new button
# we selected this method name in the glade file as a signal callback
def on_machine_state_clicked(self,widget):
if self.data.estopped:
return
elif not self.data.machine_on:
self.emc.machine_on(1)
self.widgets.on_label.set_text("Machine On")
self.gscreen.add_alarm_entry("Machine powered on")
else:
self.emc.machine_off(1)
self.widgets.on_label.set_text("Machine Off")
self.gscreen.add_alarm_entry("Machine powered off")
# display the main tab and set the mode to setup
def on_setup_button_clicked(self,widget):
self.widgets.notebook_main.set_current_page(0)
self.data.mode_order = _MAN,_MDI,_AUTO
label = self.data.mode_labels
self.widgets.button_mode.set_label(label[self.data.mode_order[0]])
self.gscreen.mode_changed(self.data.mode_order[0])
self.toggle_modes(widget)
# display the main tab and set the mode to run
def on_run_button_clicked(self,widget):
self.widgets.notebook_main.set_current_page(0)
self.data.mode_order = _AUTO,_MAN,_MDI
label = self.data.mode_labels
self.widgets.button_mode.set_label(label[self.data.mode_order[0]])
self.gscreen.mode_changed(self.data.mode_order[0])
self.toggle_modes(widget)
# display the main tab and set the mode to MDI
def on_mdi_button_clicked(self,widget):
self.widgets.notebook_main.set_current_page(0)
self.data.mode_order = _MDI,_MAN,_AUTO
label = self.data.mode_labels
self.widgets.button_mode.set_label(label[self.data.mode_order[0]])
self.gscreen.mode_changed(self.data.mode_order[0])
self.toggle_modes(widget)
# This is called when the system button is toggled
# If the page is not showing it displays a unlock code dialog
# unless you have already unlocked the page.
# if that returns true then the page is shown
# otherwise the button is untoggled and the page is not shown
# if you press the system buttonn when the system page is already showing
# it will relock the page
def on_system_button_clicked(self,widget):
if self.widgets.notebook_main.get_current_page() == 4:
self.gscreen.block("system_button")
widget.set_active(True)
self.gscreen.unblock("system_button")
global _LOCKTOGGLE
_LOCKTOGGLE=1
self.widgets.system_button.set_label(" System\n(Locked)")
self.gscreen.add_alarm_entry("System page re-locked")
self.on_setup_button_clicked(self.widgets.setup_button)
return
if not self.system_dialog():
self.gscreen.block("system_button")
widget.set_active(False)
self.gscreen.unblock("system_button")
return
self.widgets.notebook_main.set_current_page(4)
self.toggle_modes(widget)
self.widgets.system_button.set_label(" System\n ")
# Display the tooledit tab
def on_tooledit_button_clicked(self,widget):
self.widgets.notebook_main.set_current_page(3)
self.toggle_modes(widget)
# Display the offsetpage tab
def on_offsetpage_button_clicked(self,widget):
self.widgets.notebook_main.set_current_page(2)
self.toggle_modes(widget)
# This toggles the buttons so only one is presses at any one time
def toggle_modes(self,widget):
temp = "setup_button","mdi_button","run_button","tooledit_button","system_button","offsetpage_button"
for i in temp:
state = False
if self.widgets[i] == widget: state = True
self.gscreen.block(i)
self.widgets[i].set_active(state)
self.gscreen.unblock(i)
def on_button_edit_clicked(self,widget):
state = widget.get_active()
if not state:
self.gscreen.edited_gcode_check()
self.widgets.notebook_main.set_current_page(0)
self.widgets.notebook_main.set_show_tabs(not (state))
self.gscreen.edit_mode(state)
if not state and self.widgets.button_full_view.get_active():
self.gscreen.set_full_graphics_view(True)
if self.data.edit_mode:
self.widgets.mode_select_box.hide()
self.widgets.search_box.show()
self.widgets.button_edit.set_label("Exit\nEdit")
else:
self.widgets.mode_select_box.show()
self.widgets.search_box.hide()
self.widgets.button_edit.set_label("Edit")
self.widgets.notebook_main.set_show_tabs(False)
# This dialog is for unlocking the system tab
# The unlock code number is defined at the top of the page
def system_dialog(self):
global _LOCKTOGGLE
if _LOCKTOGGLE == 0: return True
dialog = gtk.Dialog("Enter System Unlock Code",
self.widgets.window1,
gtk.DialogFlags.DESTROY_WITH_PARENT)
label = gtk.Label("Enter System Unlock Code")
label.modify_font(pango.FontDescription("sans 20"))
calc = gladevcp.Calculator()
dialog.vbox.pack_start(label,True,True,0)
dialog.vbox.add(calc)
calc.set_value("")
calc.set_property("font","sans 20")
calc.set_editable(True)
calc.entry.connect("activate", lambda w : dialog.emit('response',gtk.ResponseType.ACCEPT))
calc.integer_entry_only(True)
calc.num_pad_only(True)
dialog.parse_geometry("360x400")
dialog.set_decorated(False)
dialog.show_all()
response = dialog.run()
code = calc.get_value()
dialog.destroy()
if response == gtk.ResponseType.ACCEPT:
if code == int(self.data.unlock_code):
self.gscreen.add_alarm_entry("System page unlocked")
_LOCKTOGGLE = 0
return True
_LOCKTOGGLE = 1
return False
def _get_RGBA_color(self, color_raw):
def convert_color(color):
colortuple = ((int(color.red * 255.0), int(color.green * 255.0), int(color.blue * 255.0)))
return ('#' + ''.join(f'{i:02X}' for i in colortuple))
# convert string RGB to 8bit RGBA
if type(color_raw) == str:
color = Gdk.RGBA()
color.parse(color_raw)
return convert_color(Gdk.RGBA(color.red, color.green, color.blue, color.alpha))
# convert old 16bit RGB to 8bit RGBA
elif type(color_raw) == tuple:
b = Gdk.RGBA(color_raw[0], color_raw[1], color_raw[2], 0)
color = Gdk.RGBA()
color.parse(b.to_string())
return convert_color(Gdk.RGBA(color.red, color.green, color.blue, color.alpha))
def on_abs_colorbutton_color_set(self,widget):
self.gscreen.set_abs_color()
for i in self.data.axis_list:
axis = "dro_%s1"% i
color = self._get_RGBA_color(self.data.abs_color)
self.widgets[axis].set_style("labelcolor", color )
def on_rel_colorbutton_color_set(self,widget):
self.gscreen.set_rel_color()
color = self._get_RGBA_color(self.data.rel_color)
for i in self.data.axis_list:
axis = "dro_%s2"% i
self.widgets[axis].set_style("labelcolor", color )
def on_dtg_colorbutton_color_set(self,widget):
self.gscreen.set_dtg_color()
color = self._get_RGBA_color(self.data.dtg_color)
for i in self.data.axis_list:
axis = "dro_%s3"% i
self.widgets[axis].set_style("labelcolor", color )
def on_hal_status_not_all_homed(self,widget,data):
temp =[]
for letter in self.data.axis_list:
axnum = "xyzabcuvws".index(letter)
if str(axnum) in data:
self.widgets["home_%s"%letter].set_text(" ")
temp.append(" %s"%letter.upper())
self.gscreen.add_alarm_entry(_("There are unhomed axes: %s"%temp))
def on_hal_status_axis_homed(self,widget,data):
for letter in self.data.axis_list:
axnum = "xyzabcuvws".index(letter)
if str(axnum) in data:
self.widgets["home_%s"%letter].set_text("*")
else:
self.widgets["home_%s"%letter].set_text(" ")
def on_show_dtg_pressed(self, widget):
data = widget.get_active()
self.widgets.dtg_vbox.set_visible(data)
self.gscreen.set_show_dtg(data)
# Connect to gscreens regular signals and add a couple more
def connect_signals(self,handlers):
self.gscreen.connect_signals(handlers)
# connect to handler file callbacks:
self.gscreen.widgets.metric_select.connect("clicked", self.on_metric_select_clicked)
self.gscreen.widgets.diameter_mode.connect("clicked", self.on_diameter_mode_pressed)
temp = "setup_button","mdi_button","run_button","tooledit_button","system_button","offsetpage_button"
for cb in temp:
i = "_sighandler_%s"% (cb)
self.data[i] = int(self.widgets[cb].connect("toggled", self["on_%s_clicked"%cb]))
self.widgets.hal_status.connect("not-all-homed",self.on_hal_status_not_all_homed)
self.widgets.hal_status.connect("homed",self.on_hal_status_axis_homed)
self.widgets.abs_colorbutton.connect("color-set", self.on_abs_colorbutton_color_set)
self.widgets.rel_colorbutton.connect("color-set", self.on_rel_colorbutton_color_set)
self.widgets.dtg_colorbutton.connect("color-set", self.on_dtg_colorbutton_color_set)
self.widgets.unlock_number.connect("value-changed",self.gscreen.on_unlock_number_value_changed)
self.widgets.show_dtg.connect("clicked", self.on_show_dtg_pressed)
# We don't want Gscreen to initialize ALL it's regular widgets because this custom
# screen doesn't have them all -just most of them. So we call the ones we want
def initialize_widgets(self):
self.gscreen.init_show_windows()
self.gscreen.init_dynamic_tabs()
#self.gscreen.init_axis_frames()
#self.gscreen.init_dro_colors()
self.gscreen.init_screen2()
self.gscreen.init_fullscreen1()
self.gscreen.init_gremlin()
self.gscreen.init_manual_spindle_controls()
self.gscreen.init_dro_colors()
self.init_dro() # local function
self.gscreen.init_audio()
self.gscreen.init_desktop_notify()
self.gscreen.init_statusbar()
self.gscreen.init_entry()
self.gscreen.init_tooleditor()
self.gscreen.init_offsetpage()
self.gscreen.init_embeded_terminal()
self.gscreen.init_themes()
self.gscreen.init_screen1_geometry()
self.gscreen.init_running_options()
self.gscreen.init_hide_cursor()
#self.gscreen.init_mode()
self.gscreen.mode_changed(self.data.mode_order[0])
self.gscreen.init_sensitive_on_off()
self.gscreen.init_sensitive_run_idle()
self.gscreen.init_sensitive_all_homed()
self.gscreen.init_sensitive_override_mode()
self.gscreen.init_sensitive_graphics_mode()
self.gscreen.init_sensitive_origin_mode()
self.init_sensitive_edit_mode() # local function
for i in ("setup_button","mdi_button","run_button","tooledit_button","offsetpage_button","button_index_tool"):
self.data.sensitive_override_mode.append(i)
self.data.sensitive_graphics_mode.append(i)
self.data.sensitive_origin_mode.append(i)
self.widgets["spindle-at-speed"].set_property("on_color","black")
self.gscreen.init_unlock_code()
self.gscreen.init_state()
for i in ('x','y','z','a','b','c','u','v','w'):
if i in self.data.axis_list:
self.widgets["dro_%s1"%i].show()
self.widgets["dro_%s2"%i].show()
self.widgets["dro_%s3"%i].show()
self.widgets["axis_%s"%i].show()
self.widgets["home_%s"%i].show()
else:
self.widgets["dro_%s1"%i].hide()
self.widgets["dro_%s2"%i].hide()
self.widgets["dro_%s3"%i].hide()
self.widgets["axis_%s"%i].hide()
self.widgets["home_%s"%i].hide()
#self.widgets.offsetpage1.set_highlight_color("lightblue")
self.widgets.offsetpage1.set_font("sans 18")
self.widgets.offsetpage1.set_row_visible("1",False)
self.widgets.tooledit1.set_font("sans 18")
if self.data.embedded_keyboard:
self.gscreen.launch_keyboard()
def init_sensitive_edit_mode(self):
self.data.sensitive_edit_mode = ["button_graphics","button_override","button_restart","button_cycle_start","button_single_step",
"run_button","setup_button","mdi_button","system_button","tooledit_button","ignore_limits",
"offsetpage_button"]
def init_dro(self):
self.on_abs_colorbutton_color_set(None)
self.on_rel_colorbutton_color_set(None)
self.on_dtg_colorbutton_color_set(None)
self.widgets.show_dtg.set_active(self.data.show_dtg)
self.on_show_dtg_pressed(self.widgets.show_dtg)
self.gscreen.init_dro()
data = self.data.dro_units
for i in ("1","2","3"):
for letter in self.data.axis_list:
axis = "dro_%s%s"% (letter,i)
try:
self.widgets[axis].set_property("display_units_mm",data)
except:
pass
# every 100 milli seconds this gets called
# we add calls to the regular functions for the widgets we are using.
# and add any extra calls/code
def periodic(self):
self.update_mdi_spindle_button() # local method
self.gscreen.update_spindle_bar()
#self.gscreen.update_dro()
self.gscreen.update_active_gcodes()
self.gscreen.update_active_mcodes()
self.gscreen.update_aux_coolant_pins()
self.gscreen.update_feed_speed_label()
self.gscreen.update_tool_label()
self.gscreen.update_coolant_leds()
self.gscreen.update_estop_led()
self.gscreen.update_machine_on_led()
self.gscreen.update_limit_override()
self.gscreen.update_override_label()
self.gscreen.update_jog_rate_label()
self.gscreen.update_mode_label()
self.gscreen.update_units_button_label()
# spindle controls
def update_mdi_spindle_button(self):
self.widgets.at_speed_label.set_label(_("%d RPM"%abs(self.data.spindle_speed)))
label = self.widgets.spindle_control.get_label()
speed = self.data.spindle_speed
if speed == 0 and not label == _("Start"):
temp = _("Start")
self.widgets["spindle-at-speed"].set_property("on_color","black")
elif speed and not label == _("Stop"):
temp = _("Stop")
self.widgets["spindle-at-speed"].set_property("on_color","green")
else: return
self.widgets.spindle_control.set_label(temp)
def __getitem__(self, item):
return getattr(self, item)
def __setitem__(self, item, value):
return setattr(self, item, value)
# standard handler call
def get_handlers(halcomp,builder,useropts,gscreen):
return [HandlerClass(halcomp,builder,useropts,gscreen)]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,471 @@
# This is a component of LinuxCNC
# Copyright 2013 Chris Morley <chrisinnanaimo@hotmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#############################################################################
# This is a gscreen skin customized for a Bridgeport Interact Mill that used a
# Heidenhain TNC 151a controller.
# Chris Brady Oct 2015
#
import gi
from gi.repository import Gtk as gtk
from gi.repository import Pango as pango
import hal
import gladevcp.makepins # needed for the dialog's calulator widget
import hal_glib
_MAN = 0;_MDI = 1;_AUTO = 2;_LOCKTOGGLE = 1
# This is a handler file for using Gscreen's infrastructure
# to load a completely custom glade screen
# The only things that really matters is that it's saved as a GTK builder project,
# the toplevel window is caller window1 (The default name) and you connect a destroy
# window signal else you can't close down linuxcnc
class HandlerClass:
# This will be pretty standard to gain access to everything
# emc is for control and status of linuxcnc
# data is important data from gscreen and linuxcnc
# widgets is all the widgets from the glade files
# gscreen is for access to gscreens methods
def __init__(self, halcomp,builder,useropts,gscreen):
self.emc = gscreen.emc
self.data = gscreen.data
self.widgets = gscreen.widgets
self.gscreen = gscreen
# Hide all menus at the bottom of the default gscreen page
self.widgets.mode0.hide()
self.widgets.mode1.hide()
self.widgets.mode2.hide()
self.widgets.mode3.hide()
self.widgets.mode4.hide()
self.widgets.button_mode.hide()
self.widgets.diameter_mode.hide()
self.widgets.aux_coolant_m7.hide()
self.widgets.aux_coolant_m8.hide()
self.widgets.show_dtg.hide()
self.widgets.diameter_mode.hide()
self.widgets.button_flood.hide()
self.widgets.button_run.hide()
# Initialize variables
self.data.lathe_mode=False
self.data.graphic_ypos=0
self.data.graphic_xpos=0
self.data.view=0
self.data.homed=0
self.data.jog_rates=[30,50,80,120]
self.data.jog_incrs=[0.0002,0.001,0.01,0.1]
self.data.jog_rate_idx=2
self.widgets.jog_r1.set_label("%5.4f"% self.data.jog_incrs[0])
self.widgets.jog_r2.set_label("%4.3f"% self.data.jog_incrs[1])
self.widgets.jog_r3.set_label("%3.2f"% self.data.jog_incrs[2])
self.widgets.jog_r4.set_label("%2.1f"% self.data.jog_incrs[3])
self.widgets.button_mode.hide()
self.widgets.button_home_all.hide()
# every 100 milli seconds this gets called
# we add calls to the regular functions for the widgets we are using.
# and add any extra calls/code
def periodic(self):
self.gscreen.update_dro()
self.gscreen.update_active_gcodes()
self.gscreen.update_active_mcodes()
self.gscreen.update_feed_speed_label()
self.gscreen.update_tool_label()
self.update_estop_led()
self.gscreen.update_machine_on_led()
self.gscreen.update_jog_rate_label()
self.gscreen.update_mode_label()
self.gscreen.update_units_button_label()
self.update_override_label()
self.update_spindle()
def update_spindle(self):
# Actual speed from hal
# Limit speed representation to 1 decimal point
speed = int(self.gscreen.halcomp["spindle-spd-disp"]*10)/10
self.widgets.meter_spindle_speed.set_property("value", speed)
# Initialize hal pins that we need access to
def initialize_pins(self):
self.gscreen.init_spindle_pins()
self.gscreen.init_coolant_pins()
self.gscreen.init_jog_pins()
self.gscreen.init_override_pins()
self.gscreen.init_control_pins()
self.gscreen.halcomp.newpin("spindle-spd-disp", hal.HAL_FLOAT, hal.HAL_IN)
self.gscreen.halcomp.newpin("jog-spd-out", hal.HAL_FLOAT, hal.HAL_OUT)
self.gscreen.halcomp.newpin("jog-inc-out", hal.HAL_FLOAT, hal.HAL_OUT)
self.data['ext-estop'] = hal_glib.GPin(self.gscreen.halcomp.newpin('ext-estop', hal.HAL_BIT, hal.HAL_IN))
self.data['ext-estop'].connect('value-changed', self.on_estop_in)
self.data['enc-fault-x'] = hal_glib.GPin(self.gscreen.halcomp.newpin('enc-fault-x', hal.HAL_BIT, hal.HAL_IN))
self.data['enc-fault-x'].connect('value-changed', self.on_x_enc_fault)
self.data['enc-fault-y'] = hal_glib.GPin(self.gscreen.halcomp.newpin('enc-fault-y', hal.HAL_BIT, hal.HAL_IN))
self.data['enc-fault-y'].connect('value-changed', self.on_y_enc_fault)
self.data['enc-fault-x'] = hal_glib.GPin(self.gscreen.halcomp.newpin('enc-fault-z', hal.HAL_BIT, hal.HAL_IN))
self.data['enc-fault-x'].connect('value-changed', self.on_z_enc_fault)
def on_emc_off(self,*args):
self.widgets.button_clear.show()
self.widgets.button_mode.hide()
self.widgets.button_home_all.hide()
# Force mode to manual
self.data.mode_order = (self.data._MAN,self.data._MDI,self.data._AUTO)
label = self.data.mode_labels
self.widgets.button_mode.set_label(label[self.data.mode_order[0]])
self.mode_changed(self.data.mode_order[0])
def on_btn_clear(self,widget):
if self.gscreen.halcomp["ext-estop"] == False:
self.emc.estop_reset(1)
self.emc.machine_on(1)
self.widgets.button_clear.hide()
self.widgets.button_home_all.show()
def on_estop_in(self,widget):
self.widgets.mode0.hide()
if self.gscreen.halcomp["ext-estop"] == True:
self.emc.estop_reset(1)
self.emc.machine_on(1)
else:
self.emc.machine_off(1)
self.emc.estop(1)
def update_estop_led(self):
if self.data.estopped:
self.widgets.led_estop.set_active(False)
else:
self.widgets.led_estop.set_active(True)
def on_x_enc_fault(self,hal_object):
print("X Encoder Fault")
self.gscreen.add_alarm_entry(_("X Axis Encoder Error"))
def on_y_enc_fault(self,hal_object):
print("Y Encoder Fault")
self.gscreen.add_alarm_entry(_("Y Axis Encoder Error"))
def on_z_enc_fault(self,hal_object):
print("Z Encoder Fault")
self.gscreen.add_alarm_entry(_("Z Axis Encoder Error"))
def homing(self,*args):
self.mode_changed(self.data._MAN)
self.widgets.button_mode.hide()
self.widgets.button_home_all.show()
self.widgets.button_move_to.set_sensitive(0)
def on_hal_status_all_homed(self,widget):
self.gscreen.on_hal_status_all_homed(1)
self.data.homed=1
self.widgets.button_home_all.hide()
self.widgets.button_mode.show()
self.widgets.jog_r3.set_active(1)
self.on_jog_rate(self.widgets.jog_r3)
self.gscreen.sensitize_widgets(self.data.sensitive_all_homed,1)
self.widgets.button_move_to.set_sensitive(1)
def on_interp_run(self,*args):
self.gscreen.sensitize_widgets(self.data.sensitive_run_idle,False)
self.widgets.button_reload.set_sensitive(0)
def on_interp_idle(self,widget):
self.gscreen.on_hal_status_interp_idle(widget)
self.widgets.button_reload.set_sensitive(1)
def on_jog_rate(self,widget):
if widget == self.widgets.jog_r1:
self.data.jog_rate_idx=0
speed = self.data.jog_rates[0]
self.widgets.jog_r2.set_active(0)
self.widgets.jog_r3.set_active(0)
self.widgets.jog_r4.set_active(0)
self.gscreen.halcomp["jog-spd-out"] = speed
self.gscreen.halcomp["jog-inc-out"] = self.data.jog_incrs[0]
elif widget == self.widgets.jog_r2:
self.data.jog_rate_idx=1
speed = self.data.jog_rates[1]
self.widgets.jog_r1.set_active(0)
self.widgets.jog_r3.set_active(0)
self.widgets.jog_r4.set_active(0)
self.gscreen.halcomp["jog-spd-out"] = speed
self.gscreen.halcomp["jog-inc-out"] = self.data.jog_incrs[1]
elif widget == self.widgets.jog_r3:
self.data.jog_rate_idx=2
speed = self.data.jog_rates[2]
self.widgets.jog_r1.set_active(0)
self.widgets.jog_r2.set_active(0)
self.widgets.jog_r4.set_active(0)
self.gscreen.halcomp["jog-spd-out"] = speed
self.gscreen.halcomp["jog-inc-out"] = self.data.jog_incrs[2]
elif widget == self.widgets.jog_r4:
self.data.jog_rate_idx=3
speed = self.data.jog_rates[3]
self.widgets.jog_r1.set_active(0)
self.widgets.jog_r2.set_active(0)
self.widgets.jog_r3.set_active(0)
self.gscreen.halcomp["jog-spd-out"] = speed
self.gscreen.halcomp["jog-inc-out"] = self.data.jog_incrs[3]
def jog_point1(self,widget):
if self.data.mode_order[0] == self.data._MAN: # if in manual mode
print("jog point1")
if widget == self.widgets.jog_plus:
self.do_jog(True,True)
else:
self.do_jog(False,True)
def do_jog(self,direction,action):
# if manual mode, if jogging
# if only one axis button pressed
# jog positive at selected rate
if self.data.mode_order[0] == self.data._MAN:
if len(self.data.active_axis_buttons) > 1:
print(self.data.active_axis_buttons)
elif self.data.active_axis_buttons[0][0] == None:
self.gscreen.homed_status_message = self.widgets.statusbar1.push(1,"No axis selected to jog")
else:
if not self.data.active_axis_buttons[0][0] == "s":
if not action: cmd = 0
elif direction: cmd = 1
else: cmd = -1
self.emc.jogging(1)
jogincr = self.data.jog_incrs[self.data.jog_rate_idx]
self.emc.incremental_jog(self.data.active_axis_buttons[0][1],cmd,jogincr)
def on_mode_clicked(self,widget,event):
# only change machine modes on click
if event.type == gdk.BUTTON_PRESS:
a,b,c = self.data.mode_order
self.data.mode_order = b,c,a
label = self.data.mode_labels
self.widgets.button_mode.set_label(label[self.data.mode_order[0]])
self.mode_changed(self.data.mode_order[0])
def mode_changed(self,mode):
print("Mode Change", mode)
if mode == self.data._MAN:
self.widgets.notebook_mode.hide()
self.widgets.hal_mdihistory.hide()
self.widgets.dro_frame.show()
self.widgets.vmode0.show()
self.widgets.vmode1.hide()
self.widgets.button_run.set_active(0)
self.widgets.button_jog_mode.set_active(1)
self.widgets.button_view.emit("clicked")
elif mode == self.data._MDI:
if self.data.plot_hidden:
self.toggle_offset_view()
self.emc.set_mdi_mode()
self.widgets.hal_mdihistory.show()
self.widgets.vmode0.show()
self.widgets.vmode1.hide()
self.widgets.button_run.set_active(0)
self.widgets.notebook_mode.hide()
self.widgets.button_jog_mode.set_active(0)
elif mode == self.data._AUTO:
self.widgets.vmode0.hide()
self.widgets.vmode1.show()
self.widgets.button_run.set_active(0)
if self.data.full_graphics:
self.widgets.notebook_mode.hide()
else:
self.widgets.notebook_mode.show()
self.widgets.hal_mdihistory.hide()
self.widgets.button_jog_mode.set_active(0)
def on_button_flood(self,widget):
if self.widgets.button_flood.get_active():
self.gscreen.halcomp["aux-coolant-m8-out"] = True
else:
self.gscreen.halcomp["aux-coolant-m8-out"] = False
def on_ign_toolc_pressed(self, widget):
data = widget.get_active()
def on_tool_change(self,widget):
if self.widgets.ignore_toolchange.get_active() == True:
self.gscreen.halcomp["tool-changed"] = True
else:
h = self.gscreen.halcomp
c = h['change-tool']
n = h['tool-number']
cd = h['tool-changed']
print("tool change",c,cd,n)
if c:
message = _("Please change to tool # %s, then click OK."% n)
self.gscreen.warning_dialog(message, True,pinname="TOOLCHANGE")
else:
h['tool-changed'] = False
def on_button_edit_clicked(self,widget):
state = widget.get_active()
if not state:
self.gscreen.edited_gcode_check()
self.widgets.notebook_main.set_current_page(0)
self.widgets.notebook_main.set_show_tabs(not (state))
self.edit_mode(state)
if state:
self.widgets.search_box.show()
else:
self.widgets.search_box.hide()
def edit_mode(self,data):
print("edit mode pressed",data)
self.gscreen.sensitize_widgets(self.data.sensitive_edit_mode,not data)
if data:
self.widgets.mode6.show()
self.widgets.dro_frame.hide()
self.widgets.gcode_view.set_sensitive(1)
self.data.edit_mode = True
self.widgets.show_box.hide()
self.widgets.notebook_mode.show()
self.widgets.display_btns.hide()
else:
self.widgets.mode6.hide()
self.widgets.dro_frame.show()
self.widgets.gcode_view.set_sensitive(0)
self.data.edit_mode = False
self.widgets.show_box.show()
self.widgets.display_btns.show()
def on_button_full_view_clicked(self,widget):
self.set_full_graphics_view(widget.get_active())
def on_manual_spindle(self,widget):
if self.data.mode_order[0] == self.data._AUTO:
return
if self.widgets.button_man_spindle.get_active():
self.widgets.button_man_spindle.set_label("Stop")
self.emc.spindle_forward(1,self.data.spindle_start_rpm)
else:
print("Spindle stop")
self.widgets.button_man_spindle.set_label("Start")
self.emc.spindle_off(1)
def on_spindle_plus(self,widget):
if self.data.mode_order[0] != self.data._AUTO:
self.emc.spindle_faster(1)
def on_spindle_minus(self,widget):
if self.data.mode_order[0] != self.data._AUTO:
self.emc.spindle_slower(1)
def on_view_change(self,widget):
mode = self.data.mode_order[0]
if mode == self.data._AUTO:
self.data.view = self.data.view+1
if self.data.view > 3:
self.data.view = 0
view = self.data.view
else:
view = 0
print("view", view)
if view == 0:
# Gremlin + Gcode + DRO
self.data.full_graphics = False
self.widgets.show_box.show()
if mode == self.data._AUTO:
self.widgets.notebook_mode.show()
self.widgets.dro_frame.show()
self.widgets.display_btns.show()
self.widgets.gremlin.set_property('enable_dro',False)
elif view == 1:
# Gremlin style DRO
self.data.full_graphics = True
self.widgets.show_box.show()
self.widgets.notebook_mode.hide()
self.widgets.dro_frame.hide()
self.widgets.gremlin.set_property('enable_dro',True)
elif view == 2:
# Gremlin + DRO
self.data.full_graphics = True
self.widgets.dro_frame.show()
self.widgets.notebook_mode.hide()
self.widgets.show_box.show()
self.widgets.gremlin.set_property('enable_dro',False)
elif view == 3:
# DRO + Gcode
self.data.full_graphics = False
self.widgets.dro_frame.show()
if mode == self.data._AUTO:
self.widgets.notebook_mode.show()
self.widgets.gcode_view.set_sensitive(0)
self.widgets.show_box.hide()
self.widgets.display_btns.hide()
self.widgets.gremlin.set_property('enable_dro',False)
def update_override_label(self):
self.widgets.fo.set_text("FO: %3d%%"%(round(self.data.feed_override,2)*100))
self.widgets.mv.set_text("RO: %3d%%"%(round(self.data.rapid_override,2)*100))
self.widgets.so.set_text("SO: %3d%%"%(round(self.data.spindle_override,2)*100))
# Gremlin display buttons
def on_d_zoomp_pressed(self,widget):
self.widgets.gremlin.zoom_in()
def on_d_zoomm_pressed(self,widget):
self.widgets.gremlin.zoom_out()
def on_d_up_pressed(self,widget):
self.data.graphic_ypos = self.data.graphic_ypos-8
self.widgets.gremlin.pan(self.data.graphic_xpos,self.data.graphic_ypos)
def on_d_down_pressed(self,widget):
self.data.graphic_ypos = self.data.graphic_ypos+8
self.widgets.gremlin.pan(self.data.graphic_xpos,self.data.graphic_ypos)
def on_d_right_pressed(self,widget):
self.data.graphic_xpos = self.data.graphic_xpos+8
self.widgets.gremlin.pan(self.data.graphic_xpos,self.data.graphic_ypos)
def on_d_left_pressed(self,widget):
self.data.graphic_xpos = self.data.graphic_xpos-8
self.widgets.gremlin.pan(self.data.graphic_xpos,self.data.graphic_ypos)
# Connect to gscreens regular signals and add a couple more
def connect_signals(self,handlers):
self.gscreen.connect_signals(handlers)
# connect to handler file callbacks:
self.gscreen.widgets.d_zoomp.connect("clicked", self.on_d_zoomp_pressed)
self.gscreen.widgets.d_zoomm.connect("clicked", self.on_d_zoomm_pressed)
self.gscreen.widgets.d_up.connect("clicked", self.on_d_up_pressed)
self.gscreen.widgets.d_down.connect("clicked", self.on_d_down_pressed)
self.gscreen.widgets.d_left.connect("clicked", self.on_d_left_pressed)
self.gscreen.widgets.d_right.connect("clicked", self.on_d_right_pressed)
self.gscreen.widgets.button_man_spindle.connect("clicked", self.on_manual_spindle)
self.gscreen.widgets.button_spindle_plus.connect("clicked", self.on_spindle_plus)
self.gscreen.widgets.button_spindle_minus.connect("clicked", self.on_spindle_minus)
self.gscreen.widgets.button_view.connect("clicked", self.on_view_change)
self.gscreen.widgets.button_mode.connect("button_press_event", self.on_mode_clicked)
self.gscreen.widgets.button_edit.connect("clicked", self.on_button_edit_clicked)
self.gscreen.widgets.button_flood.connect("clicked", self.on_button_flood)
self.gscreen.widgets.ignore_toolchange.connect("clicked", self.on_ign_toolc_pressed)
self.gscreen.widgets.jog_r1.connect("pressed", self.on_jog_rate)
self.gscreen.widgets.jog_r2.connect("pressed", self.on_jog_rate)
self.gscreen.widgets.jog_r3.connect("pressed", self.on_jog_rate)
self.gscreen.widgets.jog_r4.connect("pressed", self.on_jog_rate)
self.gscreen.widgets.jog_plus.connect("clicked", self.jog_point1)
self.gscreen.widgets.jog_minus.connect("clicked", self.jog_point1)
self.gscreen.widgets.button_homing.connect("clicked", self.homing)
self.widgets.hal_status.connect("all-homed",self.on_hal_status_all_homed)
self.widgets.hal_status.connect("state-off",self.on_emc_off)
self.gscreen.widgets.button_clear.connect("clicked", self.on_btn_clear)
self.widgets.hal_status.connect("interp-idle",self.on_interp_idle)
self.widgets.hal_status.connect("interp-run",self.on_interp_run)
# standard handler call
def get_handlers(halcomp,builder,useropts,gscreen):
return [HandlerClass(halcomp,builder,useropts,gscreen)]

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.16"/>
<object class="GtkTextBuffer" id="textbuffer1">
<property name="text" translatable="yes"> Tester Screen
Build a glade file and save it in:
configs/sim/gscreen/gscreen_custom
The glade file must be called tester.glade
The toplevel window must be called window1
Then it can be launched from the linuxcnc launcher menu:
sim/gscreen/gscreen_custom/tester
tester uses a handler file found in:
share/gscreen/skins/tester/tester_handler.py
tester_handler.py is a template of a
handler file for adding python code for
more sophisticated customizations.
If you wish to modify it for your screen it could be copied to:
configs/sim/gscreen/gscreen_custom
See the linuxcnc documentations on Gscreen for more information.
</property>
</object>
<object class="GtkWindow" id="window1">
<property name="can-focus">False</property>
<child>
<object class="GtkTextView" id="textview1">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="buffer">textbuffer1</property>
</object>
</child>
</object>
</interface>

View File

@@ -0,0 +1,57 @@
import hal
# This is a handler file for using Gscreen's infrastructure
# to load a completely custom glade screen.
# The only things that really matters is that it's saved as a GTK builder project,
# the toplevel window is caller window1 (The default name) and you connect a destroy
# window signal else you can't close down linuxcnc
# standard handler call
def get_handlers(halcomp,builder,useropts,gscreen):
return [HandlerClass(halcomp,builder,useropts,gscreen)]
class HandlerClass:
# This will be pretty standard to gain access to everything
# emc is for control and status of linuxcnc
# data is important data from gscreen and linuxcnc
# widgets is all the widgets from the glade files
# gscreen is for access to gscreens methods
def __init__(self, halcomp,builder,useropts,gscreen):
self.emc = gscreen.emc
self.data = gscreen.data
self.widgets = gscreen.widgets
self.gscreen = gscreen
# This connects siganals without using glade's autoconnect method
# in this case to destroy the window
# it calls the method in gscreen: gscreen.on_window_destroy()
def connect_signals(self,handlers):
signal_list = [ ["window1","destroy", "on_window1_destroy"],]
for i in signal_list:
if len(i) == 3:
self.gscreen.widgets[i[0]].connect(i[1], self.gscreen[i[2]])
elif len(i) == 4:
self.gscreen.widgets[i[0]].connect(i[1], self.gscreen[i[2]],i[3])
# We don't want Gscreen to initialize it's regular widgets because this custom
# screen doesn't have most of them. So we add this function call.
# Since this custom screen uses gladeVCP magic for its interaction with linuxcnc
# We don't add much to this function, but we do want the window to display.
# init_show_window will do this
def initialize_widgets(self):
self.gscreen.init_show_windows()
# If we need extra HAL pins here is where we do it.
# Note you must import hal at the top of this script to do it.
# For gaxis there is no extra pins but since we don't want gscreen to
# add it's default pins we added this dunmmy function
def initialize_pins(self):
pass
# every 100 milli seconds this gets called
# add pass so gscreen doesn't try to update it's regular widgets or
# add the individual function names that you would like to call.
def periodic(self):
pass