#!/usr/bin/python
# -*- coding:UTF-8 -*-
"""
    A try of a new GUI for LinuxCNC based on gladevcp and Python
    Based on the design of moccagui from Tom
    and with a lot of code from gscreen from Chris Morley
    and with the help from Michael Haberler
    and Chris Morley and some more

    Copyright 2012 Norbert Schechner
    nieson@web.de

    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

"""

import traceback          # needed to launch traceback errors
import hal                # base hal class to react to hal signals
import hal_glib           # needed to make our own hal pins
import gtk                # base for pygtk widgets and constants
import sys                # handle system calls
import os                 # needed to get the paths and directories
import pango              # needed for font settings and changing
import gladevcp.makepins  # needed for the dialog"s calculator widget
import atexit             # needed to register child's to be closed on closing the GUI
import subprocess         # to launch onboard and other processes
import vte                # To get the embedded terminal
import tempfile           # needed only if the user click new in edit mode to open a new empty file
import linuxcnc           # to get our own error system
import gobject            # needed to add the timer for periodic
import locale             # for setting the language of the GUI
import gettext            # to extract the strings to be translated

from gladevcp.gladebuilder import GladeBuilder

from time import strftime   # needed for the clock in the GUI

# Throws up a dialog with debug info when an error is encountered
def excepthook( exc_type, exc_obj, exc_tb ):
    try:
        w = app.widgets.window1
    except KeyboardInterrupt:
        sys.exit( 0 )
    except NameError:
        w = None
    lines = traceback.format_exception( exc_type, exc_obj, exc_tb )
    m = gtk.MessageDialog( w,
                          gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                          gtk.MESSAGE_ERROR, gtk.BUTTONS_OK,
                          ( "Found an error!\nThe following information may be useful for troubleshooting:\n\n" )
                          + "".join( lines ) )
    m.show()
    m.run()
    m.destroy()


sys.excepthook = excepthook

debug = False

if debug:
    pydevdir = '/home/emcmesa/Aptana_Studio_3/plugins/org.python.pydev_2.7.0.2013032300/pysrc'

    if os.path.isdir( pydevdir ):  # and  'emctask' in sys.builtin_module_names:
        sys.path.append( pydevdir )
        sys.path.insert( 0, pydevdir )
        try:
            import pydevd

            print( "pydevd imported, connecting to Eclipse debug server..." )
            pydevd.settrace()
        except:
            print( "no pydevd module found" )
            pass

# constants
#         # gmoccapy  #"
_RELEASE = " 1.5.6.3"
_INCH = 0                         # imperial units are active
_MM = 1                           # metric units are active
_TEMPDIR = tempfile.gettempdir()  # Now we know where the tempdir is, usualy /tmp

# set up paths to files
BASE = os.path.abspath( os.path.join( os.path.dirname( sys.argv[0] ), ".." ) )
LIBDIR = os.path.join( BASE, "lib", "python" )
sys.path.insert( 0, LIBDIR )

# as now we know the libdir path we can import our own modules
from gmoccapy import widgets       # a class to handle the widgets
from gmoccapy import player        # a class to handle sounds
from gmoccapy import notification  # this is the module we use for our error handling
from gmoccapy import preferences   # this handles the preferences
from gmoccapy import getiniinfo    # this handles the INI File reading so checking is done in that module
from gmoccapy import dialogs       # this takes the code of all our dialogs

# set up paths to files, part two
CONFIGPATH = os.environ['CONFIG_DIR']
DATADIR = os.path.join( BASE, "share", "gmoccapy" )
IMAGEDIR = os.path.join( DATADIR, "images" )
XMLNAME = os.path.join( DATADIR, "gmoccapy.glade" )
THEMEDIR = "/usr/share/themes"
USERTHEMEDIR = os.path.join(os.path.expanduser("~"), ".themes")
LOCALEDIR = os.path.join( BASE, "share", "locale" )

# path to TCL for external programs eg. halshow
TCLPATH = os.environ['LINUXCNC_TCL_DIR']

# the ICONS should must be in share/gmoccapy/images
ALERT_ICON = os.path.join( IMAGEDIR, "applet-critical.png" )
INFO_ICON = os.path.join( IMAGEDIR, "std_info.gif" )

# this is for hiding the pointer when using a touch screen
pixmap = gtk.gdk.Pixmap( None, 1, 1, 1 )
color = gtk.gdk.Color()
INVISABLE = gtk.gdk.Cursor( pixmap, pixmap, color, color, 0, 0 )


class gmoccapy( object ):
    def __init__( self ):

        # prepare for translation / internationalisation
        locale.setlocale( locale.LC_ALL, '' )
        locale.bindtextdomain( "gmoccapy", LOCALEDIR )
        gettext.install( "gmoccapy", localedir = LOCALEDIR, unicode = True )
        gettext.bindtextdomain( "gmoccapy", LOCALEDIR )

        # needed components to comunicate with hal and linuxcnc
        self.halcomp = hal.component( "gmoccapy" )
        self.command = linuxcnc.command()
        self.stat = linuxcnc.stat()

        self.command.teleop_enable(1)
        self.command.wait_complete()
        self.stat.poll()
        if self.stat.kinematics_type != linuxcnc.KINEMATICS_IDENTITY:
            raise SystemExit, "\n*** gmoccapy: Only KINEMATICS_IDENTITY is supported\n"

        self.error_channel = linuxcnc.error_channel()
        # initial poll, so all is up to date
        self.stat.poll()
        self.error_channel.poll()

        self.builder = gtk.Builder()
        # translation of the glade file will be done with
        self.builder.set_translation_domain( "gmoccapy" )
        self.builder.add_from_file( XMLNAME )
        self.builder.connect_signals( self )

        self.widgets = widgets.Widgets( self.builder )

        self.initialized = False  # will be set True after the window has been shown and all
        # basic settings has been finished, so we avoid some actions
        # because we cause click or toggle events when initializing
        # widget states.

        self.start_line = 0      # needed for start from line

        self.active_gcodes = []  # this are the formated G code values
        self.active_mcodes = []  # this are the formated M code values
        self.gcodes = []         # this are the unformated G code values to check if an update is requiered
        self.mcodes = []         # this are the unformated M code values to check if an update is requiered

        self.distance = 0        # This global will hold the jog distance
        self.tool_change = False # this is needed to get back to manual mode after a tool change
        self.macrobuttons = []   # The list of all macrios defined in the INI file
        self.fo_counts = 0       # need to calculate diference in counts to change the feed override slider
        self.so_counts = 0       # need to calculate diference in counts to change the spindle override slider
        self.jv_counts = 0       # need to calculate diference in counts to change the jog_vel slider
        self.mv_counts = 0       # need to calculate diference in counts to change the max_speed slider

        self.spindle_override = 1  # holds the feed override value and is needed to be able to react to halui pin
        self.feed_override = 1     # holds the spindle override value and is needed to be able to react to halui pin
