240 lines
12 KiB
Python
240 lines
12 KiB
Python
# 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)]
|