#        self.rapidrate = 1         # holds the rapid override value and is needed to be able to react to halui pin

        self.incr_rbt_list = []    # we use this list to add hal pin to the button later
        self.jog_increments = []   # This holds the increment values
        self.unlock = False        # this value will be set using the hal pin unlock settings

        # needed to display the labels
        self.system_list = ( "0", "G54", "G55", "G56", "G57", "G58", "G59", "G59.1", "G59.2", "G59.3" )
        self.dro_size = 28           # The size of the DRO, user may want them bigger on bigger screen
        self.axisnumber_four = ""    # we use this to get the number of the 4-th axis
        self.axisletter_four = None  # we use this to get the letter of the 4-th axis
        self.hide_axis_4 = False     # will hold if the 4'th axis should be hidden

        self.notification = notification.Notification()  # Our own message system
        self.notification.connect( "message_deleted", self._on_message_deleted )
        self.last_key_event = None, 0  # needed to avoid the auto repeat function of the keyboard
        self.all_homed = False         # will hold True if all axis are homed
        self.faktor = 1.0              # needed to calculate velocitys

        self.xpos = 40     # The X Position of the main Window
        self.ypos = 30     # The Y Position of the main Window
        self.width = 979   # The width of the main Window
        self.height = 750  # The heigh of the main Window

        self.gcodeerror = ""  # we need this to avoid multile messages of the same error

        # the default theme = System Theme we store here to be able to go back to that one later
        self.default_theme = gtk.settings_get_default().get_property( "gtk-theme-name" )

        # the sounds to play if an error or message rises
        self.alert_sound = "/usr/share/sounds/ubuntu/stereo/bell.ogg"
        self.error_sound = "/usr/share/sounds/ubuntu/stereo/dialog-question.ogg"

        # Our own clas to get information from ini the file we use this way, to be sure
        # to get a valid result, as the checks are done in that module
        self.get_ini_info = getiniinfo.GetIniInfo()

        self.prefs = preferences.preferences( self.get_ini_info.get_preference_file_path() )

        self._get_axis_list()
        self._init_axis_four()
        self._init_jog_increments()

        self._init_hal_pins()

        self._init_user_messages()

        # set the title of the window, to show the release
        self.widgets.window1.set_title( "gmoccapy for linuxcnc %s" % _RELEASE )
        self.widgets.lbl_version.set_label( "<b>gmoccapy\n%s</b>" % _RELEASE )

        panel = gladevcp.makepins.GladePanel( self.halcomp, XMLNAME, self.builder, None )

        self.halcomp.ready()

        # this are settings to be done before window show
        self._init_preferences()

        # finally show the window
        self.widgets.window1.show()

        self._init_dynamic_tabs()
        self._init_tooleditor()
        self._init_themes()
        self._init_audio()
        self._init_gremlin()
        self._init_hide_cursor()
        self._init_keyboard()
        self._init_offsetpage()
        self._init_keybindings()
        self._init_IconFileSelection()

        # now we initialize the file to load widget
        self._init_file_to_load()

        self._show_offset_tab( False )
        self._show_tooledit_tab( False )
        self._show_iconview_tab( False )

        # check if the user want a Logo
        if self.prefs.getpref( "logo", False, bool ):
            logofile = self.prefs.getpref( "logofile", None, str )
            if logofile:
                self.widgets.img_logo.set_from_file( logofile )
                self.widgets.img_logo.show()
                self.widgets.hbox_jog.hide()
                self.widgets.hbox_jog_vel.hide()

        # the velocity settings
        self.min_spindle_rev = self.prefs.getpref( "spindle_bar_min", 0.0, float )
        self.max_spindle_rev = self.prefs.getpref( "spindle_bar_max", 6000.0, float )
        self.widgets.adj_spindle_bar_min.set_value( self.min_spindle_rev )
        self.widgets.adj_spindle_bar_max.set_value( self.max_spindle_rev )
        self.widgets.spindle_feedback_bar.set_property( "min", float( self.min_spindle_rev ) )
        self.widgets.spindle_feedback_bar.set_property( "max", float( self.max_spindle_rev ) )

        # Popup Messages position and size
        self.widgets.adj_x_pos_popup.set_value( self.prefs.getpref( "x_pos_popup", 45, float ) )
        self.widgets.adj_y_pos_popup.set_value( self.prefs.getpref( "y_pos_popup", 55, float ) )
        self.widgets.adj_width_popup.set_value( self.prefs.getpref( "width_popup", 250, float ) )
        self.widgets.adj_max_messages.set_value( self.prefs.getpref( "max_messages", 10, float ) )
        self.widgets.fontbutton_popup.set_font_name( self.prefs.getpref( "message_font", "sans 10", str ) )
        self.widgets.chk_use_frames.set_active( self.prefs.getpref( "use_frames", True, bool ) )

        # Only used if the DRO buttons will remain in gmoccapy
        self.widgets.chk_show_dro_btn.set_active( self.prefs.getpref( "show_dro_btn", False, bool ) )
        self.widgets.chk_auto_units.set_active( self.prefs.getpref( "use_auto_units", True, bool ) )
        self.on_chk_show_dro_btn_toggled( None )
        self.on_chk_auto_units_toggled( None )
        if self.widgets.Combi_DRO_x.machine_units == 0:
            self.widgets.tbtn_units.set_active( True )

        self.widgets.tbtn_rel.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.tbtn_dtg.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.tbtn_units.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        # end of the button usage

        # this sets the background colors of several buttons
        # the colors are different for the states of the button
        self.widgets.tbtn_on.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.tbtn_estop.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FF0000" ) )
        self.widgets.tbtn_estop.modify_bg( gtk.STATE_NORMAL, gtk.gdk.color_parse( "#00FF00" ) )
        self.widgets.rbt_manual.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.rbt_mdi.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.rbt_auto.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.tbtn_setup.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.rbt_forward.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#00FF00" ) )
        self.widgets.rbt_reverse.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#00FF00" ) )
        self.widgets.rbt_stop.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.rbt_view_p.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.rbt_view_x.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.rbt_view_y.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.rbt_view_y2.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.rbt_view_z.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.tbtn_flood.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#00FF00" ) )
        self.widgets.tbtn_fullsize_preview.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.tbtn_fullsize_preview1.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.tbtn_mist.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#00FF00" ) )
        self.widgets.tbtn_optional_blocks.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.tbtn_optional_stops.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.tbtn_user_tabs.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.tbtn_view_dimension.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.tbtn_view_tool_path.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        self.widgets.tbtn_edit_offsets.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )

        # This is needed only because we connect all the horizontal button
        # to hal pins, so the user can conect them to hardware buttons
        self.h_tabs = []
        tab_main = [( 0, "btn_homing" ), ( 1, "btn_touch" ), ( 3, "btn_tool" ),
                    ( 8, "tbtn_fullsize_preview" ), ( 9, "btn_exit" )
        ]
        self.h_tabs.append( tab_main )

        tab_mdi = [( 9, "btn_show_kbd" )]
        self.h_tabs.append( tab_mdi )

        tab_auto = [( 0, "btn_load" ), ( 1, "btn_run" ), ( 2, "btn_stop" ), ( 3, "tbtn_pause" ),
                    ( 4, "btn_step" ), ( 5, "btn_from_line" ), ( 6, "tbtn_optional_blocks" ),
                    ( 7, "tbtn_optional_stops" ), ( 8, "tbtn_fullsize_preview1" ), ( 9, "btn_edit" )
        ]
        self.h_tabs.append( tab_auto )

        tab_ref = [( 1, "btn_home_all" ), ( 3, "btn_home_x" ),
                   ( 5, "btn_home_z" ), ( 7, "btn_unhome_all" ), ( 9, "btn_back_ref" )
        ]
        if not self.lathe_mode:
            tab_ref.append( ( 4, "btn_home_y" ) )
        if len( self.axis_list ) == 4:
            tab_ref.append( ( 6, "btn_home_4" ) )
        self.h_tabs.append( tab_ref )

        tab_touch = [( 0, "tbtn_edit_offsets" ), ( 1, "btn_zero_x" ), ( 3, "btn_zero_z" ), ( 4, "btn_zero_g92" ),
                     ( 5, "btn_set_value_x" ), ( 7, "btn_set_value_z" ), ( 8, "btn_set_selected" ),
                     ( 9, "btn_back_zero" )
        ]
        if not self.lathe_mode:
            tab_touch.append( ( 2, "btn_zero_y" ) )
            tab_touch.append( ( 6, "btn_set_value_y" ) )
        self.h_tabs.append( tab_touch )

        tab_setup = [( 0, "btn_delete" ), ( 4, "btn_classicladder" ), ( 5, "btn_hal_scope" ), ( 6, "btn_status" ),
                     ( 7, "btn_hal_meter" ), ( 8, "btn_calibration" ), ( 9, "btn_show_hal" )
        ]
        self.h_tabs.append( tab_setup )

        tab_edit = [( 0, "btn_open_edit" ), ( 2, "btn_save" ), ( 3, "btn_save_as" ), ( 4, "btn_save_and_run" ),
                    ( 6, "btn_new" ), ( 8, "btn_keyb" ), ( 9, "btn_back_edit" )
        ]
        self.h_tabs.append( tab_edit )

        tab_tool = [( 0, "btn_delete_tool" ), ( 1, "btn_add_tool" ), ( 2, "btn_reload_tooltable" ),
                    ( 3, "btn_apply_tool_changes" ), ( 4, "btn_select_tool_by_no" ), ( 5, "btn_index_tool" ),
                    ( 6, "btn_change_tool" ), ( 8, "btn_tool_touchoff_z" ), ( 9, "btn_back_tool" )
        ]
        if self.lathe_mode:
            tab_tool.append( ( 7, "btn_tool_touchoff_x" ) )
        self.h_tabs.append( tab_tool )

        tab_file = [( 0, "btn_home" ), ( 1, "btn_dir_up" ), ( 3, "btn_sel_prev" ), ( 4, "btn_sel_next" ),
                    ( 5, "btn_jump_to" ), ( 7, "btn_select" ), ( 9, "btn_back_file_load" )
        ]
        self.h_tabs.append( tab_file )

        self.v_tabs = [( 0, "tbtn_estop" ), ( 1, "tbtn_on" ), ( 2, "rbt_manual" ), ( 3, "rbt_mdi" ),
                       ( 4, "rbt_auto" ), ( 5, "tbtn_setup" ), ( 6, "tbtn_user_tabs" )
        ]

        # tool measurement probe settings
        xpos, ypos, zpos, maxprobe = self.get_ini_info.get_tool_sensor_data()
        if not xpos or not ypos or not zpos or not maxprobe:
            self.widgets.chk_use_tool_measurement.set_active( False )
            self.widgets.chk_use_tool_measurement.set_sensitive( False )
            self.widgets.btn_block_height.set_sensitive( False )
            self.widgets.lbl_tool_measurement.show()
            self.widgets.btn_zero_g92.show()
            self.widgets.btn_block_height.hide()
            print( _( "**** GMOCCAPY INFO ****" ) )
            print( _( "**** no valid probe config in INI File ****" ) )
            print( _( "**** disabled tool measurement ****" ) )
        else:
            self.widgets.lbl_tool_measurement.hide()
            self.widgets.spbtn_probe_height.set_value( self.prefs.getpref( "probeheight", -1.0, float ) )
            self.widgets.spbtn_search_vel.set_value( self.prefs.getpref( "searchvel", 75.0, float ) )
            self.widgets.spbtn_probe_vel.set_value( self.prefs.getpref( "probevel", 10.0, float ) )
            self.widgets.chk_use_tool_measurement.set_active( self.prefs.getpref( "use_toolmeasurement", False, bool ) )
            # to set the hal pin with correct values we emit a toogled
            self.widgets.chk_use_tool_measurement.emit( "toggled" )
            self.widgets.lbl_x_probe.set_label( str( xpos ) )
            self.widgets.lbl_y_probe.set_label( str( ypos ) )
            self.widgets.lbl_z_probe.set_label( str( zpos ) )
            self.widgets.lbl_maxprobe.set_label( str( maxprobe ) )
            self.widgets.btn_block_height.set_sensitive( True )
            self.widgets.btn_zero_g92.hide()
            self.widgets.btn_block_height.show()
            self._replace_list_item( 4, "btn_zero_g92", "btn_block_height" )

        # and the rest of the widgets
        self.widgets.rbt_manual.set_active( True )
        self.widgets.ntb_jog.set_current_page( 0 )
        self.widgets.tbtn_optional_blocks.set_active( self.prefs.getpref( "blockdel", False ) )
        self.command.set_block_delete( self.widgets.tbtn_optional_blocks.get_active() )
        self.widgets.tbtn_optional_stops.set_active( not self.prefs.getpref( "opstop", False ) )
        self.command.set_optional_stop( self.widgets.tbtn_optional_stops.get_active() )
        self.widgets.chk_show_dro.set_active( self.prefs.getpref( "enable_dro", False ) )
        self.widgets.chk_show_offsets.set_active( self.prefs.getpref( "show_offsets", False ) )
        self.widgets.chk_show_dtg.set_active( self.prefs.getpref( "show_dtg", False ) )
        self.widgets.chk_show_offsets.set_sensitive( self.widgets.chk_show_dro.get_active() )
        self.widgets.chk_show_dtg.set_sensitive( self.widgets.chk_show_dro.get_active() )
        self.widgets.cmb_mouse_button_mode.set_active( self.prefs.getpref( "mouse_btn_mode", 4, int ) )

        self.widgets.tbtn_view_tool_path.set_active( self.prefs.getpref( "view_tool_path", True ) )
        self.widgets.tbtn_view_dimension.set_active( self.prefs.getpref( "view_dimension", True ) )
        view = self.prefs.getpref( "gremlin_view", "rbt_view_p", str )
        self.widgets[view].set_active( True )

        # if the INI Config is valid, lets check further on, what to do
        if self.get_ini_info.get_embedded_tabs()[1]:
            if "ntb_preview" in self.get_ini_info.get_embedded_tabs()[1]:
                self.widgets.ntb_preview.set_property( "show-tabs", True )

            # This is normaly only used for the plasma screen layout
            if "box_coolant_and_spindle" in self.get_ini_info.get_embedded_tabs()[1]:
                widgetlist = ["box_spindle", "box_cooling"]
                for widget in widgetlist:
                    self.widgets[widget].hide()
                self.widgets.tbtn_user_tabs.set_sensitive( False )

            if "box_cooling" in self.get_ini_info.get_embedded_tabs()[1]:
                widgetlist = ["frm_cooling"]
                for widget in widgetlist:
                    self.widgets[widget].hide()

            if "box_spindle" in self.get_ini_info.get_embedded_tabs()[1]:
                widgetlist = ["frm_spindle"]
                for widget in widgetlist:
                    self.widgets[widget].hide()

            if "box_vel_info" in self.get_ini_info.get_embedded_tabs()[1]:
                widgetlist = ["frm_max_vel", "frm_feed_override"]
                for widget in widgetlist:
                    self.widgets[widget].hide()

            if "box_custom_1" in self.get_ini_info.get_embedded_tabs()[1]:
                self.widgets.box_custom_1.show()

            if "box_custom_2" in self.get_ini_info.get_embedded_tabs()[1]:
                self.widgets.box_custom_2.show()

            if "box_custom_3" in self.get_ini_info.get_embedded_tabs()[1]:
                self.widgets.box_custom_3.show()

            if "box_custom_4" in self.get_ini_info.get_embedded_tabs()[1]:
                self.widgets.box_custom_4.show()

            if "box_tool_and_code_info" in self.get_ini_info.get_embedded_tabs()[1]:
                widgetlist = ["frm_tool_info", "active_speed_label", "lbl_speed", "box_vel_info"]
                for widget in widgetlist:
                    self.widgets[widget].hide()
                self.widgets.btn_tool.set_sensitive( False )
                self.widgets.tbtn_user_tabs.set_sensitive( False )

        # get if run from line should be used
        rfl = self.prefs.getpref( "run_from_line", "no_run", str )
        # and set the corresponding button active
        self.widgets["rbtn_%s_from_line" % rfl].set_active( True )
        if rfl == "no_run":
            self.widgets.btn_from_line.set_sensitive( False )
        else:
            self.widgets.btn_from_line.set_sensitive( True )

        # get the way to unlock the setting
        unlock = self.prefs.getpref( "unlock_way", "use", str )
        # and set the corresponding button active
        self.widgets["rbt_%s_unlock" % unlock].set_active( True )
        # if Hal pin should be used, only set the button active, if the pin is high
        if unlock == "hal" and not self.halcomp["unlock-settings"]:
            self.widgets.tbtn_setup.set_sensitive( False )
        self.unlock_code = self.prefs.getpref( "unlock_code", "123", str )  # get unlock code

        # get when the keyboard should be shown
        # and set the corresponding button active
        # only if onbaoard keýboard is ok.
        if self.onboard:
            self.widgets.chk_use_kb_on_offset.set_active( self.prefs.getpref( "show_keyboard_on_offset",
                                                                            True, bool ) )
            self.widgets.chk_use_kb_on_tooledit.set_active( self.prefs.getpref( "show_keyboard_on_tooledit",
                                                                              False, bool ) )
            self.widgets.chk_use_kb_on_edit.set_active( self.prefs.getpref( "show_keyboard_on_edit",
                                                                          True, bool ) )
            self.widgets.chk_use_kb_on_mdi.set_active( self.prefs.getpref( "show_keyboard_on_mdi",
                                                                         True, bool ) )
            self.widgets.chk_use_kb_on_file_selection.set_active( self.prefs.getpref( "show_keyboard_on_file_selection",
                                                                                    False, bool ) )

        # check if the user want to display preview window insteadt of offsetpage widget
        state = self.prefs.getpref( "show_preview_on_offset", False, bool )
        if state:
            self.widgets.rbtn_show_preview.set_active( True )
        else:
            self.widgets.rbtn_show_offsets.set_active( True )

        # check if keyboard shortcuts should be used and set the chkbox widget
        self.widgets.chk_use_kb_shortcuts.set_active( self.prefs.getpref( "use_keyboard_shortcuts",
                                                                        False, bool ) )

        # check the highlighting type
        # the following would load the python language
        # self.widgets.gcode_view.set_language("python")
        LANGDIR = os.path.join( BASE, "share", "gtksourceview-2.0", "language-specs" )
        file_path = os.path.join( LANGDIR, "gcode.lang" )
        if os.path.isfile( file_path ):
            print "**** GMOCCAPY INFO: Gcode.lang found ****"
            self.widgets.gcode_view.set_language( "gcode", LANGDIR )

        # set the user colors and digits of the DRO
        self.abs_color = self.prefs.getpref( "abs_color", "blue", str )
        self.rel_color = self.prefs.getpref( "rel_color", "black", str )
        self.dtg_color = self.prefs.getpref( "dtg_color", "yellow", str )
        self.homed_color = self.prefs.getpref( "homed_color", "green", str )
        self.unhomed_color = self.prefs.getpref( "unhomed_color", "red", str )
        self.widgets.abs_colorbutton.set_color( gtk.gdk.color_parse( self.abs_color ) )
        self.widgets.rel_colorbutton.set_color( gtk.gdk.color_parse( self.rel_color ) )
        self.widgets.dtg_colorbutton.set_color( gtk.gdk.color_parse( self.dtg_color ) )
        self.widgets.homed_colorbtn.set_color( gtk.gdk.color_parse( self.homed_color ) )
        self.widgets.unhomed_colorbtn.set_color( gtk.gdk.color_parse( self.unhomed_color ) )

        # set default values according to the machine units
        digits = 3
        if self.stat.linear_units != _MM:
            digits = 4
        self.dro_digits = self.prefs.getpref( "dro_digits", digits, int )
        self.widgets.adj_dro_digits.set_value( self.dro_digits )
        # the adjustment change signal will set the dro_digits correct, so no extra need here.

        for axis in self.axis_list:
            if axis == self.axisletter_four:
                axis = 4
            self.widgets["Combi_DRO_%s" % axis].set_property( "abs_color", gtk.gdk.color_parse( self.abs_color ) )
            self.widgets["Combi_DRO_%s" % axis].set_property( "rel_color", gtk.gdk.color_parse( self.rel_color ) )
            self.widgets["Combi_DRO_%s" % axis].set_property( "dtg_color", gtk.gdk.color_parse( self.dtg_color ) )
            self.widgets["Combi_DRO_%s" % axis].set_property( "homed_color", gtk.gdk.color_parse( self.homed_color ) )
            self.widgets["Combi_DRO_%s" % axis].set_property( "unhomed_color", gtk.gdk.color_parse( self.unhomed_color ) )
            self.widgets["Combi_DRO_%s" % axis].set_property( "actual", self.dro_actual)

        self.toggle_readout = self.prefs.getpref( "toggle_readout", True, bool )
        self.widgets.chk_toggle_readout.set_active(self.toggle_readout)

        self.widgets.adj_start_spindle_RPM.set_value( self.spindle_start_rpm )
        self.widgets.gcode_view.set_sensitive( False )
        self.tooledit_btn_delete_tool = self.widgets.tooledit1.wTree.get_object( "delete" )
        self.tooledit_btn_add_tool = self.widgets.tooledit1.wTree.get_object( "add" )
        self.tooledit_btn_reload_tool = self.widgets.tooledit1.wTree.get_object( "reload" )
        self.tooledit_btn_apply_tool = self.widgets.tooledit1.wTree.get_object( "apply" )
        self.widgets.tooledit1.hide_buttonbox( True )
        self.widgets.ntb_user_tabs.remove_page( 0 )
        self._add_macro_button()

        if not self.get_ini_info.get_embedded_tabs()[2]:
            self.widgets.tbtn_user_tabs.set_sensitive( False )

        # call the function to change the button status
        # so every thing is ready to start
        widgetlist = ["rbt_manual", "rbt_mdi", "rbt_auto", "btn_homing", "btn_touch", "btn_tool",
                      "ntb_jog", "scl_feed", "btn_feed_100", "rbt_forward", "btn_index_tool",
                      "rbt_reverse", "rbt_stop", "tbtn_flood", "tbtn_mist", "btn_change_tool",
                      "btn_select_tool_by_no", "btn_spindle_100", "scl_max_vel", "scl_spindle",
                      "btn_tool_touchoff_x", "btn_tool_touchoff_z"
        ]
        self._sensitize_widgets( widgetlist, False )

        # Do we control a lathe?
        if self.lathe_mode:
            # is this a backtool lathe?
            self.backtool_lathe = self.get_ini_info.get_backtool_lathe()

            # we first hide the Y button to home and touch off
            self.widgets.btn_home_y.hide()
            self.widgets.btn_zero_y.hide()
            self.widgets.btn_set_value_y.hide()
            self.widgets.lbl_replace_y.show()
            self.widgets.lbl_replace_zero_y.show()
            self.widgets.lbl_replace_set_value_y.show()
            self.widgets.btn_tool_touchoff_x.show()
            self.widgets.lbl_hide_tto_x.hide()

            # we have to re-arrange the jog buttons, so first remove all button
            self.widgets.tbl_jog_btn.remove( self.widgets.btn_y_minus )
            self.widgets.tbl_jog_btn.remove( self.widgets.btn_y_plus )
            self.widgets.tbl_jog_btn.remove( self.widgets.btn_x_minus )
            self.widgets.tbl_jog_btn.remove( self.widgets.btn_x_plus )
            self.widgets.tbl_jog_btn.remove( self.widgets.btn_z_minus )
            self.widgets.tbl_jog_btn.remove( self.widgets.btn_z_plus )

            # now we place them in a different order
            if self.backtool_lathe:
                self.widgets.tbl_jog_btn.attach( self.widgets.btn_x_plus, 1, 2, 0, 1, gtk.SHRINK, gtk.SHRINK )
                self.widgets.tbl_jog_btn.attach( self.widgets.btn_x_minus, 1, 2, 2, 3, gtk.SHRINK, gtk.SHRINK )
            else:
                self.widgets.tbl_jog_btn.attach( self.widgets.btn_x_plus, 1, 2, 2, 3, gtk.SHRINK, gtk.SHRINK )
                self.widgets.tbl_jog_btn.attach( self.widgets.btn_x_minus, 1, 2, 0, 1, gtk.SHRINK, gtk.SHRINK )
            self.widgets.tbl_jog_btn.attach( self.widgets.btn_z_plus, 2, 3, 1, 2, gtk.SHRINK, gtk.SHRINK )
            self.widgets.tbl_jog_btn.attach( self.widgets.btn_z_minus, 0, 1, 1, 2, gtk.SHRINK, gtk.SHRINK )

            # The Y DRO we make to a second X DRO to indicate the diameter
            self.widgets.Combi_DRO_y.set_to_diameter( True )
            self.widgets.Combi_DRO_y.set_property( "joint_number", 0 )

            # we change the axis letters of the DRO's
            self.widgets.Combi_DRO_x.change_axisletter( "R" )
            self.widgets.Combi_DRO_y.change_axisletter( "D" )

            # and we will have to change the colors of the Y DRO according to the settings
            self.widgets.Combi_DRO_y.set_property( "abs_color", gtk.gdk.color_parse( self.abs_color ) )
            self.widgets.Combi_DRO_y.set_property( "rel_color", gtk.gdk.color_parse( self.rel_color ) )
            self.widgets.Combi_DRO_y.set_property( "dtg_color", gtk.gdk.color_parse( self.dtg_color ) )
            self.widgets.Combi_DRO_y.set_property( "homed_color", gtk.gdk.color_parse( self.homed_color ) )
            self.widgets.Combi_DRO_y.set_property( "unhomed_color", gtk.gdk.color_parse( self.unhomed_color ) )
            self.widgets.Combi_DRO_y.set_property( "actual", self.dro_actual)

            # For gremlin we don"t need the following button
            if self.backtool_lathe:
                self.widgets.rbt_view_y2.set_active( True )
            else:
                self.widgets.rbt_view_y.set_active( True )
            self.widgets.rbt_view_p.hide()
            self.widgets.rbt_view_x.hide()
            self.widgets.rbt_view_z.hide()

            # check if G7 or G8 is active
            if "70" in self.stat.gcodes:
                self._switch_to_g7( True )
            else:
                self._switch_to_g7( False )

        else:
            # the Y2 view is not needed on a mill
            self.widgets.rbt_view_y2.hide()
            # X Offset is not necesary on a mill
            self.widgets.lbl_tool_offset_x.hide()
            self.widgets.lbl_offset_x.hide()
            self.widgets.btn_tool_touchoff_x.hide()
            self.widgets.lbl_hide_tto_x.show()

        # this must be done last, otherwise we will get wrong values
        # because the window is not fully realized
        self.init_notification()

        # since the main loop is needed to handle the UI and its events, blocking calls like sleep()
        # will block the UI as well, so everything goes through event handlers (aka callbacks)
        # The gobject.timeout_add() function sets a function to be called at regular intervals
        # the time between calls to the function, in milliseconds
        gobject.timeout_add( 100, self._periodic )  # time between calls to the function, in milliseconds

    def set_motion_mode(self):
        self.stat.poll()
        if self.stat.motion_mode != linuxcnc.TRAJ_MODE_TELEOP:
            self.command.teleop_enable(1)
            self.command.wait_complete()

    def _get_axis_list( self ):
        temp = self.get_ini_info.get_coordinates()
        self.axis_list = []
        for letter in temp:
            if letter.lower() in self.axis_list:
                continue
            if not letter.lower() in ["x", "y", "z", "a", "b", "c", "u", "v", "w"]:
                continue
            self.axis_list.append( letter.lower() )

    def _init_preferences( self ):
        # check if NO_FORCE_HOMING is used in ini
        self.no_force_homing = self.get_ini_info.get_no_force_homing()
        self.spindle_start_rpm = self.prefs.getpref( 'spindle_start_rpm', 300, float )
        # if it's a lathe config, set the tooleditor style
        self.lathe_mode = self.get_ini_info.get_lathe()
        self.jog_rate = self.get_ini_info.get_jog_vel()
        self.jog_rate_max = self.get_ini_info.get_max_jog_vel()
        self.spindle_override_max = self.get_ini_info.get_max_spindle_override()
        self.spindle_override_min = self.get_ini_info.get_min_spindle_override()
        self.feed_override_max = self.get_ini_info.get_max_feed_override()
        self.dro_actual = self.get_ini_info.get_position_feedback_actual()

        # set the slider limmits
        self.widgets.adj_max_vel.configure( self.stat.max_velocity * 60, 0.0,
                                           self.stat.max_velocity * 60, 1, 0, 0 )
        self.widgets.adj_jog_vel.configure( self.jog_rate, 0,
                                           self.jog_rate_max, 1, 0, 0 )
        self.widgets.adj_spindle.configure( 100, self.spindle_override_min * 100,
                                           self.spindle_override_max * 100, 1, 0, 0 )
        self.widgets.adj_feed.configure( 100, 0, self.feed_override_max * 100, 1, 0, 0 )

        # holds the max velocity value and is needed to be able to react to halui pin
        self.max_velocity = self.maxvel = self.stat.max_velocity

        # set and get all information for turtle jogging
        self.rabbit_jog = self.jog_rate
        hide_turtle_jog_button = self.prefs.getpref( "hide_turtle_jog_button", False, bool )
        self.widgets.chk_turtle_jog.set_active( hide_turtle_jog_button )
        self.turtle_jog_factor = self.prefs.getpref( 'turtle_jog_factor', 20, int )
        self.widgets.adj_turtle_jog_factor.configure( self.turtle_jog_factor, 1,
                                                     100, 1, 0, 0 )
        if hide_turtle_jog_button:
            self.widgets.tbtn_turtle_jog.hide()
            self.turtle_jog_factor = 1
        self.turtle_jog = self.rabbit_jog / self.turtle_jog_factor

        # and according to machine units the digits to display
        if self.stat.linear_units == _MM:
            self.widgets.scl_max_vel.set_digits( 0 )
            self.widgets.scl_jog_vel.set_digits( 0 )
        else:
            self.widgets.scl_max_vel.set_digits( 3 )
            self.widgets.scl_jog_vel.set_digits( 3 )

        # the scale to apply to the count of the hardware mpg wheel, to avoid to much turning
        default = ( self.stat.max_velocity * 60 - self.stat.max_velocity * 0.1 ) / 100
        self.scale_max_vel = self.prefs.getpref( "scale_max_vel", default, float )
        self.widgets.adj_scale_max_vel.set_value( self.scale_max_vel )
        default = ( self.jog_rate_max / 100 )
        self.scale_jog_vel = self.prefs.getpref( "scale_jog_vel", default, float )
        self.widgets.adj_scale_jog_vel.set_value( self.scale_jog_vel )
        self.scale_spindle_override = self.prefs.getpref( "scale_spindle_override", 1, float )
        self.widgets.adj_scale_spindle_override.set_value( self.scale_spindle_override )
        self.scale_feed_override = self.prefs.getpref( "scale_feed_override", 1, float )
        self.widgets.adj_scale_feed_override.set_value( self.scale_feed_override )

    def _init_axis_four( self ):
        self.dro_size = int( self.prefs.getpref( "dro_size", 28, int ) )
        self.widgets.adj_dro_size.set_value( self.dro_size )

        if len( self.axis_list ) < 4:
            self.widgets.Combi_DRO_4.hide()
            self.widgets.chk_hide_axis_4.set_active( False )
            self.widgets.frm_tool_changer.set_sensitive( False )
            self.prefs.putpref( "hide_axis_4", False, bool )

            for axis in self.axis_list:
                self.widgets["Combi_DRO_%s" % axis].set_property( "font_size", self.dro_size )

            return
        axis_four = list( set( self.axis_list ) - set( ( "x", "y", "z" ) ) )
        if len( axis_four ) > 1:
            message = _( "**** GMOCCAPY ERROR : ****" )
            message += _( 
                "**** gmoccapy can only handle 4 axis, ****\n**** but you have given %d through your INI file ****\n" % len( 
                    self.axis_list ) )
            message += _( "**** gmoccapy will not start ****\n\n" )
            print( message )
            self.widgets.window1.destroy()
        self.axisletter_four = axis_four[0]
        self.axisnumber_four = "xyzabcuvw".index( self.axisletter_four )
        self.widgets.Combi_DRO_4.set_property( "joint_number", self.axisnumber_four )
        self.widgets.Combi_DRO_4.change_axisletter( self.axisletter_four.upper() )
        if self.axisletter_four in "abc":
            self.widgets.Combi_DRO_4.set_property( "mm_text_template", "%11.2f" )
            self.widgets.Combi_DRO_4.set_property( "imperial_text_template", "%11.2f" )
        image = self.widgets["img_home_%s" % self.axisletter_four]
        self.widgets.btn_home_4.set_image( image )
        self.widgets.btn_home_4.set_property( "tooltip-text", _( "Home axis %s" ) % self.axisletter_four.upper() )

        # We have to change the size of the DRO, to make 4 DRO fit the space we got
        for axis in self.axis_list:
            if axis == self.axisletter_four:
                axis = 4
            self.widgets["Combi_DRO_%s" % axis].set_property( "font_size", self.dro_size * 3 / 4 )

        self.widgets.btn_4_plus.set_label( "%s+" % self.axisletter_four.upper() )
        self.widgets.btn_4_minus.set_label( "%s-" % self.axisletter_four.upper() )
        self.widgets.btn_4_plus.show()
        self.widgets.btn_4_minus.show()
        self.widgets.lbl_replace_4.hide()
        self.widgets.btn_home_4.show()

        # we have to re-arrange the jog buttons, so first remove all button
        self.widgets.tbl_jog_btn.remove( self.widgets.btn_z_minus )
        self.widgets.tbl_jog_btn.remove( self.widgets.btn_z_plus )
        self.widgets.tbl_jog_btn.remove( self.widgets.btn_4_minus )
        self.widgets.tbl_jog_btn.remove( self.widgets.btn_4_plus )

        # now we place them in a different order
        self.widgets.tbl_jog_btn.attach( self.widgets.btn_z_plus, 2, 3, 0, 1, gtk.SHRINK, gtk.SHRINK )
        self.widgets.tbl_jog_btn.attach( self.widgets.btn_z_minus, 2, 3, 2, 3, gtk.SHRINK, gtk.SHRINK )
        self.widgets.tbl_jog_btn.attach( self.widgets.btn_4_plus, 3, 4, 0, 1, gtk.SHRINK, gtk.SHRINK )
        self.widgets.tbl_jog_btn.attach( self.widgets.btn_4_minus, 3, 4, 2, 3, gtk.SHRINK, gtk.SHRINK )

        if self.prefs.getpref( "hide_axis_4", False, bool ):
            self._hide_axis_4( True )

    def _hide_axis_4( self, state = False ):
        print( "axis 4 should be hidden", state )

        # we save the state, because it will be needed also
        # in _init_offsetpage and _init_tooleditor
        self.hide_axis_4 = state

        self.widgets.chk_hide_axis_4.set_active( self.hide_axis_4 )

        if self.hide_axis_4:
            self.widgets.frm_tool_changer.set_sensitive( True )
            self.widgets.Combi_DRO_4.hide()
            self.widgets.btn_4_plus.hide()
            self.widgets.btn_4_minus.hide()
            font_size = self.dro_size

            # we have to re-arrange the jog buttons, so first remove all button
            self.widgets.tbl_jog_btn.remove( self.widgets.btn_z_minus )
            self.widgets.tbl_jog_btn.remove( self.widgets.btn_z_plus )
            self.widgets.tbl_jog_btn.remove( self.widgets.btn_4_minus )
            self.widgets.tbl_jog_btn.remove( self.widgets.btn_4_plus )

            # now we place them in a different order
            self.widgets.tbl_jog_btn.attach( self.widgets.btn_z_plus, 3, 4, 0, 1, gtk.SHRINK, gtk.SHRINK )
            self.widgets.tbl_jog_btn.attach( self.widgets.btn_z_minus, 3, 4, 2, 3, gtk.SHRINK, gtk.SHRINK )
            self.widgets.tbl_jog_btn.attach( self.widgets.btn_4_plus, 3, 4, 0, 1, gtk.SHRINK, gtk.SHRINK )
            self.widgets.tbl_jog_btn.attach( self.widgets.btn_4_minus, 3, 4, 2, 3, gtk.SHRINK, gtk.SHRINK )

            self.widgets.btn_4_plus.hide()
            self.widgets.btn_4_minus.hide()
            self.widgets.lbl_replace_4.show()
            self.widgets.btn_home_4.hide()

        else:
            font_size = self.dro_size * 3 / 4

            # we have to re-arrange the jog buttons, so first remove all button
            self.widgets.tbl_jog_btn.remove( self.widgets.btn_z_minus )
            self.widgets.tbl_jog_btn.remove( self.widgets.btn_z_plus )
            self.widgets.tbl_jog_btn.remove( self.widgets.btn_4_minus )
            self.widgets.tbl_jog_btn.remove( self.widgets.btn_4_plus )

            # now we place them in a different order
            self.widgets.tbl_jog_btn.attach( self.widgets.btn_z_plus, 2, 3, 0, 1, gtk.SHRINK, gtk.SHRINK )
            self.widgets.tbl_jog_btn.attach( self.widgets.btn_z_minus, 2, 3, 2, 3, gtk.SHRINK, gtk.SHRINK )
            self.widgets.tbl_jog_btn.attach( self.widgets.btn_4_plus, 3, 4, 0, 1, gtk.SHRINK, gtk.SHRINK )
            self.widgets.tbl_jog_btn.attach( self.widgets.btn_4_minus, 3, 4, 2, 3, gtk.SHRINK, gtk.SHRINK )

            self.widgets.btn_4_plus.show()
            self.widgets.btn_4_minus.show()
            self.widgets.lbl_replace_4.hide()
            self.widgets.btn_home_4.show()
            self.widgets.Combi_DRO_4.show()

        for axis in self.axis_list:
            if axis == self.axisletter_four:
                axis = 4
            self.widgets["Combi_DRO_%s" % axis].set_property( "font_size", font_size )

    def _init_jog_increments( self ):
        # Now we will build the option buttons to select the Jog-rates
        # We do this dynamicly, because users are able to set them in INI File
        # because of space on the screen only 10 items are allowed
        # jogging increments

        # We get the increments from INI File
        self.jog_increments = self.get_ini_info.get_increments()
        if len( self.jog_increments ) > 10:
            print( _( "**** GMOCCAPY INFO ****" ) )
            print( _( "**** Too many increments given in INI File for this screen ****" ) )
            print( _( "**** Only the first 10 will be reachable through this screen ****" ) )
            # we shorten the incrementlist to 10 (first is default = 0)
            self.jog_increments = self.jog_increments[0:11]

        # The first radio button is created to get a radio button group
        # The group is called according the name off  the first button
        # We use the pressed signal, not the toggled, otherwise two signals will be emitted
        # One from the released button and one from the pressed button
        # we make a list of the buttons to later add the hardware pins to them
        label = _( "Continuous" )
        rbt0 = gtk.RadioButton( None, label )
        rbt0.connect( "pressed", self.on_increment_changed, 0 )
        self.widgets.vbtb_jog_incr.pack_start( rbt0, True, True, 0 )
        rbt0.set_property( "draw_indicator", False )
        rbt0.show()
        rbt0.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
        rbt0.__name__ = "rbt0"
        self.incr_rbt_list.append( rbt0 )
        # the rest of the buttons are now added to the group
        # self.no_increments is set while setting the hal pins with self._check_len_increments
        for item in range( 1, len( self.jog_increments ) ):
            rbt = "rbt%d" % ( item )
            rbt = gtk.RadioButton( rbt0, self.jog_increments[item] )
            rbt.connect( "pressed", self.on_increment_changed, self.jog_increments[item] )
            self.widgets.vbtb_jog_incr.pack_start( rbt, True, True, 0 )
            rbt.set_property( "draw_indicator", False )
            rbt.show()
            rbt.modify_bg( gtk.STATE_ACTIVE, gtk.gdk.color_parse( "#FFFF00" ) )
            rbt.__name__ = "rbt%d" % ( item )
            self.incr_rbt_list.append( rbt )
        self.active_increment = "rbt0"

    def _check_screen2( self ):
        # second screen
        self.screen2 = False
        screen2 = os.path.join( CONFIGPATH, "gmoccapy2.glade" )
        if os.path.exists( screen2 ):
            print ( _( "**** GMOCCAPY INFO ****" ) )
            print ( _( "**** gmoccapy screen 2 found ****" ) )
            try:
                self.builder.add_from_file( screen2 )
                self.screen2 = True
            except Exception, e:
                print ( _( "**** GMOCCAPY ERROR ****" ) )
                print _( "**** screen 2 GLADE ERROR: ****" )
                self.widgets.tbtn_use_screen2.set_sensitive( False )
                traceback.print_exc()
        else:
            print ( _( "**** GMOCCAPY INFO ****" ) )
            print _( "**** No gmoccapy2.glade file present ****" )
            self.widgets.tbtn_use_screen2.set_sensitive( False )

# =============================================================
# Dynamic tabs handling Start

    def _init_dynamic_tabs( self ):
        # dynamic tabs setup
        self._dynamic_childs = {}
        # register all tabs, so they will be closed together with the GUI
        atexit.register( self._kill_dynamic_childs )

        tab_names, tab_location, tab_cmd = self.get_ini_info.get_embedded_tabs()
        if not tab_names:
            print ( _( "**** GMOCCAPY INFO ****" ) )
            print ( _( "**** Invalid embedded tab configuration ****" ) )
            print ( _( "**** No tabs will be added! ****" ) )
            return

        try:
            for t, c, name in zip( tab_names, tab_cmd, tab_location ):
                nb = self.widgets[name]
                xid = self._dynamic_tab( nb, t )
                if not xid: continue
                cmd = c.replace( '{XID}', str( xid ) )
                child = subprocess.Popen( cmd.split() )
                self._dynamic_childs[xid] = child
                nb.show_all()
        except:
            print( _( "ERROR, trying to initialize the user tabs or panaels, check for typos" ) )

    # adds the embedded object to a notebook tab or box
    def _dynamic_tab( self, widget, text ):
        s = gtk.Socket()
        try:
            widget.append_page( s, gtk.Label( " " + text + " " ) )
        except:
            try:
                widget.pack_end( s, True, True, 0 )
            except:
                return None
        return s.get_id()

    # Gotta kill the embedded processes when gmoccapy closes
    def _kill_dynamic_childs( self ):
        for child in self._dynamic_childs.values():
            child.terminate()

# Dynamic tabs handling End
# =============================================================

    # first we hide all the axis columns the unhide the ones we want
    # if it's a lathe config we show lathe related columns
    # and we load the tooltable data
    def _init_tooleditor( self ):
        self.widgets.tooledit1.set_visible( "abcxyzuvwijq", False )
        for axis in self.axis_list:
            if axis == self.axisletter_four:
                if self.hide_axis_4:
                    continue
            self.widgets.tooledit1.set_visible( "%s" % axis, True )

        if self.lathe_mode:
            self.widgets.tooledit1.set_visible( "ijq", True )
        # get the path to the tool table
        tooltable = self.get_ini_info.get_toolfile()
        if not tooltable:
            print( _( "**** GMOCCAPY ERROR ****" ) )
            print( _( "**** Did not find a toolfile file in [EMCIO] TOOL_TABLE ****" ) )
            sys.exit()
        toolfile = os.path.join( CONFIGPATH, tooltable )
        self.widgets.tooledit1.set_filename( toolfile )

    def _init_themes( self ):
        # If there are themes then add them to combo box
        model = self.widgets.theme_choice.get_model()
        model.clear()
        model.append(("Follow System Theme",))
        themes = []
        if os.path.exists(USERTHEMEDIR):
            names = os.listdir(USERTHEMEDIR)
            names.sort()
            for dirs in names:
                sbdirs = os.listdir(os.path.join(USERTHEMEDIR, dirs))
                if 'gtk-2.0' in sbdirs:
                    themes.append(dirs)
        if os.path.exists(THEMEDIR):
            names = os.listdir(THEMEDIR)
            names.sort()
            for dirs in names:
                sbdirs = os.listdir(os.path.join(THEMEDIR, dirs))
                if 'gtk-2.0' in sbdirs:
                    themes.append(dirs)
        temp = 0
        theme_name = self.prefs.getpref( "gtk_theme", "Follow System Theme", str )
        for index,theme in enumerate(themes):
            model.append((theme,))
            if theme == theme_name:
                temp = index + 1
        self.widgets.theme_choice.set_active(temp)
        settings = gtk.settings_get_default()
        if not theme_name == "Follow System Theme":
            settings.set_string_property( "gtk-theme-name", theme_name, "" )

    def _init_audio( self ):
        # try to add ability for audio feedback to user.
        self._AUDIO_AVAILABLE = False
        try:
            import gst

            self._AUDIO_AVAILABLE = True
            print ( _( "**** GMOCCAPY INFO ****" ) )
            print ( _( "**** audio available! ****" ) )
        except:
            print ( _( "**** GMOCCAPY INFO ****" ) )
            print ( _( "**** no audio available! ****" ) )
            print( _( "**** PYGST libray not installed? ****" ) )
            return

        if self._AUDIO_AVAILABLE:
            self.audio = player.Player()
            self.alert_sound = self.prefs.getpref( 'audio_alert', self.alert_sound, str )
            self.error_sound = self.prefs.getpref( 'audio_error', self.error_sound, str )
            self.widgets.audio_alert_chooser.set_filename( self.alert_sound )
            self.widgets.audio_error_chooser.set_filename( self.error_sound )
        else:
            self.widgets.audio_alert_chooser.set_sensitiv( False )
            self.widgets.audio_error_chooser.set_sensitiv( False )

    # init the preview
    def _init_gremlin( self ):
        grid_size = self.prefs.getpref( 'grid_size', 1.0, float )
        self.widgets.grid_size.set_value( grid_size )
        self.widgets.gremlin.grid_size = grid_size
        view = self.prefs.getpref( 'view', "p", str )
        self.widgets.gremlin.set_property( "view", view )
        self.widgets.gremlin.set_property( "metric_units", int( self.stat.linear_units ) )
        self.widgets.gremlin.set_property( "mouse_btn_mode", self.prefs.getpref( "mouse_btn_mode", 4, int ) )
        self.widgets.gremlin.set_property( "use_commanded", not self.dro_actual)
        self.widgets.gremlin.init_glcanondraw(
             trajcoordinates=self.get_ini_info.get_trajcoordinates(),
             kinstype=self.get_ini_info.get_kinstype())

    # init the function to hide the cursor
    def _init_hide_cursor( self ):
        hide_cursor = self.prefs.getpref( 'hide_cursor', False, bool )
        self.widgets.chk_hide_cursor.set_active( hide_cursor )
        # if hide cursor requested
        # we set the graphics to use touchscreen controls
        if hide_cursor:
            self.widgets.window1.window.set_cursor( INVISABLE )
            self.widgets.gremlin.set_property( "use_default_controls", False )
        else:
            self.widgets.window1.window.set_cursor( None )
            self.widgets.gremlin.set_property( "use_default_controls", True )

# =============================================================
# Onboard keybord handling Start

    # shows "Onboard" virtual keyboard if available
    # else error message
    def _init_keyboard( self, args = "", x = "", y = "" ):
        self.onboard = False

        # now we check if onboard or matchbox-keyboard is installed
        try:
            if os.path.isfile( "/usr/bin/onboard" ):
                self.onboard_kb = subprocess.Popen( ["onboard", "--xid", args, x, y],
                                                   stdin = subprocess.PIPE,
                                                   stdout = subprocess.PIPE,
                                                   close_fds = True )
                print ( _( "**** GMOCCAPY INFO ****" ) )
                print ( _( "**** virtual keyboard program found : <onboard>" ) )
            elif os.path.isfile( "/usr/bin/matchbox-keyboard" ):
                self.onboard_kb = subprocess.Popen( ["matchbox-keyboard", "--xid"],
                                                   stdin = subprocess.PIPE,
                                                   stdout = subprocess.PIPE,
                                                   close_fds = True )
                print ( _( "**** GMOCCAPY INFO ****" ) )
                print ( _( "**** virtual keyboard program found : <matchbox-keyboard>" ) )
            else:
                print ( _( "**** GMOCCAPY INFO ****" ) )
                print ( _( "**** No virtual keyboard installed, we checked for <onboard> and <matchbox-keyboard>." ) )
                self._no_virt_keyboard()
                return
            sid = self.onboard_kb.stdout.readline()
            socket = gtk.Socket()
            socket.show()
            self.widgets.key_box.add( socket )
            socket.add_id( long( sid ) )
            self.onboard = True
        except Exception, e:
            print ( _( "**** GMOCCAPY ERROR ****" ) )
            print ( _( "**** Error launching virtual keyboard," ) )
            print ( _( "**** is onboard or matchbox-keyboard installed? ****" ) )
            traceback.print_exc()
            self._no_virt_keyboard()

    def _no_virt_keyboard( self ):
        # In this case we will disable the coresponding part on the settings page
        self.widgets.chk_use_kb_on_offset.set_active( False )
        self.widgets.chk_use_kb_on_tooledit.set_active( False )
        self.widgets.chk_use_kb_on_edit.set_active( False )
        self.widgets.chk_use_kb_on_mdi.set_active( False )
        self.widgets.chk_use_kb_on_file_selection.set_active( False )
        self.widgets.frm_keyboard.set_sensitive( False )
        self.widgets.btn_show_kbd.set_sensitive( False )
        self.widgets.btn_show_kbd.set_image( self.widgets.img_brake_macro )
        self.widgets.btn_show_kbd.set_property( "tooltip-text", _( "interrupt running macro" ) )
        self.widgets.btn_keyb.set_sensitive( False )

    def _kill_keyboard( self ):
        try:
            self.onboard_kb.kill()
            self.onboard_kb.terminate()
            self.onboard_kb = None
        except:
            try:
                self.onboard_kb.kill()
                self.onboard_kb.terminate()
                self.onboard_kb = None
            except:
                pass

# Onboard keybord handling End
# =============================================================

    def _init_offsetpage( self ):
        temp = "xyzabcuvw"
        self.widgets.offsetpage1.set_col_visible( temp, False )
        temp = ""
        for axis in self.axis_list:
            if axis == self.axisletter_four:
                if self.hide_axis_4:
                    continue
            temp = temp + axis
        self.widgets.offsetpage1.set_col_visible( temp, True )

        parameterfile = self.get_ini_info.get_parameter_file()
        if not parameterfile:
            print( _( "**** GMOCCAPY ERROR ****" ) )
            print( _( "**** Did not find a parameter file in [RS274NGC] PARAMETER_FILE ****" ) )
            sys.exit()
        path = os.path.join( CONFIGPATH, parameterfile )
        self.widgets.offsetpage1.set_filename( path )

        self.widgets.offsetpage1.set_display_follows_program_units()
        if self.stat.program_units != 1:
            self.widgets.offsetpage1.set_to_mm()
            self.widgets.offsetpage1.machine_units_mm = _MM
        else:
            self.widgets.offsetpage1.set_to_inch()
            self.widgets.offsetpage1.machine_units_mm = _INCH
        self.widgets.offsetpage1.hide_buttonbox( True )
        self.widgets.offsetpage1.set_row_visible( "1", False )
        self.widgets.offsetpage1.set_font( "sans 12" )
        self.widgets.offsetpage1.set_foreground_color( "#28D0D9" )
        self.widgets.offsetpage1.selection_mask = ( "Tool", "G5x", "Rot" )
        systemlist = ["Tool", "G5x", "Rot", "G92", "G54", "G55", "G56", "G57", "G58", "G59", "G59.1",
                      "G59.2", "G59.3"]
        names = []
        for system in systemlist:
            system_name = "system_name_%s" % system
            name = self.prefs.getpref( system_name, system, str )
            names.append( [system, name] )
        self.widgets.offsetpage1.set_names( names )

    # Icon file selection stuff
    def _init_IconFileSelection( self ):
        self.widgets.IconFileSelection1.set_property( "start_dir", self.get_ini_info.get_program_prefix() )

        file_ext = self.get_ini_info.get_file_ext()
        filetypes = ""
        for ext in file_ext:
            filetypes += ext.replace( "*.", "" ) + ","
        self.widgets.IconFileSelection1.set_property( "filetypes", filetypes )

        jump_to_dir = self.prefs.getpref( "jump_to_dir", os.path.expanduser( "~" ), str )
        self.widgets.jump_to_dir_chooser.set_current_folder( jump_to_dir )
        self.widgets.IconFileSelection1.set_property( "jump_to_dir", jump_to_dir )

        self.widgets.IconFileSelection1.show_buttonbox( False )
        self.widgets.IconFileSelection1.show_filelabel( False )
        
        # now we initialize the button states
        self.widgets.btn_home.set_sensitive(self.widgets.IconFileSelection1.btn_home.get_sensitive())
        self.widgets.btn_dir_up.set_sensitive(self.widgets.IconFileSelection1.btn_dir_up.get_sensitive())
        self.widgets.btn_sel_prev.set_sensitive(self.widgets.IconFileSelection1.btn_sel_prev.get_sensitive())
        self.widgets.btn_sel_next.set_sensitive(self.widgets.IconFileSelection1.btn_sel_next.get_sensitive())
        self.widgets.btn_select.set_sensitive(self.widgets.IconFileSelection1.btn_select.get_sensitive())
        self.widgets.btn_jump_to.set_sensitive(self.widgets.IconFileSelection1.btn_jump_to.get_sensitive())
        self.widgets.btn_jump_to.set_sensitive(self.widgets.IconFileSelection1.btn_jump_to.get_sensitive())

    # init the keyboard shortcut bindings
    def _init_keybindings( self ):
        try:
            accel_group = gtk.AccelGroup()
            self.widgets.window1.add_accel_group( accel_group )
            self.widgets.button_estop.add_accelerator( "clicked", accel_group, 65307, 0, gtk.ACCEL_LOCKED )
        except:
            pass
        self.widgets.window1.connect( "key_press_event", self.on_key_event, 1 )
        self.widgets.window1.connect( "key_release_event", self.on_key_event, 0 )

    # Initialize the file to load dialog, setting an title and the correct
    # folder as well as a file filter
    def _init_file_to_load( self ):
        file_dir = self.get_ini_info.get_program_prefix()
        self.widgets.file_to_load_chooser.set_current_folder( file_dir )
        title = _( "Select the file you want to be loaded at program start" )
        self.widgets.file_to_load_chooser.set_title( title )
        self.widgets.ff_file_to_load.set_name( "linuxcnc files" )
        self.widgets.ff_file_to_load.add_pattern( "*.ngc" )
        file_ext = self.get_ini_info.get_file_ext()
        for ext in file_ext:
            self.widgets.ff_file_to_load.add_pattern( ext )

    # search for and set up user requested message system.
    # status displays on the statusbat and requires no acknowledge.
    # dialog displays a GTK dialog box with yes or no buttons
    # okdialog displays a GTK dialog box with an ok button
    # dialogs require an answer before focus is sent back to main screen
    def _init_user_messages( self ):
        user_messages = self.get_ini_info.get_user_messages()
        print user_messages
        if not user_messages:
            return
        for message in user_messages:
            if message[1] == "status":
                pin = hal_glib.GPin( self.halcomp.newpin( "messages." + message[2], hal.HAL_BIT, hal.HAL_IN ) )
                pin.connect( "value_changed", self._show_user_message, message )
            elif message[1] == "okdialog":
                pin = hal_glib.GPin( self.halcomp.newpin( "messages." + message[2], hal.HAL_BIT, hal.HAL_IN ) )
                pin.connect( "value_changed", self._show_user_message, message )
                pin = hal_glib.GPin( 
                    self.halcomp.newpin( "messages." + message[2] + "-waiting", hal.HAL_BIT, hal.HAL_OUT ) )
            elif message[1] == "yesnodialog":
                pin = hal_glib.GPin( self.halcomp.newpin( "messages." + message[2], hal.HAL_BIT, hal.HAL_IN ) )
                pin.connect( "value_changed", self._show_user_message, message )
                pin = hal_glib.GPin( 
                    self.halcomp.newpin( "messages." + message[2] + "-waiting", hal.HAL_BIT, hal.HAL_OUT ) )
                pin = hal_glib.GPin( 
                    self.halcomp.newpin( "messages." + message[2] + "-responce", hal.HAL_BIT, hal.HAL_OUT ) )
            else:
                print( _( "**** GMOCCAPY ERROR **** /n Message type %s not suported" % message[1] ) )

    def _show_user_message( self, pin, message ):
        if message[1] == "status":
            if pin.get():
                self._show_error( ( 0, message[0] ) )
        elif message[1] == "okdialog":
            self.halcomp["messages." + message[2] + "-waiting"] = 0
            if pin.get():
                self.halcomp["messages." + message[2] + "-waiting"] = 1
                title = "Pin " + message[2] + " message"
                responce = dialogs.show_user_message( self, message[0], title )
                self.halcomp["messages." + message[2] + "-waiting"] = 0
        elif message[1] == "yesnodialog":
            if pin.get():
                self.halcomp["messages." + message[2] + "-waiting"] = 1
                self.halcomp["messages." + message[2] + "-responce"] = 0
                title = "Pin " + message[2] + " message"
                responce = dialogs.yesno_dialog( self, message[0], title )
                self.halcomp["messages." + message[2] + "-waiting"] = 0
                self.halcomp["messages." + message[2] + "-responce"] = responce
            else:
                self.halcomp["messages." + message[2] + "-waiting"] = 0
        else:
            print( _( "**** GMOCCAPY ERROR **** /n Message type %s not suported" % message[1] ) )

    def _show_offset_tab( self, state ):
        page = self.widgets.ntb_preview.get_nth_page( 1 )
        if page.get_visible() and state or not page.get_visible() and not state:
            return
        if state:
            page.show()
            self.widgets.ntb_preview.set_property( "show-tabs", state )
            self.widgets.ntb_preview.set_current_page( 1 )
            self.widgets.offsetpage1.mark_active( ( self.system_list[self.stat.g5x_index] ).lower() )
            if self.widgets.chk_use_kb_on_offset.get_active():
                self.widgets.ntb_info.set_current_page( 1 )
        else:
            names = self.widgets.offsetpage1.get_names()
            for system, name in names:
                system_name = "system_name_%s" % system
                self.prefs.putpref( system_name, name, str )
            page.hide()
            self.widgets.tbtn_edit_offsets.set_active( False )
            self.widgets.ntb_preview.set_current_page( 0 )
            self.widgets.ntb_info.set_current_page( 0 )
            if self.widgets.ntb_preview.get_n_pages() <= 4:  # else user tabs are availible
                self.widgets.ntb_preview.set_property( "show-tabs", state )

    def _show_tooledit_tab( self, state ):
        page = self.widgets.ntb_preview.get_nth_page( 2 )
        if page.get_visible() and state or not page.get_visible() and not state:
            return
        if state:
            page.show()
            self.widgets.ntb_preview.set_property( "show-tabs", not state )
            self.widgets.vbx_jog.hide()
            self.widgets.ntb_preview.set_current_page( 2 )
            self.widgets.tooledit1.set_selected_tool( self.stat.tool_in_spindle )
            if self.widgets.chk_use_kb_on_tooledit.get_active():
                self.widgets.ntb_info.set_current_page( 1 )
        else:
            page.hide()
            if self.widgets.ntb_preview.get_n_pages() > 4:  # user tabs are availible
                self.widgets.ntb_preview.set_property( "show-tabs", not state )
            self.widgets.vbx_jog.show()
            self.widgets.ntb_preview.set_current_page( 0 )
            self.widgets.ntb_info.set_current_page( 0 )

    def _show_iconview_tab( self, state ):
        page = self.widgets.ntb_preview.get_nth_page( 3 )
        if page.get_visible() and state or not page.get_visible() and not state:
            return
        if state:
            page.show()
            self.widgets.ntb_preview.set_property( "show-tabs", not state )
            self.widgets.ntb_preview.set_current_page( 3 )
            if self.widgets.chk_use_kb_on_file_selection.get_active():
                self.widgets.box_info.show()
                self.widgets.ntb_info.set_current_page( 1 )
        else:
            page.hide()
            if self.widgets.ntb_preview.get_n_pages() > 4:  # user tabs are availible
                self.widgets.ntb_preview.set_property( "show-tabs", not state )
            self.widgets.ntb_preview.set_current_page( 0 )
            self.widgets.ntb_info.set_current_page( 0 )

    # every 100 milli seconds this gets called
    # check linuxcnc for status, error and then update the readout
    def _periodic( self ):
        self.stat.poll()
        error = self.error_channel.poll()
        if error:
            self._show_error( error )

        if self.gcodes != self.stat.gcodes:
            self._update_active_gcodes()
        if self.mcodes != self.stat.mcodes:
            self._update_active_mcodes()

        if self.lathe_mode:
            if "G8" in self.active_gcodes and self.diameter_mode:
                self._switch_to_g7( False )
            elif "G7" in self.active_gcodes and not self.diameter_mode:
                self._switch_to_g7( True )

        self._update_vel()
        self._update_coolant()
        self._update_spindle()
        self._update_halui_pin()

        self.widgets.lbl_time.set_label( strftime( "%H:%M:%S" ) + "\n" + strftime( "%d.%m.%Y" ) )

        # keep the timer running
        return True

    def _show_error( self, error ):
        kind, text = error
        # print kind,text
        if "joint" in text:
            for letter in self.axis_list:
                axnum = "xyzabcuvws".index( letter )
                text = text.replace( "joint %d" % axnum, "Axis %s" % letter.upper() )
        if kind in ( linuxcnc.NML_ERROR, linuxcnc.OPERATOR_ERROR ):
            icon = ALERT_ICON
            self.halcomp["error"] = True
        elif kind in ( linuxcnc.NML_TEXT, linuxcnc.OPERATOR_TEXT ):
            icon = INFO_ICON
        elif kind in ( linuxcnc.NML_DISPLAY, linuxcnc.OPERATOR_DISPLAY ):
            icon = INFO_ICON
        else:
            icon = ALERT_ICON
        if text == "" or text == None:
            text = _( "Unknown error type and no error text given" )
        self.notification.add_message( text, icon )

        if self._AUDIO_AVAILABLE:
            if kind == 1 or kind == 11:
                self.audio.set_sound( self.error_sound )
            else:
                self.audio.set_sound( self.alert_sound )
            self.audio.run()

    def on_gremlin_gcode_error( self, widget, errortext ):
        if self.gcodeerror == errortext:
            return
        else:
            self.gcodeerror = errortext
            print( errortext )
            dialogs.warning_dialog( self, _( "Important Warning" ), errortext )


# =========================================================
# button handlers Start

    # toggle emergency button
    def on_tbtn_estop_toggled( self, widget, data = None ):
        if widget.get_active():  # estop is active, open circuit
            self.command.state( linuxcnc.STATE_ESTOP )
            self.command.wait_complete()
            self.stat.poll()
            if self.stat.task_state == linuxcnc.STATE_ESTOP_RESET:
                widget.set_active( False )
        else:  # estop circuit is fine
            self.command.state( linuxcnc.STATE_ESTOP_RESET )
            self.command.wait_complete()
            self.stat.poll()
            if self.stat.task_state == linuxcnc.STATE_ESTOP:
                widget.set_active( True )
                self._show_error( ( 11, _( "ERROR : External ESTOP is set, could not change state!" ) ) )

    # toggle machine on / off button
    def on_tbtn_on_toggled( self, widget, data = None ):
        if widget.get_active():
            if self.stat.task_state == linuxcnc.STATE_ESTOP:
                widget.set_active( False )
                return
            self.command.state( linuxcnc.STATE_ON )
            self.command.wait_complete()
            self.stat.poll()
            if self.stat.task_state != linuxcnc.STATE_ON:
                widget.set_active( False )
                self._show_error( ( 11, _( "ERROR : Could not switch the machine on, is limit switch activated?" ) ) )
                self._update_widgets( False )
                return
            self._update_widgets( True )
        else:
            self.command.state( linuxcnc.STATE_OFF )
            self._update_widgets( False )

    # The mode buttons
    def on_rbt_manual_pressed( self, widget, data = None ):
        self.command.mode( linuxcnc.MODE_MANUAL )
        self.command.wait_complete()

    def on_rbt_mdi_pressed( self, widget, data = None ):
        self.command.mode( linuxcnc.MODE_MDI )
        self.command.wait_complete()

    def on_rbt_auto_pressed( self, widget, data = None ):
        self.command.mode( linuxcnc.MODE_AUTO )
        self.command.wait_complete()

    # If button exit is clicked, press emergency button bevor closing the application
    def on_btn_exit_clicked( self, widget, data = None ):
        self.widgets.window1.destroy()

# button handlers End
# =========================================================

# =========================================================
# hal status Start

    # use the hal_status widget to control buttons and
    # actions allowed by the user and sensitive widgets
    def on_hal_status_all_homed( self, widget ):
        self.all_homed = True
        self.widgets.ntb_button.set_current_page( 0 )
        widgetlist = ["rbt_mdi", "rbt_auto", "btn_index_tool", "btn_change_tool", "btn_select_tool_by_no",
                      "btn_tool_touchoff_x", "btn_tool_touchoff_z", "btn_touch"
        ]
        self._sensitize_widgets( widgetlist, True )

    def on_hal_status_not_all_homed( self, *args ):
        self.all_homed = False
        if self.no_force_homing:
            return
        widgetlist = ["rbt_mdi", "rbt_auto", "btn_index_tool", "btn_touch", "btn_change_tool", "btn_select_tool_by_no",
                      "btn_tool_touchoff_x", "btn_tool_touchoff_z", "btn_touch"
        ]
        self._sensitize_widgets( widgetlist, False )

    def on_hal_status_homed( self, widget, data ):
        pass

    def on_hal_status_file_loaded( self, widget, filename ):
        widgetlist = ["btn_use_current"
        ]
        # this test is only neccesary, because of remap and toolchange, it will emit a file loaded signal
        if filename:
            fileobject = file( filename, 'r' )
            lines = fileobject.readlines()
            fileobject.close()
            self.halcomp["program.length"] = len( lines )

            if len( filename ) > 50:
                filename = filename[0:10] + "..." + filename[len( filename ) - 39:len( filename )]
            self.widgets.lbl_program.set_text( filename )
            self._sensitize_widgets( widgetlist, True )
        else:
            self.halcomp["program.length"] = 0
            self._sensitize_widgets( widgetlist, False )
            self.widgets.lbl_program.set_text( _( "No file loaded" ) )

    def on_hal_status_line_changed( self, widget, line ):
        self.halcomp["program.current-line"] = line
        # this test is only neccesary, because of remap and toolchange, it will emit a file loaded signal
        if self.halcomp["program.length"] > 0:
            self.halcomp["program.progress"] = 100.00 * line / self.halcomp["program.length"]
        else:
            self.halcomp["program.progress"] = 0.0
            # print("Progress = {0:.2f} %".format(100.00 * line / self.halcomp["program.length"]))

    def on_hal_status_interp_idle( self, widget ):
        widgetlist = ["rbt_manual", "ntb_jog", "btn_from_line",
                      "tbtn_flood", "tbtn_mist", "rbt_forward", "rbt_reverse", "rbt_stop",
                      "btn_load", "btn_edit", "tbtn_optional_blocks"
        ]
        if not self.widgets.rbt_hal_unlock.get_active():
            widgetlist.append( "tbtn_setup" )
        if self.all_homed or self.no_force_homing:
            widgetlist.append( "rbt_mdi" )
            widgetlist.append( "rbt_auto" )
            widgetlist.append( "btn_index_tool" )
            widgetlist.append( "btn_change_tool" )
            widgetlist.append( "btn_select_tool_by_no" )
            widgetlist.append( "btn_tool_touchoff_x" )
            widgetlist.append( "btn_tool_touchoff_z" )
            widgetlist.append( "btn_touch" )
        self._sensitize_widgets( widgetlist, True )
        for btn in self.macrobuttons:
            btn.set_sensitive( True )
        if self.onboard:
            self.widgets.btn_show_kbd.set_image( self.widgets.img_keyboard )
        else:
            self.widgets.btn_show_kbd.set_image( self.widgets.img_brake_macro )
        self.widgets.btn_run.set_sensitive( True )

        if self.tool_change:
            self.command.mode( linuxcnc.MODE_MANUAL )
            self.command.wait_complete()
            self.tool_change = False

        self.halcomp["program.current-line"] = 0
        self.halcomp["program.progress"] = 0.0

    def on_hal_status_interp_run( self, widget ):
        widgetlist = ["rbt_manual", "rbt_mdi", "rbt_auto", "tbtn_setup", "btn_index_tool",
                      "btn_from_line", "btn_change_tool", "btn_select_tool_by_no",
                      "btn_load", "btn_edit", "tbtn_optional_blocks", "rbt_reverse", "rbt_stop", "rbt_forward",
                      "btn_tool_touchoff_x", "btn_tool_touchoff_z", "btn_touch"
        ]
        # in MDI it should be possible to add more commands, even if the interpreter is running
        if self.stat.task_mode != linuxcnc.MODE_MDI:
            widgetlist.append( "ntb_jog" )

        self._sensitize_widgets( widgetlist, False )
        self.widgets.btn_run.set_sensitive( False )

        self.widgets.btn_show_kbd.set_image( self.widgets.img_brake_macro )
        self.widgets.btn_show_kbd.set_property( "tooltip-text", _( "interrupt running macro" ) )

    def on_hal_status_tool_in_spindle_changed( self, object, new_tool_no ):
        self._update_toolinfo( new_tool_no )

    def on_hal_status_state_estop( self, widget = None ):
        self.widgets.tbtn_estop.set_active( True )
        self.widgets.tbtn_estop.set_image( self.widgets.img_emergency )
        self.widgets.tbtn_on.set_image( self.widgets.img_machine_on )
        self.widgets.tbtn_on.set_sensitive( False )
        self.widgets.chk_ignore_limits.set_sensitive( False )
        self.widgets.tbtn_on.set_active( False )
        self.command.mode( linuxcnc.MODE_MANUAL )

    def on_hal_status_state_estop_reset( self, widget = None ):
        self.widgets.tbtn_estop.set_active( False )
        self.widgets.tbtn_estop.set_image( self.widgets.img_emergency_off )
        self.widgets.tbtn_on.set_image( self.widgets.img_machine_off )
        self.widgets.tbtn_on.set_sensitive( True )
        self.widgets.ntb_jog.set_sensitive( True )
        self.widgets.tbl_jog_btn.set_sensitive( False )
        self.widgets.vbtb_jog_incr.set_sensitive( False )
        self.widgets.hbox_jog_vel.set_sensitive( False )
        self.widgets.chk_ignore_limits.set_sensitive( True )
        self._check_limits()

    def on_hal_status_state_off( self, widget ):
        widgetlist = ["rbt_manual", "rbt_mdi", "rbt_auto", "btn_homing", "btn_touch", "btn_tool",
                      "hbox_jog_vel", "tbl_jog_btn", "vbtb_jog_incr", "scl_feed", "btn_feed_100", "rbt_forward", "btn_index_tool",
                      "rbt_reverse", "rbt_stop", "tbtn_flood", "tbtn_mist", "btn_change_tool", "btn_select_tool_by_no",
                      "btn_spindle_100", "scl_max_vel", "scl_spindle",
                      "btn_tool_touchoff_x", "btn_tool_touchoff_z"
        ]
        self._sensitize_widgets( widgetlist, False )
        if self.widgets.tbtn_on.get_active():
            self.widgets.tbtn_on.set_active( False )
        self.widgets.tbtn_on.set_image( self.widgets.img_machine_off )
        self.widgets.btn_exit.set_sensitive( True )
        self.widgets.chk_ignore_limits.set_sensitive( True )
        self.widgets.ntb_main.set_current_page( 0 )
        self.widgets.ntb_button.set_current_page( 0 )
        self.widgets.ntb_info.set_current_page( 0 )
        self.widgets.ntb_jog.set_current_page( 0 )

    def on_hal_status_state_on( self, widget ):
        widgetlist = ["rbt_manual", "btn_homing", "btn_touch", "btn_tool",
                      "ntb_jog", "scl_feed", "btn_feed_100", "rbt_forward",
                      "rbt_reverse", "rbt_stop", "tbtn_flood", "tbtn_mist",
                      "btn_spindle_100", "scl_max_vel", "scl_spindle"
        ]
        self._sensitize_widgets( widgetlist, True )
        if not self.widgets.tbtn_on.get_active():
            self.widgets.tbtn_on.set_active( True )
        self.widgets.tbtn_on.set_image( self.widgets.img_machine_on )
        self.widgets.btn_exit.set_sensitive( False )
        self.widgets.chk_ignore_limits.set_sensitive( False )
        if self.widgets.ntb_main.get_current_page() != 0:
            self.command.mode( linuxcnc.MODE_MANUAL )
            self.command.wait_complete()

    def on_hal_status_mode_manual( self, widget ):
        self.widgets.rbt_manual.set_active( True )
        # setup page will be activated, if we don't leave, the pages will be reset with this call
        if self.widgets.tbtn_setup.get_active() == True:
            return
        self.widgets.ntb_main.set_current_page( 0 )
        self.widgets.ntb_button.set_current_page( 0 )
        self.widgets.ntb_info.set_current_page( 0 )
        self.widgets.ntb_jog.set_current_page( 0 )
        self._check_limits()

    def on_hal_status_mode_mdi( self, widget ):
        # self.tool_change is set only if the tool change was commanded
        # from tooledit widget/page, so we do not want to switch the
        # screen layout to MDI, but set the manual widgets
        if self.tool_change:
            self.widgets.ntb_main.set_current_page( 0 )
            self.widgets.ntb_button.set_current_page( 0 )
            self.widgets.ntb_info.set_current_page( 0 )
            self.widgets.ntb_jog.set_current_page( 0 )
            return
        # if MDI button is not sensitive, we are not ready for MDI commands
        # so we have to abort external commands and get back to manual mode
        # This will hapen mostly, if we are in settings mode, as we do disable the mode button
        if not self.widgets.rbt_mdi.get_sensitive():
            self.command.abort()
            self.command.mode( linuxcnc.MODE_MANUAL )
            self.command.wait_complete()
            self._show_error( ( 13, _( "It is not possible to change to MDI Mode at the moment" ) ) )
            return
        else:
            if self.widgets.chk_use_kb_on_mdi.get_active():
                self.widgets.ntb_info.set_current_page( 1 )
            else:
                self.widgets.ntb_info.set_current_page( 0 )
            self.widgets.ntb_main.set_current_page( 0 )
            self.widgets.ntb_button.set_current_page( 1 )
            self.widgets.ntb_jog.set_current_page( 1 )
            self.widgets.hal_mdihistory.entry.grab_focus()
            self.widgets.rbt_mdi.set_active( True )

    def on_hal_status_mode_auto( self, widget ):
        # if Auto button is not sensitive, we are not ready for AUTO commands
        # so we have to abort external commands and get back to manual mode
        # This will hapen mostly, if we are in settings mode, as we do disable the mode button
        if not self.widgets.rbt_auto.get_sensitive():
            self.command.abort()
            self.command.mode( linuxcnc.MODE_MANUAL )
            self.command.wait_complete()
            self._show_error( ( 13, _( "It is not possible to change to Auto Mode at the moment" ) ) )
            return
        else:
            self.widgets.ntb_main.set_current_page( 0 )
            self.widgets.ntb_button.set_current_page( 2 )
            self.widgets.ntb_info.set_current_page( 0 )
            self.widgets.ntb_jog.set_current_page( 2 )
            self.widgets.rbt_auto.set_active( True )

# hal status End
# =========================================================

    # There are some settings we can only do if the window is on the screen allready
    def on_window1_show( self, widget, data = None ):

        # it is time to get the correct estop state and set the button status
        self.stat.poll()
        if self.stat.task_state == linuxcnc.STATE_ESTOP:
            self.widgets.tbtn_estop.set_active( True )
            self.widgets.tbtn_estop.set_image( self.widgets.img_emergency )
            self.widgets.tbtn_on.set_image( self.widgets.img_machine_off )
            self.widgets.tbtn_on.set_sensitive( False )
        else:
            self.widgets.tbtn_estop.set_active( False )
            self.widgets.tbtn_estop.set_image( self.widgets.img_emergency_off )
            self.widgets.tbtn_on.set_sensitive( True )

        # if a file should be loaded, we will do so
        file = self.prefs.getpref( "open_file", "", str )
        if file:
            self.widgets.file_to_load_chooser.set_filename( file )
            # self.command.program_open(file)
            self.widgets.hal_action_open.load_file( file )

        # check how to start the GUI
        start_as = "rbtn_" + self.prefs.getpref( "screen1", "window", str )
        self.widgets[start_as].set_active( True )
        if start_as == "rbtn_fullscreen":
            self.widgets.window1.fullscreen()
        elif start_as == "rbtn_maximized":
            self.widgets.window1.maximize()
        else:
            self.xpos = int( self.prefs.getpref( "x_pos", 40, float ) )
            self.ypos = int( self.prefs.getpref( "y_pos", 30, float ) )
            self.width = int( self.prefs.getpref( "width", 979, float ) )
            self.height = int( self.prefs.getpref( "height", 750, float ) )

            # set the adjustments acording to Window position and size
            self.widgets.adj_x_pos.set_value( self.xpos )
            self.widgets.adj_y_pos.set_value( self.ypos )
            self.widgets.adj_width.set_value( self.width )
            self.widgets.adj_height.set_value( self.height )

            # move and resize the window
            self.widgets.window1.move( self.xpos, self.ypos )
            self.widgets.window1.resize( self.width, self.height )

        self.command.mode( linuxcnc.MODE_MANUAL )
        self.command.wait_complete()

        self.initialized = True

        # does the user want to show screen2
        self._check_screen2()
        if self.screen2:
            self.widgets.tbtn_use_screen2.set_active( self.prefs.getpref( "use_screen2", False, bool ) )

    # kill keyboard and estop machine before closing
    def on_window1_destroy( self, widget, data = None ):
        print "estopping / killing gmoccapy"
        self._kill_keyboard()
        self.command.state( linuxcnc.STATE_OFF )
        self.command.state( linuxcnc.STATE_ESTOP )
        gtk.main_quit()

    # What to do if a macro button has been pushed
    def _on_btn_macro_pressed( self, widget = None, data = None ):
        o_codes = data.split()
        subroutines_path = self.get_ini_info.get_subroutine_path()
        if not subroutines_path:
            message = _( "**** GMOCCAPY ERROR ****" )
            message += _( "\n**** No subroutine folder or program prefix is given in the ini file **** \n" )
            message += _( "**** so the corresponding file could not be found ****" )
            dialogs.warning_dialog( self, _( "Important Warning" ), message )
            return
        file = subroutines_path + "/" + o_codes[0] + ".ngc"
        if not os.path.isfile( file ):
            message = _( "**** GMOCCAPY ERROR ****" )
            message += _( "\n**** File %s of the macro could not be found ****\n" % [o_codes[0] + ".ngc"] )
            message += _( "**** we searched in subdirectory %s ****" % subroutines_path )
            dialogs.warning_dialog( self, _( "Important Warning" ), message )
            return
        command = str( "O<" + o_codes[0] + "> call" )
        for code in o_codes[1:]:
            parameter = dialogs.entry_dialog( self, data = None, header = _( "Enter value:" ),
                                             label = _( "Set parameter %s to:" ) % code, integer = False )
            if parameter == "ERROR":
                print( _( "conversion error" ) )
                dialogs.warning_dialog( self, _( "Conversion error !" ),
                                       _( "Please enter only numerical values\nValues have not been applied" ) )
                return
            elif parameter == "CANCEL":
                return
            else:
                pass
            command = command + " [" + str( parameter ) + "] "
# TODO: Should not only clear the plot, but also the loaded programm?
        # self.command.program_open("")
        # self.command.reset_interpreter()
        self.widgets.gremlin.clear_live_plotter()
# TODO: End
        self.command.mdi( command )
        for btn in self.macrobuttons:
            btn.set_sensitive( False )
        # we change the widget_image and use the button to interupt running macros
        if not self.onboard:
            self.widgets.btn_show_kbd.set_sensitive(True)
        self.widgets.btn_show_kbd.set_image( self.widgets.img_brake_macro )
        self.widgets.btn_show_kbd.set_property( "tooltip-text", _( "interrupt running macro" ) )
        self.widgets.ntb_info.set_current_page( 0 )

# helpers functions start
# =========================================================

    def _update_widgets( self, state ):
        widgetlist = ["rbt_manual", "btn_homing", "btn_touch", "btn_tool",
                      "hbox_jog_vel", "tbl_jog_btn", "vbtb_jog_incr", "scl_feed", "btn_feed_100", "rbt_forward", "btn_index_tool",
                      "rbt_reverse", "rbt_stop", "tbtn_flood", "tbtn_mist", "btn_change_tool", "btn_select_tool_by_no",
                      "btn_spindle_100", "scl_max_vel", "scl_spindle",
                      "btn_tool_touchoff_x", "btn_tool_touchoff_z"
        ]
        self._sensitize_widgets( widgetlist, state )

    def _switch_to_g7( self, state ):
        if state:
            self.widgets.Combi_DRO_x.set_property( "abs_color", gtk.gdk.color_parse( "#F2F1F0" ) )
            self.widgets.Combi_DRO_x.set_property( "rel_color", gtk.gdk.color_parse( "#F2F1F0" ) )
            self.widgets.Combi_DRO_x.set_property( "dtg_color", gtk.gdk.color_parse( "#F2F1F0" ) )
            self.widgets.Combi_DRO_y.set_property( "abs_color", gtk.gdk.color_parse( self.abs_color ) )
            self.widgets.Combi_DRO_y.set_property( "rel_color", gtk.gdk.color_parse( self.rel_color ) )
            self.widgets.Combi_DRO_y.set_property( "dtg_color", gtk.gdk.color_parse( self.dtg_color ) )
            self.diameter_mode = True
        else:
            self.widgets.Combi_DRO_y.set_property( "abs_color", gtk.gdk.color_parse( "#F2F1F0" ) )
            self.widgets.Combi_DRO_y.set_property( "rel_color", gtk.gdk.color_parse( "#F2F1F0" ) )
            self.widgets.Combi_DRO_y.set_property( "dtg_color", gtk.gdk.color_parse( "#F2F1F0" ) )
            self.widgets.Combi_DRO_x.set_property( "abs_color", gtk.gdk.color_parse( self.abs_color ) )
            self.widgets.Combi_DRO_x.set_property( "rel_color", gtk.gdk.color_parse( self.rel_color ) )
            self.widgets.Combi_DRO_x.set_property( "dtg_color", gtk.gdk.color_parse( self.dtg_color ) )
            self.diameter_mode = False

    def on_key_event( self, widget, event, signal ):

        # get the keyname
        keyname = gtk.gdk.keyval_name( event.keyval )
        #print("pressed key = ",keyname)

        # estop with F1 shold work every time
        # so should also escape aboart actions
        if keyname == "F1":  # will estop the machine, but not reset estop!
            self.command.state( linuxcnc.STATE_ESTOP )
            return True
        if keyname == "Escape":
            self.command.abort()
            return True

        #print self.last_key_event[0] ,self.last_key_event[1]
        # This will avoid excecuting the key press event several times caused by keyboard auto repeat
        if self.last_key_event[0] == keyname and self.last_key_event[1] == signal:
            return True

        try:
            if keyname == "F2" and signal:
                # only turn on if no estop!
                if self.widgets.tbtn_estop.get_active():
                    return True
                self.widgets.tbtn_on.emit( "clicked" )
                return True
        except:
            pass

        if keyname == "space" and signal:
            if event.state & gtk.gdk.CONTROL_MASK:  # only do it when control is hold down
                self.notification.del_message( -1 )
                self.widgets.window1.grab_focus()
                return

        if keyname == "Super_L" and signal:  # Left Windows
            self.notification.del_last()
            self.widgets.window1.grab_focus()
            return

        # if the user do not want to use keyboard shortcuts, we leave here
        # in this case we do not return true, otherwise entering code in MDI history
        # and the integrated editor will not work
        if not self.widgets.chk_use_kb_shortcuts.get_active():
            print( "Settings say: do not use keyboard shortcuts, aboart" )
            return

        # F3 should change to manual mode
        if keyname == "F3" and signal:
            self.command.mode(linuxcnc.MODE_MANUAL)
            self.command.wait_complete()
            # we need to leave here, otherwise the check for jogging 
            # only allowed in manual mode will finish the sub
            self.last_key_event = keyname, signal
            return True

        # F5 should change to mdi mode
        if keyname == "F5" and signal:
            self.command.mode(linuxcnc.MODE_MDI)
            self.command.wait_complete()        
            # we need to leave here, otherwise the check for jogging 
            # only allowed in manual mode will finish the sub
            self.last_key_event = keyname, signal
            return True

        # Only in MDI mode the RETURN key should execute a command
        if keyname == "Return" and signal and self.stat.task_mode == linuxcnc.MODE_MDI:
            #print("Got enter in MDI")
            self.widgets.hal_mdihistory.submit() 
            # we need to leave here, otherwise the check for jogging 
            # only allowed in manual mode will finish the sub
            return True

        # Only in manual mode jogging with keyboard is allowed
        # in this case we do not return true, otherwise entering code in MDI history
        # and the integrated editor will not work
        # we also check if we are in settings or user page
        if self.stat.task_mode != linuxcnc.MODE_MANUAL or not self.widgets.ntb_main.get_current_page() == 0:
            return

        # offset page is active, so keys must go through
        if self.widgets.ntb_preview.get_current_page() == 1:
            return

        # tooledit page is active, so keys must go through
        if self.widgets.ntb_preview.get_current_page() == 2:
            return

        # take care of differnt key handling for lathe operation
        if self.lathe_mode:
            if keyname == "Page_Up" or keyname == "Page_Down":
                return

        if event.state & gtk.gdk.SHIFT_MASK:  # SHIFT is hold down, fast jogging active
            fast = True
        else:
            fast = False

        if keyname == "Up":
            if self.lathe_mode:
                if self.backtool_lathe:
                    widget = self.widgets.btn_x_plus
                else:
                    widget = self.widgets.btn_x_minus
            else:
                widget = self.widgets.btn_y_plus
            if signal:
                self.on_btn_jog_pressed( widget, fast )
            else:
                self.on_btn_jog_released( widget )
        elif keyname == "Down":
            if self.lathe_mode:
                if self.backtool_lathe:
                    widget = self.widgets.btn_x_minus
                else:
                    widget = self.widgets.btn_x_plus
            else:
                widget = self.widgets.btn_y_minus
            if signal:
                self.on_btn_jog_pressed( widget, fast )
            else:
                self.on_btn_jog_released( widget )
        elif keyname == "Left":
            if self.lathe_mode:
                widget = self.widgets.btn_z_minus
            else:
                widget = self.widgets.btn_x_minus
            if signal:
                self.on_btn_jog_pressed( widget, fast )
            else:
                self.on_btn_jog_released( widget )
        elif keyname == "Right":
            if self.lathe_mode:
                widget = self.widgets.btn_z_plus
            else:
                widget = self.widgets.btn_x_plus
            if signal:
                self.on_btn_jog_pressed( widget, fast )
            else:
                self.on_btn_jog_released( widget )
        elif keyname == "Page_Up":
            widget = self.widgets.btn_z_plus
            if signal:
                self.on_btn_jog_pressed( widget, fast )
            else:
                self.on_btn_jog_released( widget )
        elif keyname == "Page_Down":
            widget = self.widgets.btn_z_minus
            if signal:
                self.on_btn_jog_pressed( widget, fast )
            else:
                self.on_btn_jog_released( widget )
        elif keyname == "I" or keyname == "i":
            if signal:
                if self.stat.state != 1: # still moving
                    return
                # The active button name is hold in self.active_increment
                if keyname == "I":
                    # so lets increment it by one
                    rbt = int(self.active_increment[-1]) + 1
                    # we check if we are still in the allowed limit
                    if rbt > len(self.jog_increments) - 1: # begining from zero
                        rbt = 0
                else: # must be "i"
                    # so lets reduce it by one
                    rbt = int(self.active_increment[-1]) - 1
                    # we check if we are still in the allowed limit
                    if rbt < 0:
                        rbt = len(self.jog_increments) - 1 # begining from zero
                # we set the corresponding button active
                self.incr_rbt_list[rbt].set_active(True)
                # and we have to update all pin and variables
                self.on_increment_changed(self.incr_rbt_list[rbt], self.jog_increments[rbt])
        else:
            print( "This key has not been implemented yet" )
            print "Key %s (%d) was pressed" % ( keyname, event.keyval ), signal, self.last_key_event
        self.last_key_event = keyname, signal
        return True

    # Notification stuff.
    def init_notification( self ):
        start_as = "rbtn_" + self.prefs.getpref( "screen1", "window", str )
        xpos, ypos = self.widgets.window1.window.get_origin()
        self.notification.set_property( 'x_pos', self.widgets.adj_x_pos_popup.get_value() )
        self.notification.set_property( 'y_pos', self.widgets.adj_y_pos_popup.get_value() )
        self.notification.set_property( 'message_width', self.widgets.adj_width_popup.get_value() )
        if int( self.widgets.adj_max_messages.get_value() ) != 0:
            self.notification.set_property( 'max_messages', self.widgets.adj_max_messages.get_value() )
        self.notification.set_property( 'use_frames', self.widgets.chk_use_frames.get_active() )
        self.notification.set_property( 'font', self.widgets.fontbutton_popup.get_font_name() )
        self.notification.set_property( 'icon_size', 48 )
        self.notification.set_property( 'top_to_bottom', True )

    # This is the jogging part
    def on_increment_changed( self, widget = None, data = None ):
        if self.stat.interp_state != linuxcnc.INTERP_IDLE:
            return

        if data == 0:
            self.distance = 0
        else:
            self.distance = self._parse_increment( data )
        self.halcomp["jog-increment"] = self.distance
        self.active_increment = widget.__name__

    def _from_internal_linear_unit( self, v, unit = None ):
        if unit is None:
            unit = self.stat.linear_units
        lu = ( unit or 1 ) * 25.4
        return v * lu

    def _parse_increment( self, jogincr ):
        if jogincr.endswith( "mm" ):
            scale = self._from_internal_linear_unit( 1 / 25.4 )
        elif jogincr.endswith( "cm" ):
            scale = self._from_internal_linear_unit( 10 / 25.4 )
        elif jogincr.endswith( "um" ):
            scale = self._from_internal_linear_unit( .001 / 25.4 )
        elif jogincr.endswith( "in" ) or jogincr.endswith( "inch" ):
            scale = self._from_internal_linear_unit( 1. )
        elif jogincr.endswith( "mil" ):
            scale = self._from_internal_linear_unit( .001 )
        else:
            scale = 1
        jogincr = jogincr.rstrip( " inchmuil" )
        if "/" in jogincr:
            p, q = jogincr.split( "/" )
            jogincr = float( p ) / float( q )
        else:
            jogincr = float( jogincr )
        return jogincr * scale

    def _replace_list_item( self, int_tab, old_value, new_value ):
        list = self.h_tabs[int_tab]
        self.h_tabs[int_tab] = []
        for item in list:
            if item[1] == old_value:
                new_tupple = ( item[0], new_value )
                item = new_tupple
                print( _( "**** GMOCCAPY INFO ****" ) )
                print( _( "**** replaced {0} to {1} ****".format( old_value, new_value ) ) )
            self.h_tabs[int_tab].append( item )

    # check if macros are in the INI file and add them to MDI Button List
    def _add_macro_button( self ):
        macros = self.get_ini_info.get_macros()
        num_macros = len( macros )
        if num_macros > 9:
            message = _( "**** GMOCCAPY INFO ****" )
            message += _( "\n**** found more than 9 macros, only the first 9 will be used ****" )
            print( message )
            num_macros = 9
        for increment in range( 0, num_macros ):
            name = macros[increment]
            # shorten the name if it is to long
            if len( name ) > 11:
                lbl = name[0:10]
            else:
                lbl = macros[increment]
            btn = gtk.Button( lbl, None, False )
            btn.connect( "pressed", self._on_btn_macro_pressed, name )
            btn.position = increment
            # we add the button to a list to be able later to see what makro to excecute
            self.macrobuttons.append( btn )
            self.widgets.hbtb_MDI.pack_start( btn, True, True, 0 )
            btn.show()
        # if there is still place, we fill it with empty labels, to be sure the button will not be on differnt
        # places if the amount of macros change.
        if num_macros < 9:
            for label_space in range( num_macros, 9 ):
                lbl = "lbl_sp_%s" % label_space
                lbl = gtk.Label( lbl )
                lbl.position = label_space
                lbl.set_text( "" )
                self.widgets.hbtb_MDI.pack_start( lbl, True, True, 0 )
                lbl.show()
        self.widgets.hbtb_MDI.non_homogeneous = False

    def show_try_errors( self ):
        exc_type, exc_value, exc_traceback = sys.exc_info()
        formatted_lines = traceback.format_exc().splitlines()
        print( _( "**** GMOCCAPY ERROR ****" ) )
        print( _( "**** %s ****" % formatted_lines[0] ) )
        traceback.print_tb( exc_traceback, limit = 1, file = sys.stdout )
        print ( formatted_lines[-1] )

    def _sensitize_widgets( self, widgetlist, value ):
        for name in widgetlist:
            try:
                self.widgets[name].set_sensitive( value )
            except Exception, e:
                print ( _( "**** GMOCCAPY ERROR ****" ) )
                print _( "**** No widget named: %s to sensitize ****" % name )
                traceback.print_exc()

    def _update_active_gcodes( self ):
        # active G codes
        active_codes = []
        temp = []
        for code in sorted( self.stat.gcodes[1:] ):
            if code == -1:
                continue
            if code % 10 == 0:
                temp.append( "%d" % ( code / 10 ) )
            else:
                temp.append( "%d.%d" % ( code / 10, code % 10 ) )
        for num, code in enumerate( temp ):
            if num == 8:
                active_codes.append( "\n" )
            active_codes.append( "G" + code )
        self.active_gcodes = active_codes
        self.gcodes = self.stat.gcodes
        self.widgets.active_gcodes_label.set_label( " ".join( self.active_gcodes ) )

    def _update_active_mcodes( self ):
        # M codes
        active_codes = []
        temp = []
        for code in sorted( self.stat.mcodes[1:] ):
            if code == -1:
                continue
            temp.append( "%d" % code )
        for code in ( temp ):
            active_codes.append( "M" + code )
        self.active_mcodes = active_codes
        self.mcodes = self.stat.mcodes
        self.widgets.active_mcodes_label.set_label( " ".join( self.active_mcodes ) )

    # Update the velocity labels
    def _update_vel( self ):
        # self.stat.program_units will return 1 for inch, 2 for mm and 3 for cm
        real_feed = float( self.stat.settings[1] * self.stat.feedrate )
        if self.stat.program_units != 1:
            self.widgets.lbl_current_vel.set_text( "%d" % ( self.stat.current_vel * 60.0 * self.faktor ) )
            if "G95" in self.active_gcodes:
                feed_str = "%d" % self.stat.settings[1]
                real_feed_str = "F  %.2f" % real_feed
            else:
                feed_str = "%d" % self.stat.settings[1]
                real_feed_str = "F  %.d" % real_feed
        else:
            self.widgets.lbl_current_vel.set_text( "%.3f" % ( self.stat.current_vel * 60.0 * self.faktor ) )
            if "G95" in self.active_gcodes:
                feed_str = "%.4f" % self.stat.settings[1]
                real_feed_str = "F %.4f" % real_feed
            else:
                feed_str = "%.3f" % self.stat.settings[1]
                real_feed_str = "F %.3f" % real_feed

        # converting 0.0 to string brings nothing, so the string is empty
        # happens only on start up
        if not real_feed:
            real_feed_str = "F  0"

        self.widgets.lbl_active_feed.set_label( feed_str )
        self.widgets.lbl_feed_act.set_text( real_feed_str )

    def _update_coolant( self ):
        if self.stat.flood:
            if not self.widgets.tbtn_flood.get_active():
                self.widgets.tbtn_flood.set_active( True )
                self.widgets.tbtn_flood.set_image( self.widgets.img_coolant_on )
        else:
            if self.widgets.tbtn_flood.get_active():
                self.widgets.tbtn_flood.set_active( False )
                self.widgets.tbtn_flood.set_image( self.widgets.img_coolant_off )
        if self.stat.mist:
            if not self.widgets.tbtn_mist.get_active():
                self.widgets.tbtn_mist.set_active( True )
                self.widgets.tbtn_mist.set_image( self.widgets.img_mist_on )
        else:
            if self.widgets.tbtn_mist.get_active():
                self.widgets.tbtn_mist.set_active( False )
                self.widgets.tbtn_mist.set_image( self.widgets.img_mist_off )

    def _update_halui_pin( self ):
        if self.spindle_override != self.stat.spindlerate:
            self.initialized = False
            self.widgets.adj_spindle.set_value( self.stat.spindlerate * 100 )
            self.spindle_override = self.stat.spindlerate
            self.initialized = True
        if self.feed_override != self.stat.feedrate:
            self.initialized = False
            self.widgets.adj_feed.set_value( self.stat.feedrate * 100 )
            self.feed_override = self.stat.feedrate
            self.widgets.adj_max_vel.set_value( float( self.widgets.adj_max_vel.upper * self.stat.feedrate ) )
            self.initialized = True
        if self.max_velocity != self.stat.max_velocity:
            self.initialized = False
            self.widgets.adj_max_vel.set_value( self.stat.max_velocity * 60 )
            self.max_velocity = self.stat.max_velocity
            self.initialized = True
#        if self.rapidrate != self.stat.rapidrate:
#            self.initialized = False
#            self.widgets.adj_max_vel.set_value(self.stat.max_velocity * 60 * self.stat.rapidrate)
#            print( "Rapid Rate = ", self.stat.rapidrate )
#            self.rapidrate = self.stat.rapidrate
#            self.initialized = True

    def _update_slider( self, widgetlist ):
        # update scales and sliders
        for widget in widgetlist:
            value = self.widgets[widget].get_value()
            max = self.widgets[widget].upper
            min = self.widgets[widget].lower
            self.widgets[widget].lower = min * self.faktor
            self.widgets[widget].upper = max * self.faktor
            self.widgets[widget].set_value( value * self.faktor )
        self.scale_jog_vel = self.scale_jog_vel * self.faktor
        self.scale_max_vel = self.scale_max_vel * self.faktor
        self.on_adj_max_vel_value_changed( self.widgets.adj_max_vel )

    def _change_dro_color( self, property, color ):
        for axis in self.axis_list:
            if axis == self.axisletter_four:
                axis = 4
            self.widgets["Combi_DRO_%s" % axis].set_property( property, color )
        if self.lathe_mode:
            self.widgets.Combi_DRO_y.set_property( property, color )
            # check if G7 or G8 is active
            # this is set on purpose wrong, because we want the periodic
            # to update the state correctly
            if "G7" in self.active_gcodes:
                self.diameter_mode = False
            else:
                self.diameter_mode = True

    def _update_toolinfo( self, tool ):
        toolinfo = self.widgets.tooledit1.get_toolinfo( tool )
        if toolinfo:
            # Doku
            # toolinfo[0] = cell toggle
            # toolinfo[1] = tool number
            # toolinfo[2] = pocket number
            # toolinfo[3] = X offset
            # toolinfo[4] = Y offset
            # toolinfo[5] = Z offset
            # toolinfo[6] = A offset
            # toolinfo[7] = B offset
            # toolinfo[8] = C offset
            # toolinfo[9] = U offset
            # toolinfo[10] = V offset
            # toolinfo[11] = W offset
            # toolinfo[12] = tool diameter
            # toolinfo[13] = frontangle
            # toolinfo[14] = backangle
            # toolinfo[15] = tool orientation
            # toolinfo[16] = tool info
            self.widgets.lbl_tool_no.set_text( str( toolinfo[1] ) )
            self.widgets.lbl_tool_dia.set_text( toolinfo[12] )
            self.widgets.lbl_tool_name.set_text( toolinfo[16] )

        # we do not allow touch off with no tool mounted, so we set the
        # coresponding widgets unsensitive and set the description acordingly
        if tool <= 0:
            self.widgets.lbl_tool_no.set_text( "0" )
            self.widgets.lbl_tool_dia.set_text( "0" )
            self.widgets.lbl_tool_name.set_text( _( "No tool description available" ) )
            self.widgets.btn_tool_touchoff_x.set_sensitive( False )
            self.widgets.btn_tool_touchoff_z.set_sensitive( False )
        else:
            self.widgets.btn_tool_touchoff_x.set_sensitive( True )
            self.widgets.btn_tool_touchoff_z.set_sensitive( True )

        if "G43" in self.active_gcodes and self.stat.task_mode != linuxcnc.MODE_AUTO:
            self.command.mode( linuxcnc.MODE_MDI )
            self.command.wait_complete()
            self.command.mdi( "G43" )
            self.command.wait_complete()

# helpers functions end
# =========================================================

    def on_adj_dro_digits_value_changed( self, widget, data = None ):
        if not self.initialized:
            return
        self.dro_digits = int( widget.get_value() )
        self.prefs.putpref( "dro_digits", self.dro_digits, int )
        if self.stat.program_units != 1:
            format_string_mm = "%" + str( 13 - self.dro_digits ) + "." + str( self.dro_digits ) + "f"
            format_string_inch = "%" + str( 13 - self.dro_digits - 1 ) + "." + str( self.dro_digits + 1 ) + "f"
        else:
            format_string_inch = "%" + str( 13 - self.dro_digits ) + "." + str( self.dro_digits ) + "f"
            format_string_mm = "%" + str( 13 - self.dro_digits + 1 ) + "." + str( self.dro_digits - 1 ) + "f"

        for axis in self.axis_list:
            if axis == self.axisletter_four:
                axis = 4
            self.widgets["Combi_DRO_%s" % axis].set_property( "mm_text_template", format_string_mm )
            self.widgets["Combi_DRO_%s" % axis].set_property( "imperial_text_template", format_string_inch )

        if self.lathe_mode:
            self.widgets.Combi_DRO_y.set_property( "mm_text_template", format_string_mm )
            self.widgets.Combi_DRO_y.set_property( "imperial_text_template", format_string_inch )

    def on_chk_toggle_readout_toggled( self, widget, data = None):
        state = widget.get_active()
        self.prefs.putpref( "toggle_readout", state, bool )
        self.toggle_readout = state
        for axis in self.axis_list:
            if axis == self.axisletter_four:
                axis = 4
            self.widgets["Combi_DRO_%s" % axis].set_property( "toggle_readout", state )

    def on_Combi_DRO_clicked( self, widget, joint_number, order ):
        if not self.toggle_readout:
            return
        for axis in self.axis_list:
            if axis == self.axisletter_four:
                axis = 4
            self.widgets["Combi_DRO_%s" % axis].set_order( order )
        if self.lathe_mode:
            self.widgets.Combi_DRO_y.set_order( order )
        self._offset_changed( None, None )
# from here only needed, if the DRO button will remain in gmoccapy
        if order[0] == "Abs" and self.widgets.tbtn_rel.get_label() != "Abs":
            self.widgets.tbtn_rel.set_active( False )
        if order[0] == "Rel" and self.widgets.tbtn_rel.get_label() != self.widgets.Combi_DRO_x.system:
            self.widgets.tbtn_rel.set_active( True )
        if order[0] == "DTG":
            self.widgets.tbtn_dtg.set_active( True )
        else:
            self.widgets.tbtn_dtg.set_active( False )
# to here only needed, if the DRO button will remain in gmoccapy

    def _offset_changed( self, pin, tooloffset ):
        if self.widgets.Combi_DRO_x.machine_units == _MM:
            self.widgets.lbl_tool_offset_z.set_text( "%.3f" % self.halcomp["tooloffset-z"] )
            self.widgets.lbl_tool_offset_x.set_text( "%.3f" % self.halcomp["tooloffset-x"] )
        else:
            self.widgets.lbl_tool_offset_z.set_text( "%.4f" % self.halcomp["tooloffset-z"] )
            self.widgets.lbl_tool_offset_x.set_text( "%.4f" % self.halcomp["tooloffset-x"] )

    def on_offsetpage1_selection_changed( self, widget, system, name ):
        if system not in self.system_list[1:] or self.widgets.tbtn_edit_offsets.get_active():
            self.widgets.btn_set_selected.set_sensitive( False )
        else:
            self.widgets.btn_set_selected.set_sensitive( True )

# =========================================================
# from here only needed, if the DRO button will remain in gmoccapy

    def on_Combi_DRO_system_changed( self, widget, system ):
        if self.widgets.tbtn_rel.get_active():
            self.widgets.tbtn_rel.set_label( system )
        else:
            self.widgets.tbtn_rel.set_label( "Abs" )

    def on_Combi_DRO_units_changed( self, widget, metric_units ):
        # if the user do not wish to use auto units, we leave here
        if not self.widgets.chk_auto_units.get_active():
            return

        # set gremlin_units
        self.widgets.gremlin.set_property( "metric_units", metric_units )

        widgetlist = ["adj_jog_vel", "adj_max_vel"]

        # self.stat.linear_units will return 1.0 for metric and 1/25,4 for imperial
        # display units not equal machine units
        if metric_units != int( self.stat.linear_units ):
            # machine units = metric
            if self.stat.linear_units == _MM:
                self.faktor = ( 1.0 / 25.4 )
            # machine units = imperial
            else:
                self.faktor = 25.4
            self._update_slider( widgetlist )
        else:
            # display units equal machine units would be factor = 1,
            # but if factor not equal 1.0 than we have to reconvert from previous first
            if self.faktor != 1.0:
                self.faktor = 1 / self.faktor
                self._update_slider( widgetlist )
                self.faktor = 1.0
                self._update_slider( widgetlist )

        if metric_units:
            self.widgets.scl_max_vel.set_digits( 0 )
            self.widgets.scl_jog_vel.set_digits( 0 )
        else:
            self.widgets.scl_max_vel.set_digits( 3 )
            self.widgets.scl_jog_vel.set_digits( 3 )

    def on_tbtn_rel_toggled( self, widget, data = None ):
        if self.widgets.tbtn_dtg.get_active():
            self.widgets.tbtn_dtg.set_active( False )
        if widget.get_active():
            widget.set_label( self.widgets.Combi_DRO_x.system )
            order = ["Rel", "Abs", "DTG"]
        else:
            widget.set_label( "Abs" )
            order = ["Abs", "DTG", "Rel"]
        self.on_Combi_DRO_clicked( None, None, order )

    def on_tbtn_dtg_toggled( self, widget, data = None ):
        if widget.get_active():
            widget.set_label( "GTD" )
            order = ["DTG", "Rel", "Abs"]
        else:
            widget.set_label( "DTG" )
            if self.widgets.tbtn_rel.get_active():
                order = ["Rel", "Abs", "DTG"]
            else:
                order = ["Abs", "DTG", "Rel"]
        self.on_Combi_DRO_clicked( None, None, order )

    def on_tbtn_units_toggled( self, widget, data = None ):
        if widget.get_active():
            widget.set_label( "inch" )
            metric_units = False
        else:
            widget.set_label( "mm" )
            metric_units = True
        for axis in self.axis_list:
            if axis == self.axisletter_four:
                axis = 4
            self.widgets["Combi_DRO_%s" % axis].set_to_inch( not metric_units )
        if self.lathe_mode:
            self.widgets.Combi_DRO_y.set_to_inch( not metric_units )
        # set gremlin_units
        self.widgets.gremlin.set_property( "metric_units", metric_units )

    def on_chk_auto_units_toggled( self, widget, data = None ):
        for axis in self.axis_list:
            if axis == self.axisletter_four:
                axis = 4
            self.widgets["Combi_DRO_%s" % axis].set_auto_units( self.widgets.chk_auto_units.get_active() )
        if self.lathe_mode:
            self.widgets.Combi_DRO_y.set_auto_units( self.widgets.chk_auto_units.get_active() )
        self.prefs.putpref( "use_auto_units", self.widgets.chk_auto_units.get_active(), bool )

    def on_chk_show_dro_btn_toggled( self, widget, data = None ):
        if self.widgets.chk_show_dro_btn.get_active():
            self.widgets.tbl_dro_button.show()
            self.widgets.chk_auto_units.set_active( False )
            self.widgets.chk_auto_units.set_sensitive( False )
        else:
            self.widgets.tbl_dro_button.hide()
            self.widgets.chk_auto_units.set_active( True )
            self.widgets.chk_auto_units.set_sensitive( True )
        self.prefs.putpref( "show_dro_btn", self.widgets.chk_show_dro_btn.get_active(), bool )

# to here only needed, if the DRO button will remain in gmoccapy
# =========================================================

    def on_adj_x_pos_popup_value_changed( self, widget, data = None ):
        if not self.initialized:
            return
        self.prefs.putpref( "x_pos_popup", widget.get_value(), float )
        self.init_notification()

    def on_adj_y_pos_popup_value_changed( self, widget, data = None ):
        if not self.initialized:
            return
        self.prefs.putpref( "y_pos_popup", widget.get_value(), float )
        self.init_notification()

    def on_adj_width_popup_value_changed( self, widget, data = None ):
        if not self.initialized:
            return
        self.prefs.putpref( "width_popup", widget.get_value(), float )
        self.init_notification()

    def on_adj_max_messages_value_changed( self, widget, data = None ):
        if not self.initialized:
            return
        self.prefs.putpref( "max_messages", widget.get_value(), float )
        self.init_notification()

    def on_chk_use_frames_toggled( self, widget, data = None ):
        if not self.initialized:
            return
        self.prefs.putpref( "use_frames", widget.get_active(), bool )
        self.init_notification()

    def on_fontbutton_popup_font_set( self, font ):
        self.prefs.putpref( "message_font", self.widgets.fontbutton_popup.get_font_name(), str )
        self.init_notification()

    def on_btn_launch_test_message_pressed( self, widget = None, data = None ):
        index = len( self.notification.messages )
        text = _( "Halo, welcome to the test message %d" ) % index
        self._show_error( ( 13, text ) )

    def on_chk_turtle_jog_toggled( self, widget, data = None ):
        state = widget.get_active()
        self.prefs.putpref( "hide_turtle_jog_button", state )
        self.widgets.tbl_turtle_jog_factor.set_sensitive( not state )
        if state:
            self.widgets.tbtn_turtle_jog.hide()
        else:
            self.widgets.tbtn_turtle_jog.show()
            self.turtle_jog_factor = self.prefs.getpref( 'turtle_jog_factor', 20, int )
            self.widgets.adj_turtle_jog_factor.configure( self.turtle_jog_factor, 1,
                                                         100, 1, 0, 0 )
            self.turtle_jog = self.jog_rate / self.turtle_jog_factor

    def on_adj_turtle_jog_factor_value_changed( self, widget, data = None ):
        if not self.initialized:
            return
        self.turtle_jog_factor = int( widget.get_value() )
        self.prefs.putpref( "turtle_jog_factor", self.turtle_jog_factor, int )
        self.turtle_jog = self.rabbit_jog / self.turtle_jog_factor
        if self.widgets.tbtn_turtle_jog.get_active():
            self.widgets.adj_jog_vel.configure( self.turtle_jog, 1,
                                               self.jog_rate_max / self.turtle_jog_factor, 1, 0, 0 )

    def on_tbtn_turtle_jog_toggled( self, widget, data = None ):
        if widget.get_active():
            self.rabbit_jog = self.widgets.adj_jog_vel.get_value()
            widget.set_image( self.widgets.img_turtle_jog )
            active_jog_vel = self.widgets.adj_jog_vel.get_value()
            self.widgets.adj_jog_vel.configure( self.turtle_jog, 0,
                                               self.jog_rate_max / self.turtle_jog_factor, 1, 0, 0 )
        else:
            self.turtle_jog = self.widgets.adj_jog_vel.get_value()
            widget.set_image( self.widgets.img_rabbit_jog )
            self.widgets.adj_jog_vel.configure( self.rabbit_jog, 0,
                                               self.jog_rate_max, 1, 0, 0 )

    def _on_turtle_jog_enable( self, pin ):
        self.widgets.tbtn_turtle_jog.set_active( bool( pin.get() ) )

    def on_btn_jog_pressed( self, widget, data = None ):
        # only in manual mode we will allow jogging the axis at this development state
        if not self.stat.task_mode == linuxcnc.MODE_MANUAL:
            return

        axisletter = widget.get_label()[0]
        if not axisletter.lower() in "xyzabcuvw":
            print ( "unknown axis %s" % axisletter )
            return

        # get the axisnumber
        axisnumber = "xyzabcuvws".index( axisletter.lower() )

        # if data = True, then the user pressed SHIFT for Jogging and
        # want's to jog at full speed
        if data:
            value = self.widgets.adj_max_vel.get_value() / 60
        else:
            value = self.widgets.adj_jog_vel.get_value() / 60

        velocity = value * ( 1 / self.faktor )

        dir = widget.get_label()[1]
        if dir == "+":
            direction = 1
        else:
            direction = -1

        self.set_motion_mode()
        if self.distance <> 0:  # incremental jogging
            self.command.jog( linuxcnc.JOG_INCREMENT, 0, axisnumber, direction * velocity, self.distance )
        else:  # continuous jogging
            self.command.jog( linuxcnc.JOG_CONTINUOUS, 0, axisnumber, direction * velocity )

    def on_btn_jog_released( self, widget, data = None ):
        # only in manual mode we will allow jogging the axis at this development state
        if not self.stat.task_mode == linuxcnc.MODE_MANUAL:
            return

        axisletter = widget.get_label()[0]
        if not axisletter.lower() in "xyzabcuvw":
            print ( "unknown axis %s" % axisletter )
            return

        axis = "xyzabcuvw".index( axisletter.lower() )

        # Otherwise the movement would stop before the desired distance was moved
        if self.distance <> 0:
            pass
        else:
            self.set_motion_mode()
            self.command.jog( linuxcnc.JOG_STOP, 0,  axis )

    # use the current loaded file to be loaded on start up
    def on_btn_use_current_clicked( self, widget, data = None ):
        if self.stat.file:
            self.widgets.file_to_load_chooser.set_filename( self.stat.file )
            self.prefs.putpref( "open_file", self.stat.file, str )

    # Clear the status to load a file on start up, so there will not be loaded a programm
    # on the next start of the GUI
    def on_btn_none_clicked( self, widget, data = None ):
        self.widgets.file_to_load_chooser.set_filename( " " )
        self.prefs.putpref( "open_file", " ", str )

    def on_ntb_main_switch_page( self, widget, page, page_num, data = None ):
        if self.widgets.tbtn_setup.get_active():
            if page_num != 1L:  # setup page is active,
                self.widgets.tbtn_setup.set_active( False )

    def on_tbtn_setup_toggled( self, widget, data = None ):
        # first we set to manual mode, as we do not allow changing settings in other modes
        # otherwise external halui commands could start a program while we are in settings
        self.command.mode( linuxcnc.MODE_MANUAL )
        self.command.wait_complete()

        if widget.get_active():
            # deactivate the mode buttons, so changing modes is not possible while we are in settings mode
            self.widgets.rbt_manual.set_sensitive( False )
            self.widgets.rbt_mdi.set_sensitive( False )
            self.widgets.rbt_auto.set_sensitive( False )
            code = False
            # here the user don"t want an unlock code
            if self.widgets.rbt_no_unlock.get_active():
                code = True
            # if hal pin is true, we are allowed to enter settings, this may be
            # realized using a key switch
            if self.widgets.rbt_hal_unlock.get_active() and self.halcomp["unlock-settings"]:
                code = True
            # else we ask for the code using the system.dialog
            if self.widgets.rbt_use_unlock.get_active():
                if dialogs.system_dialog( self ):
                    code = True
            # Lets see if the user has the right to enter settings
            if code:
                self.widgets.ntb_main.set_current_page( 1 )
                self.widgets.ntb_setup.set_current_page( 0 )
                self.widgets.ntb_button.set_current_page( 5 )
            else:
                if self.widgets.rbt_hal_unlock.get_active():
                    message = _( "Hal Pin is low, Access denied" )
                else:
                    message = _( "wrong code entered, Access denied" )
                dialogs.warning_dialog( self, _( "Just to warn you" ), message )
                self.widgets.tbtn_setup.set_active( False )
        else:
            # check which button should be sensitive, depending on the state of the machine
            if self.stat.task_state == linuxcnc.STATE_ESTOP:
                # estoped no mode availible
                self.widgets.rbt_manual.set_sensitive( False )
                self.widgets.rbt_mdi.set_sensitive( False )
                self.widgets.rbt_auto.set_sensitive( False )
            if ( self.stat.task_state == linuxcnc.STATE_ON ) and not self.all_homed:
                # machine on, but not homed, only manual allowed
                self.widgets.rbt_manual.set_sensitive( True )
                self.widgets.rbt_mdi.set_sensitive( False )
                self.widgets.rbt_auto.set_sensitive( False )
            if ( self.stat.task_state == linuxcnc.STATE_ON ) and ( self.all_homed or self.no_force_homing ):
                # all OK, make all modes availible
                self.widgets.rbt_manual.set_sensitive( True )
                self.widgets.rbt_mdi.set_sensitive( True )
                self.widgets.rbt_auto.set_sensitive( True )
            # this is needed here, because we do not
            # change mode, so on_hal_status_manual will not be called
            self.widgets.ntb_main.set_current_page( 0 )
            self.widgets.ntb_button.set_current_page( 0 )
            self.widgets.ntb_info.set_current_page( 0 )
            self.widgets.ntb_jog.set_current_page( 0 )

    # Show or hide the user tabs
    def on_tbtn_user_tabs_toggled( self, widget, data = None ):
        if widget.get_active():
            self.widgets.ntb_main.set_current_page( 2 )
            self.widgets.tbtn_fullsize_preview.set_sensitive( False )
        else:
            self.widgets.ntb_main.set_current_page( 0 )
            self.widgets.tbtn_fullsize_preview.set_sensitive( True )

# =========================================================
# The homing functions
    def on_btn_homing_clicked( self, widget, data = None ):
        self.widgets.ntb_button.set_current_page( 3 )

    def on_btn_home_all_clicked( self, widget, data = None ):
        self.command.teleop_enable(0)
        self.command.wait_complete()
        # home -1 means all
        self.command.home( -1 )

    def on_btn_unhome_all_clicked( self, widget, data = None ):
        self.all_homed = False
        # -1 for all
        self.command.teleop_enable(0)
        self.command.wait_complete()
        self.command.unhome( -1 )

    def on_btn_home_selected_clicked( self, widget, data = None ):
        if widget == self.widgets.btn_home_x:
            axis = 0
        elif widget == self.widgets.btn_home_y:
            axis = 1
        elif widget == self.widgets.btn_home_z:
            axis = 2
        elif widget == self.widgets.btn_home_4:
            axis = "xyzabcuvw".index( self.axisletter_four )
        self.command.home( axis )

    def _check_limits( self ):
        for axis in self.axis_list:
            axisnumber = "xyzabcuvw".index( axis )
            if self.stat.limit[axisnumber] != 0:
                return True
        if self.widgets.chk_ignore_limits.get_active():
            self.widgets.chk_ignore_limits.set_active( False )
        return False

    def on_chk_ignore_limits_toggled( self, widget, data = None ):
        if self.widgets.chk_ignore_limits.get_active():
            if not self._check_limits():
                self._show_error( ( 11, _( "ERROR : No limit switch is active, ignore limits will not be set." ) ) )
                return
            self.command.override_limits()

    def on_tbtn_fullsize_preview_toggled( self, widget, data = None ):
        if widget.get_active():
            self.widgets.box_info.hide()
            self.widgets.vbx_jog.hide()
            self.widgets.gremlin.set_property( "metric_units", self.widgets.Combi_DRO_x.metric_units )
            self.widgets.gremlin.set_property( "enable_dro", True )
            if self.lathe_mode:
                self.widgets.gremlin.set_property( "show_lathe_radius", not self.diameter_mode )
        else:
            self.widgets.box_info.show()
            self.widgets.vbx_jog.show()
            if not self.widgets.chk_show_dro.get_active():
                self.widgets.gremlin.set_property( "enable_dro", False )
        
# =========================================================
# this are hal-tools copied from gsreen function
    def on_btn_show_hal_clicked( self, widget, data = None ):
        p = os.popen( "tclsh %s/bin/halshow.tcl &" % TCLPATH )

    def on_btn_calibration_clicked( self, widget, data = None ):
        p = os.popen( "tclsh %s/bin/emccalib.tcl -- -ini %s > /dev/null &" % ( TCLPATH, sys.argv[2] ), "w" )

    def on_btn_hal_meter_clicked( self, widget, data = None ):
        p = os.popen( "halmeter &" )

    def on_btn_status_clicked( self, widget, data = None ):
        p = os.popen( "linuxcnctop  > /dev/null &", "w" )

    def on_btn_hal_scope_clicked( self, widget, data = None ):
        p = os.popen( "halscope  > /dev/null &", "w" )

    def on_btn_classicladder_clicked( self, widget, data = None ):
        if hal.component_exists( "classicladder_rt" ):
            p = os.popen( "classicladder  &", "w" )
        else:
            dialogs.warning_dialog( self, _( "INFO:" ),
                                   _( "Classicladder real-time component not detected" ) )

# =========================================================
# spindle stuff

    def _update_spindle( self ):
        if self.stat.spindle_direction > 0:
            self.widgets.rbt_forward.set_active( True )
        elif self.stat.spindle_direction < 0:
            self.widgets.rbt_reverse.set_active( True )
        elif not self.widgets.rbt_stop.get_active():
            self.widgets.rbt_stop.set_active( True )
        # this is needed, because otherwise a command S0 would not set active btn_stop
        if not abs( self.stat.spindle_speed ):
            self.widgets.rbt_stop.set_active( True )
            return

        # set the speed label in active code frame
        if self.stat.spindle_speed == 0:
            speed = self.stat.settings[2]
        else:
            speed = self.stat.spindle_speed
        self.widgets.active_speed_label.set_label( "%.0f" % abs( speed ) )
        self.on_adj_spindle_value_changed( self.widgets.adj_spindle )

    def on_rbt_forward_clicked( self, widget, data = None ):
        if widget.get_active():
            widget.set_image( self.widgets.img_forward_on )
            self._set_spindle( "forward" )
        else:
            self.widgets.rbt_forward.set_image( self.widgets.img_forward )

    def on_rbt_reverse_clicked( self, widget, data = None ):
        if widget.get_active():
            widget.set_image( self.widgets.img_reverse_on )
            self._set_spindle( "reverse" )
        else:
            widget.set_image( self.widgets.img_reverse )

    def on_rbt_stop_clicked( self, widget, data = None ):
        if widget.get_active():
            widget.set_image( self.widgets.img_stop_on )
            self._set_spindle( "stop" )
        else:
            self.widgets.rbt_stop.set_image( self.widgets.img_sstop )

    def _set_spindle( self, command ):
        # if we are in estop state, we will have to leave here, otherwise
        # we get an error, that switching spindle off is not allowed with estop
        if self.stat.task_state == linuxcnc.STATE_ESTOP:
            return

        # if we do not check this, we will get an error in auto mode
        if self.stat.task_mode == linuxcnc.MODE_AUTO:
            if self.stat.interp_state == linuxcnc.INTERP_READING or self.stat.interp_state == linuxcnc.INTERP_WAITING:
                if self.stat.spindle_direction > 0:
                    self.widgets.rbt_forward.set_sensitive( True )
                    self.widgets.rbt_reverse.set_sensitive( False )
                    self.widgets.rbt_stop.set_sensitive( False )
                elif self.stat.spindle_direction < 0:
                    self.widgets.rbt_forward.set_sensitive( False )
                    self.widgets.rbt_reverse.set_sensitive( True )
                    self.widgets.rbt_stop.set_sensitive( False )
                else:
                    self.widgets.rbt_forward.set_sensitive( False )
                    self.widgets.rbt_reverse.set_sensitive( False )
                    self.widgets.rbt_stop.set_sensitive( True )
                return

        rpm = self._check_spindle_range()
        # as the commanded value will be multiplied with speed override,
        # we take care of that but we have to check for speed override 
        # to not be zero to avoid division by zero error
        try:
            rpm_out = rpm / self.stat.spindlerate
        except:
            rpm_out = 0
        self.widgets.lbl_spindle_act.set_label( "S %s" % int( rpm ) )

        if command == "stop":
            self.command.spindle( 0 )
            self.widgets.lbl_spindle_act.set_label( "S 0" )
        if command == "forward":
            self.command.spindle( 1, rpm_out )
        elif command == "reverse":
            self.command.spindle( -1, rpm_out )
        else:
            print( _( "Something went wrong, we have an unknown spindle widget" ) )

    def _check_spindle_range( self ):
        rpm = ( self.stat.settings[2] )
        if rpm == 0:
            rpm = abs( self.spindle_start_rpm )

        spindle_override = self.widgets.adj_spindle.get_value() / 100
        real_spindle_speed = rpm * spindle_override

        if real_spindle_speed > self.max_spindle_rev:
            real_spindle_speed = self.max_spindle_rev
        elif real_spindle_speed < self.min_spindle_rev:
            real_spindle_speed = self.min_spindle_rev
        return real_spindle_speed

    def on_btn_spindle_100_clicked( self, widget, data = None ):
        self.widgets.adj_spindle.set_value( 100 )

    def on_adj_spindle_value_changed( self, widget, data = None ):
        if not self.initialized:
            return
        # this is in a try except, because on initializing the window the values are still zero
        # so we would get an division / zero error
        real_spindle_speed = 0
        try:
            if not abs( self.stat.settings[2] ):
                if self.widgets.rbt_forward.get_active() or self.widgets.rbt_reverse.get_active():
                    speed = self.stat.spindle_speed
                else:
                    speed = 0
            else:
                speed = abs( self.stat.spindle_speed )
            spindle_override = widget.get_value() / 100
            real_spindle_speed = speed * spindle_override
            if real_spindle_speed > self.max_spindle_rev:
                value_to_set = widget.get_value() / ( real_spindle_speed / self.max_spindle_rev )
                widget.set_value( value_to_set )
                real_spindle_speed = self.max_spindle_rev
            elif real_spindle_speed < self.min_spindle_rev:
                value_to_set = widget.get_value() / ( real_spindle_speed / self.min_spindle_rev )
                widget.set_value( value_to_set )
                real_spindle_speed = self.min_spindle_rev
            else:
                value_to_set = spindle_override * 100
            self.command.spindleoverride( value_to_set / 100 )
        except:
            pass
        self.widgets.lbl_spindle_act.set_text( "S %d" % real_spindle_speed )

    def on_adj_start_spindle_RPM_value_changed( self, widget, data = None ):
        self.spindle_start_rpm = widget.get_value()
        self.prefs.putpref( "spindle_start_rpm", self.spindle_start_rpm, float )

    def on_adj_spindle_bar_min_value_changed( self, widget, data = None ):
        self.min_spindle_rev = widget.get_value()
        self.prefs.putpref( "spindle_bar_min", self.min_spindle_rev, float )
        self.widgets.spindle_feedback_bar.set_property( "min", self.min_spindle_rev )

    def on_adj_spindle_bar_max_value_changed( self, widget, data = None ):
        self.max_spindle_rev = widget.get_value()
        self.prefs.putpref( "spindle_bar_max", self.max_spindle_rev, float )
        self.widgets.spindle_feedback_bar.set_property( "max", self.max_spindle_rev )

# =========================================================
# Coolant an mist coolant button
    def on_tbtn_flood_toggled( self, widget, data = None ):
        if self.stat.flood and self.widgets.tbtn_flood.get_active():
            return
        elif not self.stat.flood and not self.widgets.tbtn_flood.get_active():
            return
        elif self.widgets.tbtn_flood.get_active():
            self.widgets.tbtn_flood.set_image( self.widgets.img_coolant_on )
            self.command.flood( linuxcnc.FLOOD_ON )
        else:
            self.widgets.tbtn_flood.set_image( self.widgets.img_coolant_off )
            self.command.flood( linuxcnc.FLOOD_OFF )

    def on_tbtn_mist_toggled( self, widget, data = None ):
        if self.stat.mist and self.widgets.tbtn_mist.get_active():
            return
        elif not self.stat.mist and not self.widgets.tbtn_mist.get_active():
            return
        elif self.widgets.tbtn_mist.get_active():
            self.widgets.tbtn_mist.set_image( self.widgets.img_mist_on )
            self.command.mist( linuxcnc.MIST_ON )
        else:
            self.widgets.tbtn_mist.set_image( self.widgets.img_mist_off )
            self.command.mist( linuxcnc.MIST_OFF )

# =========================================================
# feed stuff
    def on_adj_feed_value_changed( self, widget, data = None ):
        if not self.initialized:
            return
        self.command.feedrate( widget.get_value() / 100 )
        self.widgets.adj_max_vel.set_value( float( self.widgets.adj_max_vel.upper * widget.get_value() / 100 ) )

    def on_btn_feed_100_clicked( self, widget, data = None ):
        self.widgets.adj_feed.set_value( 100 )

    def on_adj_max_vel_value_changed( self, widget, data = None ):
        if not self.initialized:
            return
        value = widget.get_value() / 60
        self.command.maxvel( value * ( 1 / self.faktor ) )

    # this are the MDI thinks we need
    def on_btn_delete_clicked( self, widget, data = None ):
        message = _( "Do you really want to delete the MDI history?\n" )
        message += _( "this will not delete the MDI History file, but will\n" )
        message += _( "delete the listbox entries for this session" )
        result = dialogs.yesno_dialog( self, message, _( "Attention!!" ) )
        if result:
            self.widgets.hal_mdihistory.model.clear()

    def on_tbtn_use_screen2_toggled( self, widget, data = None ):
        self.prefs.putpref( "use_screen2", widget.get_active(), bool )
        if widget.get_active():
            self.widgets.window2.show()
            if self.widgets.rbtn_window.get_active():
                try:
                    pos = self.widgets.window1.get_position()
                    size = self.widgets.window1.get_size()
                    left = pos[0] + size[0]
                    self.widgets.window2.move( left, pos[1] )
                except:
                    pass
        else:
            self.widgets.window2.hide()

    def on_btn_show_kbd_clicked( self, widget, data = None ):
        # if the image is img_brake macro, we want to interupt the running macro
        if self.widgets.btn_show_kbd.get_image() == self.widgets.img_brake_macro:
            self.command.abort()
            for btn in self.macrobuttons:
                btn.set_sensitive( True )
            if self.onboard:
                self.widgets.btn_show_kbd.set_image( self.widgets.img_keyboard )
                self.widgets.btn_show_kbd.set_property( "tooltip-text", _( "This button will show or hide the keyboard" ) )
            else:
                self.widgets.btn_show_kbd.set_sensitive(False)
                
        elif self.widgets.ntb_info.get_current_page() == 1:
            self.widgets.ntb_info.set_current_page( 0 )
        else:
            self.widgets.ntb_info.set_current_page( 1 )
        # special case if we are in edit mode
        if self.widgets.ntb_button.get_current_page() == 6:
            if self.widgets.ntb_info.get_visible():
                self.widgets.box_info.set_size_request( -1, 50 )
                self.widgets.ntb_info.hide()
            else:
                self.widgets.box_info.set_size_request( -1, 250 )
                self.widgets.ntb_info.show()

    def on_ntb_info_switch_page( self, widget, page, page_num, data = None ):
        if self.stat.task_mode == linuxcnc.MODE_MDI:
            self.widgets.hal_mdihistory.entry.grab_focus()
        elif self.stat.task_mode == linuxcnc.MODE_AUTO:
            self.widgets.gcode_view.grab_focus()

    # Three back buttons to be able to leave notebook pages
    # All use the same callback offset
    def on_btn_back_clicked( self, widget, data = None ):
        if self.widgets.ntb_button.get_current_page() == 6:  # edit mode, go back to auto_buttons
            self.widgets.ntb_button.set_current_page( 2 )
            if self.widgets.tbtn_fullsize_preview1.get_active():
                self.widgets.vbx_jog.set_visible(False)
        elif self.widgets.ntb_button.get_current_page() == 8:  # File selection mode
            self.widgets.ntb_button.set_current_page( 2 )
        else:  # else we go to main button on manual
            self.widgets.ntb_button.set_current_page( 0 )
            self.widgets.ntb_main.set_current_page( 0 )
            self.widgets.ntb_preview.set_current_page( 0 )

    # The offset settings, set to zero
    def on_btn_touch_clicked( self, widget, data = None ):
        self.widgets.ntb_button.set_current_page( 4 )
        self._show_offset_tab( True )
        if self.widgets.rbtn_show_preview.get_active():
            self.widgets.ntb_preview.set_current_page( 0 )

    def on_tbtn_edit_offsets_toggled( self, widget, data = None ):
        state = widget.get_active()
        self.widgets.offsetpage1.edit_button.set_active( state )
        widgetlist = ["btn_zero_x", "btn_zero_y", "btn_zero_z", "btn_set_value_x", "btn_set_value_y",
                      "btn_set_value_z", "btn_set_selected", "ntb_jog", "btn_set_selected", "btn_zero_g92"
        ]
        self._sensitize_widgets( widgetlist, not state )

        if state:
            self.widgets.ntb_preview.set_current_page( 1 )
        else:
            self.widgets.ntb_preview.set_current_page( 0 )

        # we have to replace button calls in our list to make all hardware button
        # activate the correct button call
        if state and self.widgets.chk_use_tool_measurement.get_active():
            self.widgets.btn_zero_g92.show()
            self.widgets.btn_block_height.hide()
            self._replace_list_item( 4, "btn_block_height", "btn_zero_g92" )
        elif not state and self.widgets.chk_use_tool_measurement.get_active():
            self.widgets.btn_zero_g92.hide()
            self.widgets.btn_block_height.show()
            self._replace_list_item( 4, "btn_zero_g92", "btn_block_height" )

        if not state:  # we must switch back to manual mode, otherwise jogging is not possible
            self.command.mode( linuxcnc.MODE_MANUAL )
            self.command.wait_complete()

        # show virtual keyboard?
        if state and self.widgets.chk_use_kb_on_offset.get_active():
            self.widgets.ntb_info.set_current_page( 1 )
            self.widgets.ntb_preview.set_current_page( 1 )

    def on_btn_zero_g92_clicked( self, widget, data = None ):
        self.command.mode( linuxcnc.MODE_MDI )
        self.command.wait_complete()
        self.command.mdi( "G92.1" )
        self.command.mode( linuxcnc.MODE_MANUAL )
        self.command.wait_complete()
        self.widgets.btn_touch.emit( "clicked" )

# TODO: what to do when there are more axis?
# all over one handler with "G10 L20 P0 %s%f"%(axis,value)
    def on_btn_zero_x_clicked( self, widget, data = None ):
        self.command.mode( linuxcnc.MODE_MDI )
        self.command.wait_complete()
        self.command.mdi( "G10 L20 P0 X0" )
        self.widgets.hal_action_reload.emit( "activate" )
        self.command.mode( linuxcnc.MODE_MANUAL )
        self.command.wait_complete()

    def on_btn_zero_y_clicked( self, widget, data = None ):
        self.command.mode( linuxcnc.MODE_MDI )
        self.command.wait_complete()
        self.command.mdi( "G10 L20 P0 Y0" )
        self.widgets.hal_action_reload.emit( "activate" )
        self.command.mode( linuxcnc.MODE_MANUAL )
        self.command.wait_complete()

    def on_btn_zero_z_clicked( self, widget, data = None ):
        self.command.mode( linuxcnc.MODE_MDI )
        self.command.wait_complete()
        self.command.mdi( "G10 L20 P0 Z0" )
        self.widgets.hal_action_reload.emit( "activate" )
        self.command.mode( linuxcnc.MODE_MANUAL )
        self.command.wait_complete()

    def on_btn_set_value_clicked( self, widget, data = None ):
        if widget == self.widgets.btn_set_value_x:
            axis = "x"
        elif widget == self.widgets.btn_set_value_y:
            axis = "y"
        elif widget == self.widgets.btn_set_value_z:
            axis = "z"
        else:
            axis = "Unknown"
            message = _( "Offset %s could not be set, because off unknown axis" ) % axis 
            dialogs.warning_dialog(self, _("Wrong offset setting!"), message )
            return
        if self.lathe_mode:
            if self.diameter_mode:
                preset = self.prefs.getpref( "diameter offset_axis_%s" % axis, 0, float )
                offset = dialogs.entry_dialog( self, data = preset, header = _( "Enter value for diameter" ),
                                              label = _( "Set diameter to:" ), integer = False )
            else:
                preset = self.prefs.getpref( "radius offset_axis_%s" % axis, 0, float )
                offset = dialogs.entry_dialog( self, data = preset, header = _( "Enter value for radius" ),
                                              label = _( "Set radius to:" ), integer = False )
        else:
            preset = self.prefs.getpref( "offset_axis_%s" % axis, 0, float )
            offset = dialogs.entry_dialog( self, data = preset, header = _( "Enter value for axis %s" ) % axis,
                                          label = _( "Set axis %s to:" ) % axis, integer = False )
        if offset == "CANCEL":
            return
        elif offset == "ERROR":
            print( _( "Conversion error in btn_set_value" ) )
            dialogs.warning_dialog( self, _( "Conversion error in btn_set_value!" ),
                                   _( "Please enter only numerical values. Values have not been applied" ) )
        else:
            self.command.mode( linuxcnc.MODE_MDI )
            self.command.wait_complete()
            command = "G10 L20 P0 %s%f" % ( axis, offset )
            self.command.mdi( command )
            self.widgets.hal_action_reload.emit( "activate" )
            self.command.mode( linuxcnc.MODE_MANUAL )
            self.command.wait_complete()
            self.prefs.putpref( "offset_axis_%s" % axis, offset, float )
# TODO: End

    def on_btn_set_selected_clicked( self, widget, data = None ):
        system, name = self.widgets.offsetpage1.get_selected()
        if not system:
            message = _( "you did not selected a system to be changed to, so nothing will be changed" )
            dialogs.warning_dialog( self, _( "Important Warning!" ), message )
            return
        if system == self.system_list[self.stat.g5x_index]:
            return
        else:
            self.command.mode( linuxcnc.MODE_MDI )
            self.command.wait_complete()
            self.command.mdi( system )
            self.command.mode( linuxcnc.MODE_MANUAL )
            self.command.wait_complete()

    def on_spbtn_probe_height_value_changed( self, widget, data = None ):
        self.halcomp["probeheight"] = widget.get_value()
        self.prefs.putpref( "probeheight", widget.get_value(), float )

    def on_spbtn_search_vel_value_changed( self, widget, data = None ):
        self.halcomp["searchvel"] = widget.get_value()
        self.prefs.putpref( "searchvel", widget.get_value(), float )

    def on_spbtn_probe_vel_value_changed( self, widget, data = None ):
        self.halcomp["probevel"] = widget.get_value()
        self.prefs.putpref( "probevel", widget.get_value(), float )

    def on_chk_use_tool_measurement_toggled( self, widget, data = None ):
        if widget.get_active():
            self.widgets.frm_probe_pos.set_sensitive( True )
            self.widgets.frm_probe_vel.set_sensitive( True )
            self.halcomp["toolmeasurement"] = True
            self.halcomp["searchvel"] = self.widgets.spbtn_search_vel.get_value()
            self.halcomp["probevel"] = self.widgets.spbtn_probe_vel.get_value()
            self.halcomp["probeheight"] = self.widgets.spbtn_probe_height.get_value()
        else:
            self.widgets.frm_probe_pos.set_sensitive( False )
            self.widgets.frm_probe_vel.set_sensitive( False )
            self.halcomp["toolmeasurement"] = False
            self.halcomp["searchvel"] = 0.0
            self.halcomp["probevel"] = 0.0
            self.halcomp["probeheight"] = 0.0
        self.prefs.putpref( "use_toolmeasurement", widget.get_active(), bool )

    def on_chk_hide_axis_4_toggled( self, widget, data = None ):
        if not self.initialized:
            return
        state = widget.get_active()
        self.prefs.putpref( "hide_axis_4", state, bool )
        self._hide_axis_4( state )
        self._init_offsetpage()
        self._init_tooleditor()

    def on_btn_block_height_clicked( self, widget, data = None ):
        probeheight = self.widgets.spbtn_probe_height.get_value()
        blockheight = dialogs.entry_dialog( self, data = None, header = _( "Enter the block height" ),
                                           label = _( "Block height measured from base table" ), integer = False )

        if blockheight == "CANCEL" or blockheight == "ERROR":
            return
        if blockheight != False or blockheight == 0:
            self.halcomp["blockheight"] = blockheight
            self.halcomp["probeheight"] = probeheight
            self.prefs.putpref( "blockheight", blockheight, float )
            self.prefs.putpref( "probeheight", probeheight, float )
        else:
            self.prefs.putpref( "blockheight", 0.0, float )
            self.prefs.putpref( "probeheight", 0.0, float )
            print( _( "Conversion error in btn_block_height" ) )
            dialogs.warning_dialog( self, _( "Conversion error in btn_block_height!" ),
                                   _( "Please enter only numerical values\nValues have not been applied" ) )

        # set koordinate system to new origin
        origin = self.get_ini_info.get_axis_2_min_limit() + blockheight
        self.command.mode( linuxcnc.MODE_MDI )
        self.command.wait_complete()
        self.command.mdi( "G10 L2 P0 Z%s" % origin )
        self.widgets.hal_action_reload.emit( "activate" )
        self.command.mode( linuxcnc.MODE_MANUAL )
        self.command.wait_complete()

    # choose a theme to aply
    def on_theme_choice_changed( self, widget ):
        theme = widget.get_active_text()
        if theme == None:
            return
        self.prefs.putpref( 'gtk_theme', theme, str )
        settings = gtk.settings_get_default()
        if theme == "Follow System Theme":
            theme = self.default_theme
        settings.set_string_property( "gtk-theme-name", theme, "" )

    def on_rbt_unlock_toggled( self, widget, data = None ):
        if widget.get_active():
            if widget == self.widgets.rbt_use_unlock:
                self.prefs.putpref( "unlock_way", "use", str )
            elif widget == self.widgets.rbt_no_unlock:
                self.prefs.putpref( "unlock_way", "no", str )
            else:
                self.prefs.putpref( "unlock_way", "hal", str )

    def on_rbtn_run_from_line_toggled( self, widget, data = None ):
        if widget.get_active():
            if widget == self.widgets.rbtn_no_run_from_line:
                self.prefs.putpref( "run_from_line", "no_run", str )
                self.widgets.btn_from_line.set_sensitive( False )
            else:  # widget == self.widgets.rbtn_run_from_line:
                self.prefs.putpref( "run_from_line", "run", str )
                self.widgets.btn_from_line.set_sensitive( True )

    def on_chk_use_kb_on_offset_toggled( self, widget, data = None ):
        self.prefs.putpref( "show_keyboard_on_offset", widget.get_active(), bool )

    def on_chk_use_kb_on_tooledit_toggled( self, widget, data = None ):
        self.prefs.putpref( "show_keyboard_on_tooledit", widget.get_active(), bool )

    def on_chk_use_kb_on_edit_toggled( self, widget, data = None ):
        self.prefs.putpref( "show_keyboard_on_edit", widget.get_active(), bool )

    def on_chk_use_kb_on_mdi_toggled( self, widget, data = None ):
        self.prefs.putpref( "show_keyboard_on_mdi", widget.get_active(), bool )

    def on_chk_use_kb_on_file_selection_toggled( self, widget, data = None ):
        self.prefs.putpref( "show_keyboard_on_file_selection", widget.get_active(), bool )

    def on_chk_use_kb_shortcuts_toggled( self, widget, data = None ):
        self.prefs.putpref( "use_keyboard_shortcuts", widget.get_active(), bool )

    def on_rbtn_show_preview_toggled( self, widget, data = None ):
        self.prefs.putpref( "show_preview_on_offset", widget.get_active(), bool )

    def on_adj_scale_max_vel_value_changed( self, widget, data = None ):
        self.prefs.putpref( "scale_max_vel", widget.get_value(), float )
        self.scale_max_vel = widget.get_value()

    def on_adj_scale_jog_vel_value_changed( self, widget, data = None ):
        self.prefs.putpref( "scale_jog_vel", widget.get_value(), float )
        self.scale_jog_vel = widget.get_value()

    def on_adj_scale_feed_override_value_changed( self, widget, data = None ):
        self.prefs.putpref( "scale_feed_override", widget.get_value(), float )
        self.scale_feed_override = widget.get_value()

    def on_adj_scale_spindle_override_value_changed( self, widget, data = None ):
        self.prefs.putpref( "scale_spindle_override", widget.get_value(), float )
        self.scale_spindle_override = widget.get_value()

    def on_rbtn_fullscreen_toggled( self, widget ):
        if widget.get_active():
            self.widgets.window1.fullscreen()
            self.prefs.putpref( "screen1", "fullscreen", str )
        else:
            self.widgets.window1.unfullscreen()

    def on_rbtn_maximized_toggled( self, widget ):
        if widget.get_active():
            self.widgets.window1.maximize()
            self.prefs.putpref( "screen1", "maximized", str )
        else:
            self.widgets.window1.unmaximize()

    def on_rbtn_window_toggled( self, widget ):
        self.widgets.spbtn_x_pos.set_sensitive( widget.get_active() )
        self.widgets.spbtn_y_pos.set_sensitive( widget.get_active() )
        self.widgets.spbtn_width.set_sensitive( widget.get_active() )
        self.widgets.spbtn_height.set_sensitive( widget.get_active() )
        # we have to check also if the window is active, because the button is toggled the first time
        # before the window is shown
        if widget.get_active() and self.widgets.window1.is_active():
            self.widgets.window1.move( self.xpos, self.ypos )
            self.widgets.window1.resize( self.width, self.height )
            self.prefs.putpref( "screen1", "window", str )

    def on_adj_x_pos_value_changed( self, widget, data = None ):
        if not self.initialized:
            return
        value = int( widget.get_value() )
        self.prefs.putpref( "x_pos", value, float )
        self.xpos = value
        self.widgets.window1.move( value, self.ypos )

    def on_adj_y_pos_value_changed( self, widget, data = None ):
        if not self.initialized:
            return
        value = int( widget.get_value() )
        self.prefs.putpref( "y_pos", value, float )
        self.ypos = value
        self.widgets.window1.move( self.xpos, value )

    def on_adj_width_value_changed( self, widget, data = None ):
        if not self.initialized:
            return
        value = int( widget.get_value() )
        self.prefs.putpref( "width", value, float )
        self.width = value
        self.widgets.window1.resize( value, self.height )

    def on_adj_height_value_changed( self, widget, data = None ):
        if not self.initialized:
            return
        value = int( widget.get_value() )
        self.prefs.putpref( "height", value, float )
        self.height = value
        self.widgets.window1.resize( self.width, value )

    def on_adj_dro_size_value_changed( self, widget, data = None ):
        if not self.initialized:
            return
        value = int( widget.get_value() )
        self.prefs.putpref( "dro_size", value, int )
        self.dro_size = value
        self._init_axis_four()

    def on_chk_hide_cursor_toggled( self, widget, data = None ):
        self.prefs.putpref( "hide_cursor", widget.get_active(), bool )
        self.hide_cursor = widget.get_active()
        if widget.get_active():
            self.widgets.window1.window.set_cursor( INVISABLE )
        else:
            self.widgets.window1.window.set_cursor( None )
        self.abs_color = self.prefs.getpref( "abs_color", "blue", str )
        self.rel_color = self.prefs.getpref( "rel_color", "black", str )
        self.dtg_color = self.prefs.getpref( "dtg_color", "yellow", str )
        self.homed_color = self.prefs.getpref( "homed_color", "green", str )
        self.unhomed_color = self.prefs.getpref( "unhomed_color", "red", str )

    def on_rel_colorbutton_color_set( self, widget ):
        color = widget.get_color()
        self.prefs.putpref( 'rel_color', color, str )
        self._change_dro_color( "rel_color", color )
        self.rel_color = str( color )

    def on_abs_colorbutton_color_set( self, widget ):
        color = widget.get_color()
        self.prefs.putpref( 'abs_color', widget.get_color(), str )
        self._change_dro_color( "abs_color", color )
        self.abs_color = str( color )

    def on_dtg_colorbutton_color_set( self, widget ):
        color = widget.get_color()
        self.prefs.putpref( 'dtg_color', widget.get_color(), str )
        self._change_dro_color( "dtg_color", color )
        self.dtg_color = str( color )

    def on_homed_colorbtn_color_set( self, widget ):
        color = widget.get_color()
        self.prefs.putpref( 'homed_color', widget.get_color(), str )
        self._change_dro_color( "homed_color", color )
        self.homed_color = str( color )

    def on_unhomed_colorbtn_color_set( self, widget ):
        color = widget.get_color()
        self.prefs.putpref( 'unhomed_color', widget.get_color(), str )
        self._change_dro_color( "unhomed_color", color )
        self.unhomed_color = str( color )

    def on_file_to_load_chooser_file_set( self, widget ):
        self.prefs.putpref( "open_file", widget.get_filename(), str )

    def on_jump_to_dir_chooser_file_set( self, widget, data = None ):
        path = widget.get_filename()
        self.prefs.putpref( "jump_to_dir", path, str )
        self.widgets.IconFileSelection1.set_property( "jump_to_dir", path )

    def on_grid_size_value_changed( self, widget, data = None ):
        self.widgets.gremlin.set_property( 'grid_size', widget.get_value() )
        self.prefs.putpref( 'grid_size', widget.get_value(), float )

    def on_tbtn_log_actions_toggled( self, widget, data = None ):
        self.prefs.putpref( "log_actions", widget.get_active(), bool )

    def on_chk_show_dro_toggled( self, widget, data = None ):
        self.widgets.gremlin.set_property( "metric_units", self.widgets.Combi_DRO_x.metric_units )
        self.widgets.gremlin.set_property( "enable_dro", widget.get_active() )
        self.prefs.putpref( "enable_dro", widget.get_active(), bool )
        self.widgets.chk_show_offsets.set_sensitive( widget.get_active() )
        self.widgets.chk_show_dtg.set_sensitive( widget.get_active() )

    def on_chk_show_dtg_toggled( self, widget, data = None ):
        self.widgets.gremlin.set_property( "show_dtg", widget.get_active() )
        self.prefs.putpref( "show_dtg", widget.get_active(), bool )

    def on_chk_show_offsets_toggled( self, widget, data = None ):
        self.widgets.gremlin.show_offsets = widget.get_active()
        self.prefs.putpref( "show_offsets", widget.get_active(), bool )

    def on_cmb_mouse_button_mode_changed( self, widget ):
        index = widget.get_active()
        self.widgets.gremlin.set_property( "mouse_btn_mode", index )
        self.prefs.putpref( "mouse_btn_mode", index, int )

# =========================================================
# tool stuff
    def on_btn_tool_clicked( self, widget, data = None ):
        if self.widgets.tbtn_fullsize_preview.get_active():
            self.widgets.tbtn_fullsize_preview.set_active( False )
        self.widgets.ntb_button.set_current_page( 7 )
        self._show_tooledit_tab( True )

    # Here we create a manual tool change dialog
    def on_tool_change( self, widget ):
        change = self.halcomp['toolchange-change']
        toolnumber = self.halcomp['toolchange-number']
        if change:
            # if toolnumber = 0 we will get an error because we will not be able to get
            # any tooldescription, so we avoid that case
            if toolnumber == 0:
                message = _( "Please remove the mounted tool and press OK when done" )
            else:
                tooldescr = self.widgets.tooledit1.get_toolinfo( toolnumber )[16]
                message = _( "Please change to tool\n\n# {0:d}     {1}\n\n then click OK." ).format( toolnumber, tooldescr )
            result = dialogs.warning_dialog( self, message, title = _( "Manual Toolchange" ) )
            if result:
                self.halcomp["toolchange-changed"] = True
            else:
                print"toolchange abort", self.stat.tool_in_spindle, self.halcomp['toolchange-number']
                self.command.abort()
                self.halcomp['toolchange-number'] = self.stat.tool_in_spindle
                self.halcomp['toolchange-change'] = False
                self.halcomp['toolchange-changed'] = True
                message = _( "Tool Change has been aborted!\n" )
                message += _( "The old tool will remain set!" )
                dialogs.warning_dialog( self, message )
        else:
            self.halcomp['toolchange-changed'] = False

    def on_btn_delete_tool_clicked( self, widget, data = None ):
        self.tooledit_btn_delete_tool.emit( "clicked" )

    def on_btn_add_tool_clicked( self, widget, data = None ):
        self.tooledit_btn_add_tool.emit( "clicked" )

    def on_btn_reload_tooltable_clicked( self, widget, data = None ):
        self.tooledit_btn_reload_tool.emit( "clicked" )

    def on_btn_apply_tool_changes_clicked( self, widget, data = None ):
        self.tooledit_btn_apply_tool.emit( "clicked" )
        tool = self.widgets.tooledit1.get_selected_tool()

    def on_btn_tool_touchoff_clicked( self, widget, data = None ):
        if not self.widgets.tooledit1.get_selected_tool():
            message = _( "No or more than one tool selected in tool table" )
            message += _( "Please select only one tool in the table" )
            print( message )
            dialogs.warning_dialog( self, _( "Warning Tool Touch off not possible!" ), message )
            return

        if self.widgets.tooledit1.get_selected_tool() != self.stat.tool_in_spindle:
            message = _( "you can not touch of a tool, witch is not mounted in the spindle" )
            message += _( "your selection has been reseted to the tool in spindle" )
            print( message )
            dialogs.warning_dialog( self, _( "Warning Tool Touch off not possible!" ), message )
            self.widgets.tooledit1.reload( self )
            self.widgets.tooledit1.set_selected_tool( self.stat.tool_in_spindle )
            return

        if "G41" in self.active_gcodes or "G42" in self.active_gcodes:
            message = _( "Tool touch off is not possible with cutter radius compensation switched on!\n" )
            message += _( "Please emit an G40 before tool touch off" )
            print( message )
            dialogs.warning_dialog( self, _( "Warning Tool Touch off not possible!" ), message )
            return

        if widget == self.widgets.btn_tool_touchoff_x:
            axis = "x"
        elif widget == self.widgets.btn_tool_touchoff_z:
            axis = "z"
        else:
            dialogs.warning_dialog( self, _( "Real big error!" ),
                                   _( "You managed to come to a place that is not possible in on_btn_tool_touchoff" ) )
            return

        value = dialogs.entry_dialog( self, data = None,
                                     header = _( "Enter value for axis %s to set:" ) % axis.upper(),
                                     label = _( "Set parameter of tool {0:d} and axis {1} to:" ).format( 
                                         self.stat.tool_in_spindle, axis.upper() ),
                                     integer = False )

        if value == "ERROR":
            message = _( "Conversion error because of wrong entry for touch off axis %s" ) % axis.upper()
            print( message )
            dialogs.warning_dialog( self, _( "Conversion error !" ), message )
            return
        elif value == "CANCEL":
            return
        else:
            command = "G10 L10 P%d %s%f" % ( self.stat.tool_in_spindle, axis, value )
            self.command.mode( linuxcnc.MODE_MDI )
            self.command.wait_complete()
            self.command.mdi( command )
            self.command.wait_complete()
            if "G43" in self.active_gcodes:
                self.command.mdi( "G43" )
                self.command.wait_complete()
            self.command.mode( linuxcnc.MODE_MANUAL )
            self.command.wait_complete()

    # select a tool entering a number
    def on_btn_select_tool_by_no_clicked( self, widget, data = None ):
        value = dialogs.entry_dialog( self, data = None, header = _( "Enter the tool number as integer " ),
                                     label = _( "Select the tool to change" ), integer = True )
        if value == "ERROR":
            message = _( "Conversion error because of wrong entry for tool number\n" )
            message += _( "enter only integer nummbers" )
            print( message )
            dialogs.warning_dialog( self, _( "Conversion error !" ), message )
            return
        elif value == "CANCEL":
            return
        elif int( value ) == self.stat.tool_in_spindle:
            message = _( "Selected tool is already in spindle, no change needed." )
            dialogs.warning_dialog( self, _( "Important Warning!" ), message )
            return
        else:
            self.tool_change = True
            self.command.mode( linuxcnc.MODE_MDI )
            self.command.wait_complete()
            command = "T%s M6" % int( value )
            self.command.mdi( command )

    # set tool with M61 Q? or with T? M6
    def on_btn_selected_tool_clicked( self, widget, data = None ):
        tool = self.widgets.tooledit1.get_selected_tool()
        if tool == None:
            message = _( "you selected no or more than one tool, the tool selection must be unique" )
            dialogs.warning_dialog( self, _( "Important Warning!" ), message )
            return
        if tool == self.stat.tool_in_spindle:
            message = _( "Selected tool is already in spindle, no change needed." )
            dialogs.warning_dialog( self, _( "Important Warning!" ), message )
            return
        if tool or tool == 0:
            self.tool_change = True
            tool = int( tool )
            self.command.mode( linuxcnc.MODE_MDI )
            self.command.wait_complete()

            if widget == self.widgets.btn_change_tool:
                command = "T%s M6" % tool
            else:
                command = "M61 Q%s" % tool
            self.command.mdi( command )
        else:
            message = _( "Could not understand the entered tool number. Will not change anything" )
            dialogs.warning_dialog( self, _( "Important Warning!" ), message )

# =========================================================
# gremlin relevant calls
    def on_rbt_view_p_toggled( self, widget, data = None ):
        if self.widgets.rbt_view_p.get_active():
            self.widgets.gremlin.set_property( "view", "p" )
        self.prefs.putpref( "gremlin_view", "rbt_view_p", str )

    def on_rbt_view_x_toggled( self, widget, data = None ):
        if self.widgets.rbt_view_x.get_active():
            self.widgets.gremlin.set_property( "view", "x" )
        self.prefs.putpref( "gremlin_view", "rbt_view_x", str )

    def on_rbt_view_y_toggled( self, widget, data = None ):
        if self.widgets.rbt_view_y.get_active():
            self.widgets.gremlin.set_property( "view", "y" )
        self.prefs.putpref( "gremlin_view", "rbt_view_y", str )

    def on_rbt_view_z_toggled( self, widget, data = None ):
        if self.widgets.rbt_view_z.get_active():
            self.widgets.gremlin.set_property( "view", "z" )
        self.prefs.putpref( "gremlin_view", "rbt_view_z", str )

    def on_rbt_view_y2_toggled( self, widget, data = None ):
        if self.widgets.rbt_view_y2.get_active():
            self.widgets.gremlin.set_property( "view", "y2" )
        self.prefs.putpref( "gremlin_view", "rbt_view_y2", str )

    def on_btn_zoom_in_clicked( self, widget, data = None ):
        self.widgets.gremlin.zoom_in()

    def on_btn_zoom_out_clicked( self, widget, data = None ):
        self.widgets.gremlin.zoom_out()

    def on_btn_delete_view_clicked( self, widget, data = None ):
        self.widgets.gremlin.clear_live_plotter()

    def on_tbtn_view_dimension_toggled( self, widget, data = None ):
        self.widgets.gremlin.set_property( "show_extents_option", widget.get_active() )
        self.prefs.putpref( "view_dimension", self.widgets.tbtn_view_dimension.get_active(), bool )

    def on_tbtn_view_tool_path_toggled( self, widget, data = None ):
        self.widgets.gremlin.set_property( "show_live_plot", widget.get_active() )
        self.prefs.putpref( "view_tool_path", self.widgets.tbtn_view_tool_path.get_active(), bool )

    def on_gremlin_line_clicked( self, widget, line ):
        self.widgets.gcode_view.set_line_number( line )

    def on_btn_load_clicked( self, widget, data = None ):
        print("load clicked")
        self.widgets.ntb_button.set_current_page( 8 )
        self.widgets.ntb_preview.set_current_page( 3 )
        self.widgets.tbtn_fullsize_preview.set_active( True )
        self._show_iconview_tab( True )
        self.widgets.IconFileSelection1.refresh_filelist()
        self.widgets.IconFileSelection1.iconView.grab_focus()
        self.gcodeerror = ""

    def on_btn_sel_next_clicked( self, widget, data = None ):
        self.widgets.IconFileSelection1.btn_sel_next.emit( "clicked" )

    def on_btn_sel_prev_clicked( self, widget, data = None ):
        self.widgets.IconFileSelection1.btn_sel_prev.emit( "clicked" )

    def on_btn_home_clicked( self, widget, data = None ):
        self.widgets.IconFileSelection1.btn_home.emit( "clicked" )

    def on_btn_jump_to_clicked( self, widget, data = None ):
        self.widgets.IconFileSelection1.btn_jump_to.emit( "clicked" )

    def on_btn_dir_up_clicked( self, widget, data = None ):
        self.widgets.IconFileSelection1.btn_dir_up.emit( "clicked" )

    def on_btn_select_clicked( self, widget, data = None ):
        self.widgets.IconFileSelection1.btn_select.emit( "clicked" )

    def on_IconFileSelection1_selected( self, widget, path = None ):
        if path:
            self.widgets.hal_action_open.load_file( path )
            self.widgets.ntb_preview.set_current_page( 0 )
            self.widgets.tbtn_fullsize_preview.set_active( False )
            self.widgets.ntb_button.set_current_page( 2 )
            self._show_iconview_tab( False )

    def on_IconFileSelection1_sensitive( self, widget, buttonname, state ):
        self.widgets[buttonname].set_sensitive(state)

    def on_IconFileSelection1_exit( self, widget ):
        self.widgets.ntb_preview.set_current_page( 0 )
        self.widgets.tbtn_fullsize_preview.set_active( False )
        self._show_iconview_tab( False )

    # edit a program or make a new one
    def on_btn_edit_clicked( self, widget, data = None ):
        self.widgets.ntb_button.set_current_page( 6 )
        self.widgets.ntb_preview.hide()
        self.widgets.hbox_dro.hide()
        width = self.widgets.window1.allocation.width
        width -= self.widgets.vbtb_main.allocation.width
        width -= self.widgets.box_right.allocation.width
        width -= self.widgets.box_left.allocation.width
        self.widgets.vbx_jog.set_size_request( width, -1 )
        if not self.widgets.vbx_jog.get_visible():
            self.widgets.vbx_jog.set_visible(True)
        self.widgets.gcode_view.set_sensitive( True )
        self.widgets.gcode_view.grab_focus()
        if self.widgets.chk_use_kb_on_edit.get_active():
            self.widgets.ntb_info.set_current_page( 1 )
            self.widgets.box_info.set_size_request( -1, 250 )
        else:
            self.widgets.ntb_info.hide()
            self.widgets.box_info.set_size_request( -1, 50 )
        self.widgets.tbl_search.show()
        self.gcodeerror = ""

    # Search and replace handling in edit mode
    # undo changes while in edit mode
    def on_btn_undo_clicked( self, widget, data = None ):
        self.widgets.gcode_view.undo()

    # search backward while in edit mode
    def on_btn_search_back_clicked( self, widget, data = None ):
        self.widgets.gcode_view.text_search( direction = False,
                                            mixed_case = self.widgets.chk_ignore_case.get_active(),
                                            text = self.widgets.search_entry.get_text() )

    # search forward while in edit mode
    def on_btn_search_forward_clicked( self, widget, data = None ):
        self.widgets.gcode_view.text_search( direction = True,
                                            mixed_case = self.widgets.chk_ignore_case.get_active(),
                                            text = self.widgets.search_entry.get_text() )

    # replace text in edit mode
    def on_btn_replace_clicked( self, widget, data = None ):
        self.widgets.gcode_view.replace_text_search( direction = True,
                                                    mixed_case = self.widgets.chk_ignore_case.get_active(),
                                                    text = self.widgets.search_entry.get_text(),
                                                    re_text = self.widgets.replace_entry.get_text(),
                                                    replace_all = self.widgets.chk_replace_all.get_active() )

    # redo changes while in edit mode
    def on_btn_redo_clicked( self, widget, data = None ):
        self.widgets.gcode_view.redo()

    # if we leave the edit mode, we will have to show all widgets again
    def on_ntb_button_switch_page( self, *args ):
        if self.widgets.ntb_preview.get_current_page() == 0:  # preview tab is active,
            # check if offset tab is visible, if so we have to hide it
            page = self.widgets.ntb_preview.get_nth_page( 1 )
            if page.get_visible():
                self._show_offset_tab( False )
        elif self.widgets.ntb_preview.get_current_page() == 1:
            self._show_offset_tab( False )
        elif self.widgets.ntb_preview.get_current_page() == 2:
            self._show_tooledit_tab( False )
        elif self.widgets.ntb_preview.get_current_page() == 3:
            self._show_iconview_tab( False )

        if self.widgets.tbtn_fullsize_preview.get_active():
            self.widgets.tbtn_fullsize_preview.set_active( False )
        if self.widgets.ntb_button.get_current_page() == 6 or self.widgets.ntb_preview.get_current_page() == 3:
            self.widgets.ntb_preview.show()
            self.widgets.hbox_dro.show()
            self.widgets.vbx_jog.set_size_request( 360, -1 )
            self.widgets.gcode_view.set_sensitive( 0 )
            self.widgets.btn_save.set_sensitive( True )
            self.widgets.hal_action_reload.emit( "activate" )
            self.widgets.ntb_info.set_current_page( 0 )
            self.widgets.ntb_info.show()
            self.widgets.box_info.set_size_request( -1, 200 )
            self.widgets.tbl_search.hide()

    # make a new file
    def on_btn_new_clicked( self, widget, data = None ):
        tempfilename = os.path.join( _TEMPDIR, "temp.ngc" )
        content = self.get_ini_info.get_RS274_start_code()
        if content == None:
            content = " "
        content += "\n\n\n\nM2"
        gcodefile = open( tempfilename, "w" )
        gcodefile.write( content )
        gcodefile.close()
        if self.widgets.lbl_program.get_label() == tempfilename:
            self.widgets.hal_action_reload.emit( "activate" )
        else:
            self.widgets.hal_action_open.load_file( tempfilename )
            # self.command.program_open(tempfilename)
        self.widgets.gcode_view.grab_focus()
        self.widgets.btn_save.set_sensitive( False )

    def on_tbtn_optional_blocks_toggled( self, widget, data = None ):
        self.command.set_block_delete( widget.get_active() )
        self.prefs.putpref( "blockdel", widget.get_active(), bool )
        self.widgets.hal_action_reload.emit( "activate" )


    def on_tbtn_optional_stops_toggled( self, widget, data = None ):
        self.command.set_optional_stop( widget.get_active() )
        self.prefs.putpref( "opstop", widget.get_active(), bool )

    # this can not be done with the status widget,
    # because it will not emit a RESUME signal
    def on_tbtn_pause_toggled( self, widget, data = None ):
        widgetlist = ["rbt_forward", "rbt_reverse", "rbt_stop"]
        self._sensitize_widgets( widgetlist, widget.get_active() )

    def on_btn_stop_clicked( self, widget, data = None ):
        print( "stop clicked" )
        self.start_line = 0
        self.widgets.gcode_view.set_line_number( 0 )
        self.widgets.tbtn_pause.set_active( False )

    def on_btn_run_clicked( self, widget, data = None ):
        self.command.auto( linuxcnc.AUTO_RUN, self.start_line )

    def on_btn_from_line_clicked( self, widget, data = None ):
        dialogs.restart_dialog( self )

    def on_change_sound( self, widget, sound = None ):
        file = widget.get_filename()
        if file:
            if widget == self.widgets.audio_error_chooser:
                self.error_sound = file
                self.prefs.putpref( "audio_error", file, str )
            else:
                self.alert_sound = file
                self.prefs.putpref( "audio_alert", file, str )

# =========================================================
# Hal Pin Handling Start

    def _on_counts_changed( self, pin, widget ):
        if not self.initialized:
            return
        difference = 0
        counts = pin.get()
        if self.halcomp["feed-override.count-enable"]:
            if widget == "adj_feed":
                difference = ( counts - self.fo_counts ) * self.scale_feed_override
                self.fo_counts = counts
                self._check_counts( counts )
        if self.halcomp["spindle-override.count-enable"]:
            if widget == "adj_spindle":
                difference = ( counts - self.so_counts ) * self.scale_spindle_override
                self.so_counts = counts
                self._check_counts( counts )
        if self.halcomp["jog-speed.count-enable"]:
            if widget == "adj_jog_vel":
                difference = ( counts - self.jv_counts ) * self.scale_jog_vel
                if self.widgets.tbtn_turtle_jog.get_active():
                    difference = difference / self.turtle_jog_factor
                self.jv_counts = counts
                self._check_counts( counts )
        if self.halcomp["max-velocity.count-enable"]:
            if widget == "adj_max_vel":
                difference = ( counts - self.mv_counts ) * self.scale_max_vel
                self.mv_counts = counts
                self._check_counts( counts )
        if not self.halcomp["feed-override.count-enable"] and not self.halcomp["spindle-override.count-enable"] and not self.halcomp["jog-speed.count-enable"] and not self.halcomp["max-velocity.count-enable"]:
            self._check_counts( counts )

        val = self.widgets[widget].get_value() + difference
        if val < 0:
            val = 0
        if difference != 0:
            self.widgets[widget].set_value( val )

    def _check_counts( self, counts ):
        # as we do not know how the user did connect the jog wheels, we have to check all
        # possibilitys. Does he use only one jog wheel and a selection switch or do he use
        # a mpg for each slider or one for speeds and one for override, or ??
        if self.halcomp["feed-override.counts"] == self.halcomp["spindle-override.counts"]:
            if self.halcomp["feed-override.count-enable"] and self.halcomp["spindle-override.count-enable"]:
                return
            self.fo_counts = self.so_counts = counts
        if self.halcomp["feed-override.counts"] == self.halcomp["jog-speed.counts"]:
            if self.halcomp["feed-override.count-enable"] and self.halcomp["jog-speed.count-enable"]:
                return
            self.fo_counts = self.jv_counts = counts
        if self.halcomp["feed-override.counts"] == self.halcomp["max-velocity.counts"]:
            if self.halcomp["feed-override.count-enable"] and self.halcomp["max-velocity.count-enable"]:
                return
            self.fo_counts = self.mv_counts = counts
        if self.halcomp["spindle-override.counts"] == self.halcomp["jog-speed.counts"]:
            if self.halcomp["spindle-override.count-enable"] and self.halcomp["jog-speed.count-enable"]:
                return
            self.so_counts = self.jv_counts = counts
        if self.halcomp["spindle-override.counts"] == self.halcomp["max-velocity.counts"]:
            if self.halcomp["spindle-override.count-enable"] and self.halcomp["max-velocity.count-enable"]:
                return
            self.so_counts = self.mv_counts = counts
        if self.halcomp["jog-speed.counts"] == self.halcomp["max-velocity.counts"]:
            if self.halcomp["jog-speed.count-enable"] and self.halcomp["max-velocity.count-enable"]:
                return
            self.jv_counts = self.mv_counts = counts

    def _on_analog_value_changed( self, pin, widget ):
        if not self.initialized:
            return
        if widget == "adj_feed" and not self.halcomp["feed-override.analog-enable"]:
            return
        if widget == "adj_spindle" and not self.halcomp["spindle-override.analog-enable"]:
            return
        if widget == "adj_jog_vel" and not self.halcomp["jog-speed.analog-enable"]:
            return
        if widget == "adj_max_vel" and not self.halcomp["max-velocity.analog-enable"]:
            return
        percentage = pin.get()
        if percentage > 1.0:
            percentage = 1.0
        range = self.widgets[widget].upper - self.widgets[widget].lower
        try:  # otherwise a value of 0.0 would give an error
            value = self.widgets[widget].lower + ( range * percentage )
        except:
            value = 0
        self.widgets[widget].set_value( value )

    def _on_unlock_settings_changed( self, pin ):
        if not self.widgets.rbt_hal_unlock.get_active():
            return
        self.widgets.tbtn_setup.set_sensitive( pin.get() )

    def _on_message_deleted( self, widget, messages ):
        number = []
        for message in messages:
            if message[2] == ALERT_ICON:
                number.append( message[0] )
        if len( number ) == 0:
            self.halcomp["error"] = False

    def _del_message_changed( self, pin ):
        if pin.get():
            if self.halcomp["error"] == True:
                number = []
                messages = self.notification.messages
                for message in messages:
                    if message[2] == ALERT_ICON:
                        number.append( message[0] )
                self.notification.del_message( number[0] )
                if len( number ) == 1:
                    self.halcomp["error"] = False
            else:
                self.notification.del_last()

    def _on_pin_incr_changed( self, pin, buttonnumber ):
        # print ("State = ", self.stat.state)
        if self.stat.state != 1:
            self.command.abort()
            self.command.wait_complete()
        if not pin.get():
            return
        data = self.jog_increments[int( buttonnumber )]
        self.on_increment_changed( self.incr_rbt_list[int( buttonnumber )], data )
        self.incr_rbt_list[int( buttonnumber )].set_active( True )

    def _on_pin_jog_changed( self, pin, axis, direction ):
        if axis not in "xyz":
            axis = "4"
        if direction == 1:
            widget = self.widgets["btn_%s_plus" % axis]
        else:
            widget = self.widgets["btn_%s_minus" % axis]
        if pin.get():
            self.on_btn_jog_pressed( widget )
        else:
            self.on_btn_jog_released( widget )

    def _reset_overide( self, pin, type ):
        if pin.get():
            self.widgets["btn_%s_100" % type].emit( "clicked" )

# =========================================================
# The actions of the buttons
    def _on_h_button_changed( self, pin ):
        # we check if the button is pressed ore release,
        # otehrwise a signal will be emitted, wenn the button is released and
        # the signal drob down to zero
        if not pin.get():
            return
        # lets see on witch button_box we are
        page = self.widgets.ntb_button.get_current_page()
        # witch button has been pressed
        btn = str( pin.name )
        # from the list we declared under __init__ we get the button number
        nr = int( btn[-1] )
        tab = self.h_tabs[page]  # see in the __init__ section for the declaration of self.tabs
        button = None
        # we check if there is a button or the user pressed a hardware button under
        # a non existing software button
        for index in tab:
            if int( index[0] ) == nr:
                # this is the name of the button
                button = index[1]
        if button:
            # only emit a signal if the button is sensitive, otherwise
            # running actions may be interupted
            if self.widgets[button].get_sensitive() == False:
                print( "%s not_sensitive" % button )
                return
            self.widgets[button].emit( "clicked" )
        else:
            # as we are generating the macro buttons dynamecely, we can"t use the same
            # method as above, here is how we do it
            if page == 1:  # macro page
                # does the user press a valid hardware button?
                if nr < len( self.macrobuttons ):
                    button = self.macrobuttons[nr]  # This list is generated in add_macros_buttons(self)
                    # is the button sensitive?
                    if button.get_sensitive() == False:
                        print( "%s not_sensitive" % button )
                        return
                    button.emit( "pressed" )
                else:
                    print( "No function on this button" )
            else:
                print( "No function on this button" )

    def _on_v_button_changed( self, pin ):
        if not pin.get():
            return
        btn = str( pin.name )
        nr = int( btn[-1] )
        tab = self.v_tabs  # see in the __init__ section for the declaration of self.tabs
        button = None
        for index in tab:
            if int( index[0] ) == nr:
                # this is the name of the button
                button = index[1]
        if button:
            # only emit a signal if the button is sensitive, otherwise
            # running actions may be interupted
            if self.widgets[button].get_sensitive() == False:
                print( "%s not_sensitive" % button )
                return
            button_pressed_list = ( "rbt_manual", "rbt_mdi", "rbt_auto" )
            button_toggled_list = ( "tbtn_setup" )
            if button in button_pressed_list:
                self.widgets[button].set_active( True )
                self.widgets[button].emit( "pressed" )
            elif button in button_toggled_list:
                self.widgets[button].set_active( not self.widgets[button].get_active() )
            else:
                self.widgets[button].emit( "clicked" )
        else:
            print( "No button found in v_tabs from %s" % pin.name )

# We need extra HAL pins here is where we do it.
# we make pins for the hardware buttons witch can be placed around the
# screen to activate the coresponding buttons on the GUI
    def _init_hal_pins( self ):
        # generate the horizontal button pins
        for h_button in range( 0, 10 ):
            pin = self.halcomp.newpin( "h-button-%s" % h_button, hal.HAL_BIT, hal.HAL_IN )
            hal_glib.GPin( pin ).connect( "value_changed", self._on_h_button_changed )

        # generate the vertical button pins
        for v_button in range( 0, 7 ):
            pin = self.halcomp.newpin( "v-button-%s" % v_button, hal.HAL_BIT, hal.HAL_IN )
            hal_glib.GPin( pin ).connect( "value_changed", self._on_v_button_changed )

        # buttons for jogging the axis
        for jog_button in self.axis_list:
            if jog_button not in "xyz":
                jog_button = self.axisletter_four
            pin = self.halcomp.newpin( "jog-%s-plus" % jog_button, hal.HAL_BIT, hal.HAL_IN )
            hal_glib.GPin( pin ).connect( "value_changed", self._on_pin_jog_changed, jog_button, 1 )
            pin = self.halcomp.newpin( "jog-%s-minus" % jog_button, hal.HAL_BIT, hal.HAL_IN )
            hal_glib.GPin( pin ).connect( "value_changed", self._on_pin_jog_changed, jog_button, -1 )

        # jog_increment out pin
        self.halcomp.newpin( "jog-increment", hal.HAL_FLOAT, hal.HAL_OUT )

        # generate the pins to set the increments
        for buttonnumber in range( 0, len( self.jog_increments ) ):
            pin = self.halcomp.newpin( "jog-inc-%s" % buttonnumber, hal.HAL_BIT, hal.HAL_IN )
            hal_glib.GPin( pin ).connect( "value_changed", self._on_pin_incr_changed, buttonnumber )

        # make the pin for unlocking settings page
        pin = self.halcomp.newpin( "unlock-settings", hal.HAL_BIT, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._on_unlock_settings_changed )

        # generate the pins to connect encoders to the sliders
        pin = self.halcomp.newpin( "feed-override.counts", hal.HAL_S32, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._on_counts_changed, "adj_feed" )
        pin = self.halcomp.newpin( "spindle-override.counts", hal.HAL_S32, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._on_counts_changed, "adj_spindle" )
        pin = self.halcomp.newpin( "jog-speed.counts", hal.HAL_S32, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._on_counts_changed, "adj_jog_vel" )
        pin = self.halcomp.newpin( "max-velocity.counts", hal.HAL_S32, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._on_counts_changed, "adj_max_vel" )
        self.halcomp.newpin( "feed-override.count-enable", hal.HAL_BIT, hal.HAL_IN )
        self.halcomp.newpin( "spindle-override.count-enable", hal.HAL_BIT, hal.HAL_IN )
        self.halcomp.newpin( "jog-speed.count-enable", hal.HAL_BIT, hal.HAL_IN )
        self.halcomp.newpin( "max-velocity.count-enable", hal.HAL_BIT, hal.HAL_IN )

        # generate the pins to connect analog inputs for sliders
        self.halcomp.newpin( "feed-override.analog-enable", hal.HAL_BIT, hal.HAL_IN )
        self.halcomp.newpin( "spindle-override.analog-enable", hal.HAL_BIT, hal.HAL_IN )
        self.halcomp.newpin( "jog-speed.analog-enable", hal.HAL_BIT, hal.HAL_IN )
        self.halcomp.newpin( "max-velocity.analog-enable", hal.HAL_BIT, hal.HAL_IN )
        pin = self.halcomp.newpin( "feed-override.direct-value", hal.HAL_FLOAT, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._on_analog_value_changed, "adj_feed" )
        pin = self.halcomp.newpin( "spindle-override.direct-value", hal.HAL_FLOAT, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._on_analog_value_changed, "adj_spindle" )
        pin = self.halcomp.newpin( "jog-speed.direct-value", hal.HAL_FLOAT, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._on_analog_value_changed, "adj_jog_vel" )
        pin = self.halcomp.newpin( "max-velocity.direct-value", hal.HAL_FLOAT, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._on_analog_value_changed, "adj_max_vel" )

        # make a pin to set turtle jog vel
        pin = self.halcomp.newpin( "turtle-jog", hal.HAL_BIT, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._on_turtle_jog_enable )

        # make the pins for tool measurement
        self.halcomp.newpin( "probeheight", hal.HAL_FLOAT, hal.HAL_OUT )
        self.halcomp.newpin( "blockheight", hal.HAL_FLOAT, hal.HAL_OUT )
        self.halcomp.newpin( "toolmeasurement", hal.HAL_BIT, hal.HAL_OUT )
        self.halcomp.newpin( "searchvel", hal.HAL_FLOAT, hal.HAL_OUT )
        self.halcomp.newpin( "probevel", hal.HAL_FLOAT, hal.HAL_OUT )

        # make pins to react to tool_offset changes
        pin = self.halcomp.newpin( "tooloffset-x", hal.HAL_FLOAT, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._offset_changed, "tooloffset-x" )
        pin = self.halcomp.newpin( "tooloffset-z", hal.HAL_FLOAT, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._offset_changed, "tooloffset-z" )

        # make a pin to delete a notification message
        pin = self.halcomp.newpin( "delete-message", hal.HAL_BIT, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._del_message_changed )

        # for manual tool change dialog
        self.halcomp.newpin( "toolchange-number", hal.HAL_S32, hal.HAL_IN )
        self.halcomp.newpin( "toolchange-changed", hal.HAL_BIT, hal.HAL_OUT )
        pin = self.halcomp.newpin( 'toolchange-change', hal.HAL_BIT, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( 'value_changed', self.on_tool_change )

        # make a pin to reset feed override to 100 %
        pin = self.halcomp.newpin( "reset-feed-override", hal.HAL_BIT, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._reset_overide, "feed" )

        # make a pin to reset spindle override to 100 %
        pin = self.halcomp.newpin( "reset-spindle-override", hal.HAL_BIT, hal.HAL_IN )
        hal_glib.GPin( pin ).connect( "value_changed", self._reset_overide, "spindle" )

        # make an error pin to indicate a error to hardware
        self.halcomp.newpin( "error", hal.HAL_BIT, hal.HAL_OUT )

        # make pins to indicate program progress information
        self.halcomp.newpin( "program.length", hal.HAL_S32, hal.HAL_OUT )
        self.halcomp.newpin( "program.current-line", hal.HAL_S32, hal.HAL_OUT )
        self.halcomp.newpin( "program.progress", hal.HAL_FLOAT, hal.HAL_OUT )

# Hal Pin Handling End
# =========================================================

#    def on_gremlin_button_press_event( self, widget, event ):
#        print widget.get_highlight_line()

if __name__ == "__main__":
    app = gmoccapy()

    inifile = sys.argv[2]
    print ( "**** GMOCCAPY INFO : inifile = %s ****:" % sys.argv[2] )
    postgui_halfile = app.get_ini_info.get_postgui_halfile()
    print ( "**** GMOCCAPY INFO : postgui halfile = %s ****:" % postgui_halfile )

    if postgui_halfile:
        if postgui_halfile.lower().endswith('.tcl'):
            res = os.spawnvp(os.P_WAIT, "haltcl", ["haltcl", "-i", inifile, postgui_halfile])
        else:
            res = os.spawnvp( os.P_WAIT, "halcmd", ["halcmd", "-i", inifile, "-f", postgui_halfile] )
        if res:
            raise SystemExit, res
    gtk.main()

