'''
Created on 26.08.2025

@author: NimkeL
'''
import os
import wx
import shutil
import re, math
from datetime import datetime
from sys import modules
from functools import partial
import wx.lib.scrolledpanel as scrolled

import p2cpython as cad # @UnresolvedImport
from p2cpython import BEHAVIOUR, getMessageW, P2CMessageBox, FORMAT # @UnresolvedImport
from p2c.generalsettings import MainOptions
from p2c.postoptionsdlg import postVar

from p2c.utils import logger, inPeps, round
from p2c.window import BORDER, SMALLBORDER, MINIBORDER, OptiCheckBox, StaticBox, OptiRadioButton
from p2c.window import getOpticamIcon, NormalButton, getText, LabeledEditField
from p2c.window import PINBUTTON_DOCKED, PINBUTTON_UNDOCKED, CustomStatusBar, ScreenScaleFactorNeeded
from p2c.window import BaseDialog, ShowDialogFromList
from p2c.window import ResetTooltipHoldingTime, TextField

from p2c.measurecycle import MeasureCycleMixin, MEASURETYPE, MEASUREPARAM, NOT_SET
from p2c.measurecycledlg import MYNiceButton, MeasureCycleBaseDialog, GeneralReadMeasureCycleDefaultParams
from p2c.measurecycledlg import UpdateDictRecursively, DummyPanel, Methoddispatch, MyMainButtonsPanel
from p2c.measurecycledlg import LeftLabeledEditField, RealLeftLabeledDobbleEditFieldPickPos, RealLeftLabeledDobbleEditFieldPickPos2
from p2c.measurecycledlg import GeneralUpdateMeasureCycleDefaultParams
from p2c.measurecycledlg import MeasureCycleDialogSaveProfile, MeasureCycleDialogLoadProfile

# GLOBAL VARIABLES
LOG_TAG = "mcy_makino"
MEASURECYCLEDEFAULTSFILE = "mcy_makino_defaults.xml" 
MEASURECYCLEUSERDEFAULTSFILE = "mcy_makino_user_defaults.xml"
MEASURECYCLEMACHINENAME = "makino"
EDIT_FIELD_SIZE = (int(75 * ScreenScaleFactorNeeded), -1)
LABEL_FIELD_SIZE = (int(150 * ScreenScaleFactorNeeded), -1)

strVersion = ""
strMeasureCycleType = "" 
measureObject = None            # for data exchange between here and C++ main system
measureString = None            # for data exchange between here and peps
originObject = None

# Global Flags to check which Pick position Button was clicked
POINT_PICK=[False, False, False]
G92_PICK=False

# Global Values for storing box-choices for NC Code creation and other stuff

MEASURECYCLEXML_VERSION_LIST=["1.0"]#changes to measure cycle sub panels need a new version number, add the new version number to the list

# assign the new types in module level
thisModule = modules[__name__]
# type_id (KEY_PART1) + index of record (SEARCHTERM) = "KEY"

setattr(thisModule, 'EDG', type('EDG', (object,), {"name":"EDG", "type_id":"0001", "enum": cad.eMEASURETYPE_EDG, "VDMVersion": strVersion, "iso_code":"130"}))
setattr(thisModule, 'CEN', type('CEN', (object,), {"name":"CEN", "type_id":"0002", "enum": cad.eMEASURETYPE_CEN, "VDMVersion": strVersion, "iso_code":"134"}))
setattr(thisModule, 'CRN', type('CRN', (object,), {"name":"CRN", "type_id":"0003", "enum": cad.eMEASURETYPE_CRN, "VDMVersion": strVersion, "iso_code":"137"}))
setattr(thisModule, 'MID', type('MID', (object,), {"name":"MID", "type_id":"0004", "enum": cad.eMEASURETYPE_MID, "VDMVersion": strVersion, "iso_code":"133"}))
setattr(thisModule, 'PLM', type('PLM', (object,), {"name":"PLM", "type_id":"0005", "enum": cad.eMEASURETYPE_PLM, "VDMVersion": strVersion, "iso_code":"145"}))
setattr(thisModule, 'EXC', type('EXC', (object,), {"name":"EXC", "type_id":"0006", "enum": cad.eMEASURETYPE_EXC, "VDMVersion": strVersion, "iso_code":"136"}))
setattr(thisModule, 'PAL', type('PAL', (object,), {"name":"PAL", "type_id":"0007", "enum": cad.eMEASURETYPE_PAL, "VDMVersion": strVersion, "iso_code":"132"}))
# Unused types
setattr(thisModule, 'CLH', type('CLH', (object,), {"name":"CLH", "type_id":"0008", "enum": cad.eMEASURETYPE_CLH, "VDMVersion": strVersion, "iso_code":"125"}))
setattr(thisModule, 'CAL', type('CAL', (object,), {"name":"CAL", "type_id":"0009", "enum": cad.eMEASURETYPE_CAL, "VDMVersion": strVersion, "iso_code":"138"}))
setattr(thisModule, 'EXN', type('EXN', (object,), {"name":"EXN", "type_id":"0010", "enum": cad.eMEASURETYPE_EXN, "VDMVersion": strVersion, "iso_code":"143"}))
setattr(thisModule, 'EXM', type('EXM', (object,), {"name":"EXM", "type_id":"0011", "enum": cad.eMEASURETYPE_EXM, "VDMVersion": strVersion, "iso_code":"142"}))
setattr(thisModule, 'BAL', type('BAL', (object,), {"name":"BAL", "type_id":"0012", "enum": cad.eMEASURETYPE_BAL, "VDMVersion": strVersion, "iso_code":"131"}))
setattr(thisModule, 'CEN3P', type('CEN3P', (object,), {"name":"CEN3P", "type_id":"0013", "enum": cad.eMEASURETYPE_CEN3P, "VDMVersion": strVersion, "iso_code":"134"}))

#++++++++++++++++++++++++++++ XML Data functions +++++++++++++++++++++++++++++++++++
def GetDataXMLPath():
    """
    This function returns the path to this .py file, which is also the path to the .xml file
    """
    return os.path.dirname( os.path.abspath(__file__) )    # path to this source file


def GetUserDataXMLPath():
    """
    This function returns the path to this .py file, which is also the path to the .xml file.  
    If in PEPS it returns a string with user data.  
    """
    if inPeps():    # Get Peps data path
        from peps import ReadGlobalString  # @UnresolvedImport
        return ReadGlobalString( "$_user_data_settings" )
    else:
        return os.path.dirname( os.path.abspath(__file__) )    # path to this file


def GetDefaultDataXMLFile():
    """
    This function returns the path of the default data .xml file.
    """
    return os.path.join(GetDataXMLPath(), MEASURECYCLEDEFAULTSFILE)


def GetUserDataXMLFile():
    """
    This function returns the path of the user data .xml file.
    """
    return os.path.join(GetUserDataXMLPath(), MEASURECYCLEUSERDEFAULTSFILE)
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


def GetMeasureCycleTypeString(typ):
    """
    This function maps the different measuretypes to an index for access through other functions.
    """
    # first index is "real" 1
    try:
        return ['', 'EDG', 'CEN', 'CRN', 'MID', 'PLM', 'EXC', 'PAL', 'CLH', 'CAL', 'EXN', 'EXM', 'BAL', 'CEN3P'][typ]
    except:
        return ""


class MakinoMeasureCycleMainDialog(MeasureCycleBaseDialog):
    """
    This class defines the manager dialog for measure cycle of Makino
    
    The "Main dialog" controls all measure cycle styles, it needs only close & dock button
    
    Measuretypes:       
         1 = (EDG) Edge positioning
         2 = (CEN) Center hole
         3 = (CRN) Corner measurement
         4 = (MID) Groove middle centering
         5 = (PLM) Plate Outside width centering
         6 = (EXC) Cylinder Center Measurement
         7 = (PAL) Workpiece Parallelism Measurement

    """
    
    def __init__(self, *args, **kwargs):
        #Init Base class
        MeasureCycleBaseDialog.__init__(self, *args, **kwargs)
        
        # hide the ok; help; translate button and move the esc button to the first position
        # if the dialog use GridBagSizer, scilicet "iconMFCStyle" is true 
        # hide the ok button
        ##self.btnOK.Hide()
        # hide the help button
        self.btnHelp.Hide()
        # 
        self.strVDMVersion = ""
        
        #self.unDockBestSize = (370 * ScreenScaleFactor, 837 * ScreenScaleFactor)
        #self.inDockBestSize = (350 * ScreenScaleFactor, 810 * ScreenScaleFactor)
        
        self.bCancelFromSub = False
        
        if self.iconMFCStyle:
            self.vbxH1.Detach(self.btnOK)   # an easier and more elegant way is to remove the widget from sizer
            self.btnOK.Destroy()
       
        #Read defaults parameters from xml file
        self.dictAllTypeDefaultParams = {}
        self.ReadParamsOfAllMeasueType()
        
        #Create Widgets 
        self.CreateWidgets()  
        

    def Activate(self, Measureobject=None, dummy=None):
        """ 
        Jump in point of main- (selection) dialog (can also come from sub-dialog or C++)
        """
        #
        global measureObject
        global originObject
        # we are called from C++ with a Measureobject
        if Measureobject is not None:
            logger.info(LOG_TAG + "MakinoMeasureCycleMainDialog.Activate() [CALL FROM C++]")
            measureObject = Measureobject
        # we are called from Python sub-dialog
        else:
            logger.info(LOG_TAG + "MakinoMeasureCycleMainDialog.Activate() [CALL FROM SUBMENUE]")
         
        # if not self.docked:
        #     self.CenterOnScreen()

        # dummy will be used for origin!
        if dummy is not None:
            originObject = dummy
            pass
    
        # Set same position as sub Dialog
        if not self.docked:
            if 'WindowPosition' in self.kwargsBuffer:
                self.SetPosition(self.kwargsBuffer['WindowPosition'])
            
        # else:
        #     if self.bCancelFromSub:
        #         self.docked = False
        #         self.bCancelFromSub = False
        #         wx.CallAfter(self.FireDockEvent)
        #
        # IMPORTANT: CALL BASE-CLASS METHOD (puts the data to the controls)
        # the ShowModal will fire the method TransferDataToWindow
        super(self.__class__, self).Activate()
        
    
    def OnESC(self, event):
        """
        Function for when escape button is clicked
        """
        #
        cad.getCurrentDoc().NewMeasure(measureObject, False)
        # Save the current dialog window position
        if "WindowPosition" in BaseDialog.kwargsBuffer:
            BaseDialog.kwargsBuffer['WindowPosition'] = self.GetScreenPosition()
        else:
            pass
        #
        super(self.__class__, self).OnESC(event)
        

    def ReadParamsOfAllMeasueType(self):
        """
        This function reads out all data from the default or user data .xml and saves it to a dictionary.
        """
        
        if os.path.exists(GetUserDataXMLFile()):
            strXMLPath = GetUserDataXMLFile()
        else:
            strXMLPath = GetDefaultDataXMLFile()
            
        dictTemp = GeneralReadMeasureCycleDefaultParams(strXMLPath, MEASURECYCLEMACHINENAME)
        self.dictAllTypeDefaultParams = dictTemp.copy()
    
    
    def CreateWidgets(self):
        """ 
        This function defines and creates widgets for the main measurement cycle page 
        """
        
        oldStyle = self.panel.GetWindowStyle()
        newStyle = oldStyle | wx.TAB_TRAVERSAL #| wx.CLIP_CHILDREN #| wx.FULL_REPAINT_ON_RESIZE
        self.panel.SetWindowStyle(newStyle)
        
        # Position in the machining plane
        subSizer1 = wx.StaticBoxSizer( StaticBox( self.panel, wx.ID_ANY, "Position in the machining plane", name='STB_POS_PLANE' ), wx.HORIZONTAL )
        # Bag Sizer with flexible grid
        self.vBagSub1 = wx.GridBagSizer(1, 1)
        toolTipString="Work piece parallelism measurement" # de, EXN - Position in Bearbeirungsebene
        self.btnMeasCycType7 = MYNiceButton(self.panel, wx.ID_ANY, 'Makino_PAL.bmp', 'Makino_PAL.bmp', style=wx.BORDER_RAISED, measureType="PAL", name="BTN_MEAS_CYC-TYPE7", toolTipString=toolTipString)
        self.vBagSub1.Add(self.btnMeasCycType7, (0, 0), flag=wx.LEFT | wx.TOP | wx.BOTTOM, border=SMALLBORDER)
   
        subSizer1.Add(self.vBagSub1, 1)
        
        self.vbxV1.Add(subSizer1, 0, flag=wx.ALL|wx.EXPAND, border=SMALLBORDER)
        
          
        subSizer2 = wx.StaticBoxSizer( StaticBox( self.panel, wx.ID_ANY, "Positioning", name='STB_POSITIONING' ), wx.HORIZONTAL )
        # Bag Sizer with flexible grid
        self.vBagSub2 = wx.GridBagSizer(0, 0)
        # Buttons for different measurement cycles  
        toolTipString="Work piece Edge positioning" # de, EDG - Kante antuschieren/Antasten in Z
        self.btnMeasCycType1 = MYNiceButton(self.panel, wx.ID_ANY, 'Makino_EDG.bmp', 'Makino_EDG.bmp', style=wx.BORDER_RAISED, measureType="EDG",  name="BTN_MEAS_CYC-TYPE1", toolTipString=toolTipString)
        self.vBagSub2.Add(self.btnMeasCycType1, (0, 0), flag=wx.LEFT | wx.TOP | wx.BOTTOM, border=SMALLBORDER)
        
        toolTipString="Hole Center Positioning" # de, Bohrung zentrieren 
        self.btnMeasCycType2 = MYNiceButton(self.panel, wx.ID_ANY, 'Makino_CEN.bmp', 'Makino_CEN.bmp', style=wx.BORDER_RAISED, measureType="CEN", name="BTN_MEAS_CYC-TYPE2", toolTipString=toolTipString)
        self.vBagSub2.Add(self.btnMeasCycType2, (0, 1), flag=wx.LEFT | wx.TOP | wx.BOTTOM, border=SMALLBORDER)
        
        toolTipString="Corner Edge Positioning" # de, CRN - Ecke antasten
        self.btnMeasCycType3 = MYNiceButton(self.panel, wx.ID_ANY, 'Makino_CRN.bmp', 'Makino_CRN.bmp', style=wx.BORDER_RAISED, measureType="CRN", name="BTN_MEAS_CYC-TYPE3", toolTipString=toolTipString)
        self.vBagSub2.Add(self.btnMeasCycType3, (0, 2), flag=wx.LEFT | wx.TOP | wx.BOTTOM, border=SMALLBORDER)
             
        toolTipString="Groove Width Center Positioning" # de, MID - Mitte Nut
        self.btnMeasCycType4 = MYNiceButton(self.panel, wx.ID_ANY, 'Makino_MID.bmp', 'Makino_MID.bmp', style=wx.BORDER_RAISED, measureType="MID", name="BTN_MEAS_CYC-TYPE4", toolTipString=toolTipString)
        self.vBagSub2.Add(self.btnMeasCycType4, (1, 0), flag=wx.LEFT | wx.TOP | wx.BOTTOM, border=SMALLBORDER)
        
        toolTipString="Plate Width Centering" # de, PLM - Werkstückbreite
        self.btnMeasCycType5 = MYNiceButton(self.panel, wx.ID_ANY, 'Makino_PLM.bmp', 'Makino_PLM.bmp', style=wx.BORDER_RAISED, measureType="PLM", name="BTN_MEAS_CYC-TYPE5", toolTipString=toolTipString)
        self.vBagSub2.Add(self.btnMeasCycType5, (1, 1), flag=wx.LEFT | wx.TOP | wx.BOTTOM, border=SMALLBORDER)
        
        toolTipString="Cylinder Center Measurement" # de, EXC - Zylinder zentrieren
        self.btnMeasCycType6 = MYNiceButton(self.panel, wx.ID_ANY, 'Makino_EXC.bmp', 'Makino_EXC.bmp', style=wx.BORDER_RAISED, measureType="EXC", name="BTN_MEAS_CYC-TYPE6", toolTipString=toolTipString)
        self.vBagSub2.Add(self.btnMeasCycType6, (1, 2), flag=wx.LEFT | wx.TOP | wx.BOTTOM, border=SMALLBORDER)
        
        subSizer2.Add(self.vBagSub2, 1)
      
        # toolTipString="Holes parallel"
        # self.btnMeasCycType8 = MYNiceButton(self.panel, wx.ID_ANY, 'makino_CAL_Probe.bmp', 'makino_CAL_Probe.bmp', style=wx.BORDER_RAISED, measureType="CAL",  name="BTN_MEAS_CYC-TYPE8", toolTipString=toolTipString)
        # self.vBagMain.Add(self.btnMeasCycType8, (3, 1), flag=wx.LEFT | wx.TOP | wx.BOTTOM, border=SMALLBORDER)
        #
        # toolTipString="Outer circle measurement" 
        # self.btnMeasCycType9 = MYNiceButton(self.panel, wx.ID_ANY, 'makino_EXC_Probe.bmp', 'makino_EXC_Probe.bmp', style=wx.BORDER_RAISED, measureType="EXC",  name="BTN_MEAS_CYC-TYPE9", toolTipString=toolTipString)
        # self.vBagMain.Add(self.btnMeasCycType9, (3, 2), flag=wx.LEFT | wx.TOP | wx.BOTTOM, border=SMALLBORDER)
        
        self.vbxV1.Add(subSizer2, 1, flag=wx.ALL|wx.EXPAND, border=SMALLBORDER)
        
        # Resize the dialog after adding Controls in derived classes.
        self.vbxV1.Fit(self)   
        
        # extra part
        #self.strMsgLabel = getText("WARNING", "MSG_LABEL_WARNING")
        #self.strMsgContent = getText("This measuring type works only with 3-D Probe", "STT_WORK_ONLY_PROBE")
      
        #Event binder  
        self.Bind(wx.EVT_BUTTON, self.OnMeasureTypeMYNiceButtonClicked, self.btnMeasCycType1)
        self.Bind(wx.EVT_BUTTON, self.OnMeasureTypeMYNiceButtonClicked, self.btnMeasCycType2)
        self.Bind(wx.EVT_BUTTON, self.OnMeasureTypeMYNiceButtonClicked, self.btnMeasCycType3)
        self.Bind(wx.EVT_BUTTON, self.OnMeasureTypeMYNiceButtonClicked, self.btnMeasCycType4)
        self.Bind(wx.EVT_BUTTON, self.OnMeasureTypeMYNiceButtonClicked, self.btnMeasCycType5)
        self.Bind(wx.EVT_BUTTON, self.OnMeasureTypeMYNiceButtonClicked, self.btnMeasCycType6)
        self.Bind(wx.EVT_BUTTON, self.OnMeasureTypeMYNiceButtonClicked, self.btnMeasCycType7)
        # self.Bind(wx.EVT_BUTTON, self.OnMeasureTypeMYNiceButtonClicked, self.btnMeasCycType8)
        # self.Bind(wx.EVT_BUTTON, self.OnMeasureTypeMYNiceButtonClicked, self.btnMeasCycType9)
  
    
    def OnMeasureTypeMYNiceButtonClicked(self, event):
        """
        This function defines the event for when a "MYNiceButton" Type of button is clicked.
        These buttons lead to the sub-diologs of the specific measure cycle types.
        """
        global strVersion, strMeasureCycleType
        
        objEvent = event.GetEventObject()
            
        strVersion = self.strVDMVersion
        strMeasureCycleType = objEvent.GetMeasureCycleType()
        
        # Save the current dialog window position
        if "WindowPosition" in BaseDialog.kwargsBuffer:
            # Delete value from buffer if exists, always set the latest screen position
            BaseDialog.kwargsBuffer.pop("WindowPosition", None)

        # Set and Save window current position
        BaseDialog.kwargsBuffer['WindowPosition'] = self.GetScreenPosition()

        # mydoc = cad.getCurrentDoc()
        # parent = mydoc.DocumentWindow()
        # obj_setparent = None  # @UnusedVariable
        # for item in parent.GetChildren():
        #     if item.Name == 'DLG_MEASURE_CYCLIE_SUB':
        #         obj_setparent = item  # @UnusedVariable
        #         break
        #     else: 
        #         pass
        # if obj_setparent:
        #     obj_setparent.docked = self.docked
        #     obj_setparent.Activate(strMeasureCycleType, strVersion, True)
        #     #self.Disable()
        #     self.OnESC(None) # if the dialog is show/hide; STOPPING MAIN DIALOG !!!
        #     return
        # else:
        #     return

        # Now hide the main-dialog:
        super(self.__class__, self).OnESC(event)      
        # ...and start the sub-dialog
        # to show modeless dialogs from within python:
        pyobj = cad.getCurrentDoc().GetPyObj() # @UnusedVariable
        # Now show the dialog:
        #pyobj.ShowModlessListObjectDlg("DLG_MEASURE_CYCLIE_SUB")        # Use here the NAME of the dialog (not class name)
        ShowDialogFromList("DLG_MEASURE_CYCLIE_SUB", *BaseDialog.argsBuffer, **BaseDialog.kwargsBuffer)
            

class MyPanelMeasureCycleType1(scrolled.ScrolledPanel):
    def __init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL, name=""):  # @ReservedAssignment
        """
        This class defines and creates widgets for the sub dialog for measure cycle Type 1: 
        """
        self.isMainPanel=True
        self.parent = parent
        self.name=name
        self.title="EDG"
        scrolled.ScrolledPanel.__init__(self, parent, id=id, style=style, name=name)       
        #self.SetBackgroundColour('PINK')
        self.SetupScrolling(scroll_x=True, scroll_y=True)
        
        objFont = self.GetFont()
        
        self.vBagMain = wx.GridBagSizer(0, 0) # vgap 0, hgab 0
        
        # Sizer for wire cut settings
        vBoxWireSettings = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Wire Settings", name="STB_WIRE_SETTINGS"), wx.VERTICAL) # Draht Einstellungen
        self.cbThreadWire = OptiCheckBox(self, wx.ID_ANY, label="Thread wire before measurement (M06)", name='PAR_3') # de, Draht einfädeln
        vBoxWireSettings.Add(self.cbThreadWire, 1, wx.ALL | wx.EXPAND, SMALLBORDER)
        self.cbCutWire = OptiCheckBox(self, wx.ID_ANY, label="Cut wire after measurement (M07)", name='PAR_4') # de, Draht abscheiden  
        vBoxWireSettings.Add(self.cbCutWire, 1, wx.ALL | wx.EXPAND, SMALLBORDER)    
      
        self.vBagMain.Add(vBoxWireSettings, (0, 0), flag=wx.ALL | wx.EXPAND, border=MINIBORDER)
        
        # Main Sizer for First Point
        self.stbPickStart = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Measurement Start Point", name="STB_MEASURE_POINT_1"), wx.HORIZONTAL)              
        # Sub sizer for selection and position
        vBoxSubStartPos = wx.BoxSizer(wx.VERTICAL)
        self.stbPickStart.Add(vBoxSubStartPos, 1, flag= wx.EXPAND|wx.ALL)
             
        # X Position
        toolTipString="X Coordinate of Startpoint"
        self.lLEFXStart = LabeledEditField(self, wx.ID_ANY, "X", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_1',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFXStart.typeOfValue = float
        self.lLEFXStart.decimalDigitsOfOuput = 3
        self.stbPickStart.Add(self.lLEFXStart, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)      
        # Y Position
        toolTipString="Y Coordinate of Startpoint"
        self.lLEFYStart = LabeledEditField(self, wx.ID_ANY, "Y", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_2',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFYStart.typeOfValue = float
        self.lLEFYStart.decimalDigitsOfOuput = 3    
        self.stbPickStart.Add(self.lLEFYStart, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)
        # Position choice button
        toolTipString="Catch Coordinates"
        self.buttonPickPos = NormalButton(self, wx.ID_ANY, "XY>>",wx.DefaultPosition , size=(50, 25), style=0, name="_BTN_MEASURE_POINT_1XY", toolTipString=toolTipString)
        self.stbPickStart.Add(self.buttonPickPos, 0, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)
        
        self.vBagMain.Add(self.stbPickStart, (2, 0), flag=wx.ALL|wx.EXPAND, border=MINIBORDER)
     
        # Image part
        self.bmpX = getOpticamIcon('Makino_EDG_1.bmp')
        self.bmpY = getOpticamIcon('Makino_EDG_2.bmp')

        self.stBitmap = wx.StaticBitmap(self, id=wx.ID_ANY, bitmap=self.bmpX, pos=wx.DefaultPosition,
                                        size=wx.DefaultSize, style=0, name="IMG_MCY_TYPE1")

        self.vBagMain.Add(self.stBitmap, (0, 1), (2, 1), flag=wx.ALIGN_CENTER | wx.ALL , border=MINIBORDER)
        
        # Cycle Rotation part
        #self.stbTouchDir = wx.StaticBox(self, wx.ID_ANY, "Touch Sensing Direction", name="STB_TOUCH_DIR") 
        #vTouchDir = wx.StaticBoxSizer(self.stbTouchDir, wx.VERTICAL)
        self.stbTouchDir = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Touch Sensing Direction", name="STB_TOUCH_DIR"), wx.VERTICAL)
        hTouchDir1 = wx.BoxSizer(wx.HORIZONTAL)
        self.rbDirXPlus = OptiRadioButton(self, wx.ID_ANY, "X", style=wx.RB_GROUP, name="PAR_5")
        self.rbDirYPlus = OptiRadioButton(self, wx.ID_ANY, "Y", style=0, name="RB_DIR_Y")
        hTouchDir1.Add(self.rbDirXPlus,  1, wx.EXPAND, SMALLBORDER)
        hTouchDir1.Add(self.rbDirYPlus,  1, wx.EXPAND, SMALLBORDER)
        self.stbTouchDir.Add(hTouchDir1, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        
        self.vBagMain.Add(self.stbTouchDir, (1, 0), (1, 1), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)

        # Profile Sizers - Save/Load  
        vProfile = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Profiles", name="STB_PROFILE"), wx.VERTICAL) # 
        hProfile = wx.BoxSizer(wx.HORIZONTAL)
        
        toolTipString="Transfer these entries to a database."
        self.btnProfileSave = NormalButton(self, wx.ID_ANY, "Save", wx.DefaultPosition, wx.DefaultSize, style=0, name='BTN_PROFILE_SAVE',toolTipString=toolTipString )
        toolTipString="View saved entries / load into the dialog."
        self.btnProfileLoad = NormalButton(self, wx.ID_ANY, "Load", wx.DefaultPosition, wx.DefaultSize, style=0, name='BTN_PROFILE_LOAD',toolTipString=toolTipString)
        hProfile.Add(self.btnProfileSave,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        hProfile.Add(self.btnProfileLoad,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        vProfile.Add(hProfile, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        self.vBagMain.Add(vProfile, (2, 1), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Info text marking the start of for cycle specific params
        self.MeasureInfo=TextField(self, wx.ID_ANY, "Edge Positioning", wx.DefaultPosition, wx.DefaultSize,style=0, name='Info Text EDG')
        self.vBagMain.Add(self.MeasureInfo, (3, 0), flag=wx.EXPAND | wx.ALL, border=SMALLBORDER)
        
        # Approach distance X
        toolTipString="Approach distance in X direction to work piece"
        self.lefApprX= LeftLabeledEditField(self, wx.ID_ANY, "Approach distance X", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_9', toolTipString=toolTipString, bWithCheckbox=False)
        self.lefApprX.typeOfValue = float
        self.lefApprX.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefApprX, (4, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Fast Advance I (X-axis) and J (Y-axis)
        toolTipString="Fast Advance I (X-axis), optional to shorten measurement time"
        self.lefFastAdvI= LeftLabeledEditField(self, wx.ID_ANY, "Fast Advance 'I' (X-axis)", min=0.0, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_10', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefFastAdvI.typeOfValue = float
        self.lefFastAdvI.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefFastAdvI, (5, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Approach distance Y
        toolTipString="Approach distance in Y direction to work piece"
        self.lefApprY= LeftLabeledEditField(self, wx.ID_ANY, "Approach distance Y", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_11', toolTipString=toolTipString, bWithCheckbox=False)
        self.lefApprY.typeOfValue = float
        self.lefApprY.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefApprY, (6, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
             
        # Fast Advance J (Y-axis) 
        toolTipString="Fast Advance J (Y-axis), optional to shorten measurement time"
        self.lefFastAdvJ= LeftLabeledEditField(self, wx.ID_ANY, "Fast Advance 'J' (Y-axis)", min=0.0, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_12', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefFastAdvJ.typeOfValue = float
        self.lefFastAdvJ.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefFastAdvJ, (7, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Touching Angle (A)
        toolTipString="Specifies the angle for measurement direction."
        self.lefPosAng = LeftLabeledEditField(self, wx.ID_ANY, "Touching Angle (A). | (Possible values: -90.0° to 90.0°)", min=-90.0000, max=90.0000,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.ANGLE_VALUE, name='PAR_8', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefPosAng.typeOfValue = float
        self.lefPosAng.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefPosAng, (8, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
              
        # G92
        toolTipString="Temporarily Shift Coordinate System to current (measured) Wire Position.\nATTENTION! Please consider the Wire Diameter!"
        self.lefG92 = RealLeftLabeledDobbleEditFieldPickPos2(self, wx.ID_ANY, wx.ID_ANY, extraLabel = "G92", label1="X", label2="Y", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name1='PAR_6', name2='PAR_7', 
                                             toolTipString=toolTipString, bWithCheckbox=True, name="LLEFPP_G92")
        self.lefG92.typeOfValue = float
        self.lefG92.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefG92, (9, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Status Bar for string preview
        if not parent.statusbar:
            toolTipString="Preview of NC Code String."
            self.sttOutput = wx.StaticText(self, wx.ID_ANY, label="xxxxxxxxxx", pos=wx.DefaultPosition,
               size=wx.DefaultSize, style=0, name="STT_OUTPUT_COMMON", toolTipString=toolTipString) 
            self.sttOutput.SetFont(objFont)
            self.vBagMain.Add(self.sttOutput, (10, 0), (1, 2), flag=wx.EXPAND | wx.TOP, border=BORDER)
        
        # Make all rows and columns of the GridBagSizer dynamically change with panel size
        self.vBagMain.Layout()
        for col in range(self.vBagMain.GetCols()):
            self.vBagMain.AddGrowableCol(col)
        for row in range(self.vBagMain.GetRows()):
            self.vBagMain.AddGrowableRow(row)
        
        self.SetSizerAndFit(self.vBagMain)
            
        #### Bind events ####    
        self.Bind(wx.EVT_CHECKBOX, parent.OnLabeledEFCheckboxChecked)
        # Wire Settings Check Box
        self.cbCutWire.Bind(wx.EVT_CHECKBOX, parent.OnCutWireCheckboxChecked)
        self.cbThreadWire.Bind(wx.EVT_CHECKBOX, parent.OnThreadWireCheckboxChecked)
        # Text Field changes
        self.Bind(wx.EVT_TEXT, parent.OnLabeledEFTextCtrlChanged)
        # Profile Buttons
        self.btnProfileSave.Bind(wx.EVT_BUTTON, parent.OnSaveProfileButtonClicked)
        self.btnProfileLoad.Bind(wx.EVT_BUTTON, parent.OnLoadProfileButtonClicked)
        # Position Pick Buttons
        self.buttonPickPos.Bind(wx.EVT_BUTTON, parent.OnPickPositionPointButtonClicked)
        self.lefG92.Bind(wx.EVT_BUTTON, parent.OnPickPositionG92ButtonClicked)
        # Radio Rotation Buttons
        self.rbDirXPlus.Bind(wx.EVT_RADIOBUTTON, partial(parent.OnRadioBoxMeasureDirectionClicked, vDir='+X'))
        self.rbDirYPlus.Bind(wx.EVT_RADIOBUTTON, partial(parent.OnRadioBoxMeasureDirectionClicked, vDir='+Y'))
        ####################
        

class MyPanelMeasureCycleType2(scrolled.ScrolledPanel):
    def __init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL, name=""):  # @ReservedAssignment
        """
        This class defines and creates widgets for the sub dialog for measure cycle Type 2: 
        """
        self.isMainPanel=True
        self.parent = parent
        self.name=name
        self.title="CEN"
        scrolled.ScrolledPanel.__init__(self, parent, id=id, style=style, name=name)
        ##self.SetBackgroundColour('PINK')
        self.SetupScrolling(scroll_x=True, scroll_y=True)
        
        objFont = self.GetFont()
        
        self.vBagMain = wx.GridBagSizer(0, 0) # vgap 0, hgab 0
        
        # Sizer for wire cut settings
        vBoxWireSettings = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Wire Settings", name="STB_WIRE_SETTINGS"), wx.VERTICAL) # Draht Einstellungen
        self.cbThreadWire = OptiCheckBox(self, wx.ID_ANY, label="Thread wire before measurement (M06)", name='PAR_3') # de, Draht einfädeln
        vBoxWireSettings.Add(self.cbThreadWire, 1, wx.ALL | wx.EXPAND, SMALLBORDER)
        self.cbCutWire = OptiCheckBox(self, wx.ID_ANY, label="Cut wire after measurement (M07)", name='PAR_4') # de, Draht abscheiden  
        vBoxWireSettings.Add(self.cbCutWire, 1, wx.ALL | wx.EXPAND, SMALLBORDER)    
      
        self.vBagMain.Add(vBoxWireSettings, (0, 0), flag=wx.ALL | wx.EXPAND, border=MINIBORDER)
        
        # Main Sizer for First Point
        self.stbPickStart = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Measurement Start Point", name="STB_MEASURE_POINT_1"), wx.HORIZONTAL)              
        # Sub sizer for selection and position
        vBoxSubStartPos = wx.BoxSizer(wx.VERTICAL)
        self.stbPickStart.Add(vBoxSubStartPos, 1, flag= wx.EXPAND|wx.ALL)
              
        # X Position
        toolTipString="X Coordinate of Startpoint"
        self.lLEFXStart = LabeledEditField(self, wx.ID_ANY, "X", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_1',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFXStart.typeOfValue = float
        self.lLEFXStart.decimalDigitsOfOuput = 3
        self.stbPickStart.Add(self.lLEFXStart, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)      
        # Y Position
        toolTipString="Y Coordinate of Startpoint"
        self.lLEFYStart = LabeledEditField(self, wx.ID_ANY, "Y", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_2',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFYStart.typeOfValue = float
        self.lLEFYStart.decimalDigitsOfOuput = 3    
        self.stbPickStart.Add(self.lLEFYStart, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)  
        # Position choice button
        toolTipString="Catch Coordinates"
        self.buttonPickPos = NormalButton(self, wx.ID_ANY, "XY>>",wx.DefaultPosition , size=(50, 25), style=0, name="_BTN_MEASURE_POINT_1XY", toolTipString=toolTipString)
        self.stbPickStart.Add(self.buttonPickPos, 0, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)
        
        self.vBagMain.Add(self.stbPickStart, (1, 0), flag=wx.ALL|wx.EXPAND, border=MINIBORDER)
     
        # Image part
        self.bmpX = getOpticamIcon('Makino_CEN_1.bmp')

        self.stBitmap = wx.StaticBitmap(self, id=wx.ID_ANY, bitmap=self.bmpX, pos=wx.DefaultPosition,
                                        size=wx.DefaultSize, style=0, name="IMG_MCY_TYPE2")

        self.vBagMain.Add(self.stBitmap, (0, 1), (1, 1), flag=wx.ALIGN_CENTER | wx.ALL , border=MINIBORDER)

        # Profile Sizers - Save/Load  
        vProfile = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Profiles", name="STB_PROFILE"), wx.VERTICAL) # 
        hProfile = wx.BoxSizer(wx.HORIZONTAL)
        
        toolTipString="Transfer these entries to a database."
        self.btnProfileSave = NormalButton(self, wx.ID_ANY, "Save", wx.DefaultPosition, wx.DefaultSize, style=0, name='BTN_PROFILE_SAVE',toolTipString=toolTipString )
        toolTipString="View saved entries / load in the dialog."
        self.btnProfileLoad = NormalButton(self, wx.ID_ANY, "Load", wx.DefaultPosition, wx.DefaultSize, style=0, name='BTN_PROFILE_LOAD',toolTipString=toolTipString)
        hProfile.Add(self.btnProfileSave,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        hProfile.Add(self.btnProfileLoad,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        vProfile.Add(hProfile, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        self.vBagMain.Add(vProfile, (1, 1), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Info text marking the start of for cycle specific params
        self.MeasureInfo=TextField(self, wx.ID_ANY, "Center Hole", wx.DefaultPosition, wx.DefaultSize,style=0, name='Info Text CEN')
        self.vBagMain.Add(self.MeasureInfo, (2, 0), flag=wx.EXPAND | wx.ALL, border=SMALLBORDER)
        
        # Approach distance X
        toolTipString="Approach distance in X direction to work piece"
        self.lefApprX= LeftLabeledEditField(self, wx.ID_ANY, "Approach distance X", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_9', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefApprX.typeOfValue = float
        self.lefApprX.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefApprX, (3, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Approach distance Y
        toolTipString="Approach distance in Y direction to work piece"
        self.lefApprY= LeftLabeledEditField(self, wx.ID_ANY, "Approach distance Y", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_11', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefApprY.typeOfValue = float
        self.lefApprY.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefApprY, (4, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Fast Advance I (X-axis) and J (Y-axis)
        toolTipString="Fast Advance I (X-axis), optional to shorten measurement time"
        self.lefFastAdvI= LeftLabeledEditField(self, wx.ID_ANY, "Fast Advance 'I' (X-axis)", min=0.0, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_10', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefFastAdvI.typeOfValue = float
        self.lefFastAdvI.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefFastAdvI, (5, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
             
        # Fast Advance J (Y-axis) 
        toolTipString="Fast Advance J (Y-axis), optional to shorten measurement time"
        self.lefFastAdvJ= LeftLabeledEditField(self, wx.ID_ANY, "Fast Advance 'J' (Y-axis)", min=0.0, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_12', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefFastAdvJ.typeOfValue = float
        self.lefFastAdvJ.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefFastAdvJ, (6, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Touching Angle (A)
        toolTipString="Specifies the angle for measurement direction."
        self.lefPosAng = LeftLabeledEditField(self, wx.ID_ANY, "Touching Angle (A). | (Possible values: -90.0° to 90.0°)", min=-90.0000, max=90.0000,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.ANGLE_VALUE, name='PAR_8', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefPosAng.typeOfValue = float
        self.lefPosAng.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefPosAng, (7, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # G92
        toolTipString="Temporarily Shift Coordinate System to current (measured) Wire Position."
        self.lefG92 = RealLeftLabeledDobbleEditFieldPickPos2(self, wx.ID_ANY, wx.ID_ANY, extraLabel = "G92", label1="X", label2="Y", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name1='PAR_6', name2='PAR_7', 
                                             toolTipString=toolTipString, bWithCheckbox=True, name="LLEFPP_G92")
        self.lefG92.typeOfValue = float
        self.lefG92.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefG92, (8, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Status Bar for string preview
        if not parent.statusbar:
            toolTipString="Preview of NC Code String."
            self.sttOutput = wx.StaticText(self, wx.ID_ANY, label="xxxxxxxxxx", pos=wx.DefaultPosition,
               size=wx.DefaultSize, style=0, name="STT_OUTPUT_COMMON", toolTipString=toolTipString) 
            self.sttOutput.SetFont(objFont)
            self.vBagMain.Add(self.sttOutput, (9, 0), (1, 2), flag=wx.EXPAND | wx.TOP, border=BORDER)
        
        # Make all rows and columns of the GridBagSizer dynamically change with panel size
        self.vBagMain.Layout()
        for col in range(self.vBagMain.GetCols()):
            self.vBagMain.AddGrowableCol(col)
        for row in range(self.vBagMain.GetRows()):
            self.vBagMain.AddGrowableRow(row)
        
        self.SetSizerAndFit(self.vBagMain)
            
        #### Bind events ####    
        self.Bind(wx.EVT_CHECKBOX, parent.OnLabeledEFCheckboxChecked)
        # Wire Settings Check Box
        self.cbCutWire.Bind(wx.EVT_CHECKBOX, parent.OnCutWireCheckboxChecked)
        self.cbThreadWire.Bind(wx.EVT_CHECKBOX, parent.OnThreadWireCheckboxChecked)
        # Text Field changes
        self.Bind(wx.EVT_TEXT, parent.OnLabeledEFTextCtrlChanged)
        # Profile Buttons
        self.btnProfileSave.Bind(wx.EVT_BUTTON, parent.OnSaveProfileButtonClicked)
        self.btnProfileLoad.Bind(wx.EVT_BUTTON, parent.OnLoadProfileButtonClicked)
        # Position Pick Buttons
        self.buttonPickPos.Bind(wx.EVT_BUTTON, parent.OnPickPositionPointButtonClicked)
        self.lefG92.Bind(wx.EVT_BUTTON, parent.OnPickPositionG92ButtonClicked)
        # Radio Buttons
        #self.rbPosAxisX.Bind(wx.EVT_RADIOBUTTON, parent.OnPosAxisRadioButtonSelectionChanged)
        ####################
        
        
class MyPanelMeasureCycleType3(scrolled.ScrolledPanel):
    def __init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL, name=""):  # @ReservedAssignment
        """
        This class defines and creates widgets for the sub dialog for measure cycle Type 3: 
        """
        self.isMainPanel=True
        self.parent = parent
        self.name=name
        self.title="CRN"
        scrolled.ScrolledPanel.__init__(self, parent, id=id, style=style, name=name)
        ##self.SetBackgroundColour('PINK')
        self.SetupScrolling(scroll_x=True, scroll_y=True)

        objFont = self.GetFont()

        self.vBagMain = wx.GridBagSizer(0, 0) # vgap 0, hgab 0
        
        # Sizer for wire cut settings
        vBoxWireSettings = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Wire Settings", name="STB_WIRE_SETTINGS"), wx.VERTICAL) # Draht Einstellungen
        self.cbThreadWire = OptiCheckBox(self, wx.ID_ANY, label="Thread wire before measurement (M06)", name='PAR_3') # de, Draht einfädeln
        vBoxWireSettings.Add(self.cbThreadWire, 1, wx.ALL | wx.EXPAND, SMALLBORDER)
        self.cbCutWire = OptiCheckBox(self, wx.ID_ANY, label="Cut wire after measurement (M07)", name='PAR_4') # de, Draht abscheiden  
        vBoxWireSettings.Add(self.cbCutWire, 1, wx.ALL | wx.EXPAND, SMALLBORDER)    
      
        self.vBagMain.Add(vBoxWireSettings, (0, 0), flag=wx.ALL | wx.EXPAND, border=MINIBORDER)
        
        # Main Sizer for First Point
        self.stbPickStart = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Measurement Start Point", name="STB_MEASURE_POINT_1"), wx.HORIZONTAL)              
        # Sub sizer for selection and position
        vBoxSubStartPos = wx.BoxSizer(wx.VERTICAL)
        self.stbPickStart.Add(vBoxSubStartPos, 1, flag= wx.EXPAND|wx.ALL)
              
        # X Position
        toolTipString="X Coordinate of Startpoint"
        self.lLEFXStart = LabeledEditField(self, wx.ID_ANY, "X", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_1',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFXStart.typeOfValue = float
        self.lLEFXStart.decimalDigitsOfOuput = 3
        self.stbPickStart.Add(self.lLEFXStart, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)      
        # Y Position
        toolTipString="Y Coordinate of Startpoint"
        self.lLEFYStart = LabeledEditField(self, wx.ID_ANY, "Y", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_2',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFYStart.typeOfValue = float
        self.lLEFYStart.decimalDigitsOfOuput = 3    
        self.stbPickStart.Add(self.lLEFYStart, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER) 
        # Position choice button
        toolTipString="Catch Coordinates"
        self.buttonPickPos = NormalButton(self, wx.ID_ANY, "XY>>",wx.DefaultPosition , size=(50, 25), style=0, name="_BTN_MEASURE_POINT_1XY", toolTipString=toolTipString)
        self.stbPickStart.Add(self.buttonPickPos, 0, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER) 
        
        self.vBagMain.Add(self.stbPickStart, (2, 0), flag=wx.ALL|wx.EXPAND, border=MINIBORDER)
     
        # Image part
        self.bmpX = getOpticamIcon('Makino_CRN_1.bmp')

        self.stBitmap = wx.StaticBitmap(self, id=wx.ID_ANY, bitmap=self.bmpX, pos=wx.DefaultPosition,
                                        size=wx.DefaultSize, style=0, name="IMG_MCY_TYPE3")

        self.vBagMain.Add(self.stBitmap, (0, 1), (2, 1), flag=wx.ALIGN_CENTER | wx.ALL , border=MINIBORDER)
        
        # Distance Lock part  
        vDistanceSettings = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Distance Settings", name="STB_DIST_SETTINGS"), wx.VERTICAL)
        self.rbDistKeep = OptiRadioButton(self, wx.ID_ANY, "Keep D1|D2 when changing Start Point", style=wx.RB_GROUP, name="RB_KEEP")
        self.rbDistAdj = OptiRadioButton(self, wx.ID_ANY, "Adjust D1|D2 when changing Start Point", style=0, name="RB_ADJ")
        self.rbDistReset = OptiRadioButton(self, wx.ID_ANY, "Reset D1|D2 when changing Start Point", style=0, name="RB_RESET")
        vDistanceSettings.Add(self.rbDistKeep,  1, wx.EXPAND|wx.ALL, MINIBORDER)
        vDistanceSettings.Add(self.rbDistAdj,  1, wx.EXPAND|wx.ALL, MINIBORDER)
        vDistanceSettings.Add(self.rbDistReset,  1, wx.EXPAND|wx.ALL, MINIBORDER)
 
        self.vBagMain.Add(vDistanceSettings, (1, 0), flag=wx.ALL | wx.EXPAND, border=MINIBORDER)

        # Profile Sizers - Save/Load  
        vProfile = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Profiles", name="STB_PROFILE"), wx.VERTICAL) # 
        hProfile = wx.BoxSizer(wx.HORIZONTAL)
        
        toolTipString="Transfer these entries to a database."
        self.btnProfileSave = NormalButton(self, wx.ID_ANY, "Save", wx.DefaultPosition, wx.DefaultSize, style=0, name='BTN_PROFILE_SAVE',toolTipString=toolTipString )
        toolTipString="View saved entries / load in the dialog."
        self.btnProfileLoad = NormalButton(self, wx.ID_ANY, "Load", wx.DefaultPosition, wx.DefaultSize, style=0, name='BTN_PROFILE_LOAD',toolTipString=toolTipString)
        hProfile.Add(self.btnProfileSave,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        hProfile.Add(self.btnProfileLoad,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        vProfile.Add(hProfile, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        self.vBagMain.Add(vProfile, (2, 1), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Info text marking the start of for cycle specific params
        self.MeasureInfo=TextField(self, wx.ID_ANY, "Corner Edge Positioning", wx.DefaultPosition, wx.DefaultSize,style=0, name='Info Text CRN')
        self.vBagMain.Add(self.MeasureInfo, (3, 0), flag=wx.EXPAND | wx.ALL, border=SMALLBORDER)
        
        # Approach distance X
        toolTipString="Distance to touch sensing start point in X direction"
        self.lefApprX = RealLeftLabeledDobbleEditFieldPickPos(self, wx.ID_ANY, wx.ID_ANY, label1="Distance to touch sensing start point X | D1", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name1='PAR_9', name="_BTN_MEASURE_POINT_2XY",
                                             toolTipString=toolTipString, bWithCheckbox=False)
        self.lefApprX.typeOfValue = float
        self.lefApprX.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefApprX, (4, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Approach distance Y
        toolTipString="Distance to touch sensing start point in Y direction"
        self.lefApprY = RealLeftLabeledDobbleEditFieldPickPos(self, wx.ID_ANY, wx.ID_ANY, label1="Distance to touch sensing start point Y | D2", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name1='PAR_11', name="_BTN_MEASURE_POINT_3XY",
                                             toolTipString=toolTipString, bWithCheckbox=False)
        self.lefApprY.typeOfValue = float
        self.lefApprY.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefApprY, (5, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Fast Advance I (X-axis)
        toolTipString="Fast Advance I (X-axis), optional to shorten measurement time"
        self.lefFastAdvI= LeftLabeledEditField(self, wx.ID_ANY, "Fast Advance 'I' (X-axis)", min=0.0, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_10', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefFastAdvI.typeOfValue = float
        self.lefFastAdvI.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefFastAdvI, (6, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
              
        # Fast Advance J (Y-axis) 
        toolTipString="Fast Advance J (Y-axis), optional to shorten measurement time"
        self.lefFastAdvJ= LeftLabeledEditField(self, wx.ID_ANY, "Fast Advance 'J' (Y-axis)", min=0.0, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_12', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefFastAdvJ.typeOfValue = float
        self.lefFastAdvJ.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefFastAdvJ, (7, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Workpiece Inclination (A)
        toolTipString="Specifies a previously saved Workpiece inclination value (e.g. measured my Workpiece Parallelism)"
        self.lefWorkpInc = LeftLabeledEditField(self, wx.ID_ANY, "Workpiece Inclination (A) | (Possible values: 0 to 9)", min=0, max=9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.INTEGER, name='PAR_13', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefWorkpInc.typeOfValue = int
        self.vBagMain.Add(self.lefWorkpInc, (8, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
              
        # G92
        toolTipString="Temporarily Shift Coordinate System to current (measured) Wire Position.\nATTENTION! Please consider the Wire Diameter!"
        self.lefG92 = RealLeftLabeledDobbleEditFieldPickPos2(self, wx.ID_ANY, wx.ID_ANY, extraLabel = "G92", label1="X", label2="Y", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name1='PAR_6', name2='PAR_7', 
                                             toolTipString=toolTipString, bWithCheckbox=True, name="LLEFPP_G92")
        self.lefG92.typeOfValue = float
        self.lefG92.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefG92, (9, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Status Bar for string preview
        if not parent.statusbar:
            toolTipString="Preview of NC Code String."
            self.sttOutput = wx.StaticText(self, wx.ID_ANY, label="xxxxxxxxxx", pos=wx.DefaultPosition,
               size=wx.DefaultSize, style=0, name="STT_OUTPUT_COMMON", toolTipString=toolTipString) 
            self.sttOutput.SetFont(objFont)
            self.vBagMain.Add(self.sttOutput, (10, 0), (1, 2), flag=wx.EXPAND | wx.TOP, border=BORDER)
        
        # Make all rows and columns of the GridBagSizer dynamically change with panel size
        self.vBagMain.Layout()
        for col in range(self.vBagMain.GetCols()):
            self.vBagMain.AddGrowableCol(col)
        for row in range(self.vBagMain.GetRows()):
            self.vBagMain.AddGrowableRow(row)
        
        self.SetSizerAndFit(self.vBagMain)
            
        #### Bind events ####    
        self.Bind(wx.EVT_CHECKBOX, parent.OnLabeledEFCheckboxChecked)
        # Wire Settings Check Box
        self.cbCutWire.Bind(wx.EVT_CHECKBOX, parent.OnCutWireCheckboxChecked)
        self.cbThreadWire.Bind(wx.EVT_CHECKBOX, parent.OnThreadWireCheckboxChecked)
        # Distance Lock Radio Buttons
        self.rbDistKeep.Bind(wx.EVT_RADIOBUTTON, parent.OnDistanceSettingsClicked)
        self.rbDistAdj.Bind(wx.EVT_RADIOBUTTON, parent.OnDistanceSettingsClicked)
        self.rbDistReset.Bind(wx.EVT_RADIOBUTTON, parent.OnDistanceSettingsClicked)
        # Text Field changes
        self.Bind(wx.EVT_TEXT, parent.OnLabeledEFTextCtrlChanged)
        # Profile Buttons
        self.btnProfileSave.Bind(wx.EVT_BUTTON, parent.OnSaveProfileButtonClicked)
        self.btnProfileLoad.Bind(wx.EVT_BUTTON, parent.OnLoadProfileButtonClicked)
        # Position Pick Buttons
        self.buttonPickPos.Bind(wx.EVT_BUTTON, parent.OnPickPositionPointButtonClicked)
        self.lefApprX.Bind(wx.EVT_BUTTON, parent.OnPickPositionPointButtonClicked)
        self.lefApprY.Bind(wx.EVT_BUTTON, parent.OnPickPositionPointButtonClicked)
        self.lefG92.Bind(wx.EVT_BUTTON, parent.OnPickPositionG92ButtonClicked)
        ####################
        
    def WriteDistances(self, x2=None, y3=None):
        # Get Values of Start point
        setattr(self, "x1", (self.lLEFXStart.GetValue()))
        setattr(self, "y1", (self.lLEFYStart.GetValue()))
        
        # P1 must exist 
        if getattr(self, "x1", None) is not None and getattr(self, "y1", None) is not None:               
            # Calculate and set D1
            if x2 is not None:
                d1 = round((x2 - self.x1), self.lefApprX.decimalDigitsOfOuput)
                self.lefApprX.llef1.edit.SetValue(d1)
            # Calculate and set D2
            if y3 is not None:
                d2 = round((y3 - self.y1), self.lefApprY.decimalDigitsOfOuput)
                self.lefApprY.llef1.edit.SetValue(d2)
                                 
        
class MyPanelMeasureCycleType4(scrolled.ScrolledPanel):
    def __init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL, name=""):  # @ReservedAssignment
        """
        This class defines and creates widgets for the sub dialog for measure cycle Type 4: 
        """
        self.isMainPanel=True
        self.parent = parent
        self.name=name
        self.title="MID"
        scrolled.ScrolledPanel.__init__(self, parent, id=id, style=style, name=name)
        ##self.SetBackgroundColour('PINK')
        self.SetupScrolling(scroll_x=True, scroll_y=True)

        objFont = self.GetFont()

        self.vBagMain = wx.GridBagSizer(0, 0) # vgap 0, hgab 0
        
        # Sizer for wire cut settings
        vBoxWireSettings = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Wire Settings", name="STB_WIRE_SETTINGS"), wx.VERTICAL) # Draht Einstellungen
        self.cbThreadWire = OptiCheckBox(self, wx.ID_ANY, label="Thread wire before measurement (M06)", name='PAR_3') # de, Draht einfädeln
        vBoxWireSettings.Add(self.cbThreadWire, 1, wx.ALL | wx.EXPAND, SMALLBORDER)
        self.cbCutWire = OptiCheckBox(self, wx.ID_ANY, label="Cut wire after measurement (M07)", name='PAR_4') # de, Draht abscheiden  
        vBoxWireSettings.Add(self.cbCutWire, 1, wx.ALL | wx.EXPAND, SMALLBORDER)    
      
        self.vBagMain.Add(vBoxWireSettings, (0, 0), flag=wx.ALL | wx.EXPAND, border=MINIBORDER)
        
        # Main Sizer for First Point
        self.stbPickStart = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Measurement Start Point", name="STB_MEASURE_POINT_1"), wx.HORIZONTAL)              
        # Sub sizer for selection and position
        vBoxSubStartPos = wx.BoxSizer(wx.VERTICAL)
        self.stbPickStart.Add(vBoxSubStartPos, 1, flag= wx.EXPAND|wx.ALL)
        
        # X Position
        toolTipString="X Coordinate of Startpoint"
        self.lLEFXStart = LabeledEditField(self, wx.ID_ANY, "X", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_1',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFXStart.typeOfValue = float
        self.lLEFXStart.decimalDigitsOfOuput = 3
        self.stbPickStart.Add(self.lLEFXStart, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)      
        # Y Position
        toolTipString="Y Coordinate of Startpoint"
        self.lLEFYStart = LabeledEditField(self, wx.ID_ANY, "Y", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_2',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFYStart.typeOfValue = float
        self.lLEFYStart.decimalDigitsOfOuput = 3    
        self.stbPickStart.Add(self.lLEFYStart, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)
        # Position choice button
        toolTipString="Catch Coordinates"
        self.buttonPickPos = NormalButton(self, wx.ID_ANY, "XY>>",wx.DefaultPosition , size=(50, 25), style=0, name="_BTN_MEASURE_POINT_1XY", toolTipString=toolTipString)
        self.stbPickStart.Add(self.buttonPickPos, 0, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)
        
        self.vBagMain.Add(self.stbPickStart, (2, 0), flag=wx.ALL|wx.EXPAND, border=MINIBORDER)
     
        # Image part
        self.bmpX = getOpticamIcon('Makino_MID_1.bmp')
        self.bmpY = getOpticamIcon('Makino_MID_2.bmp')

        self.stBitmap = wx.StaticBitmap(self, id=wx.ID_ANY, bitmap=self.bmpX, pos=wx.DefaultPosition,
                                        size=wx.DefaultSize, style=0, name="IMG_MCY_TYPE4")

        self.vBagMain.Add(self.stBitmap, (0, 1), (2, 1), flag=wx.ALIGN_CENTER | wx.ALL , border=MINIBORDER)
        
        # Cycle Rotation part
        self.stbTouchDir = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Touch Sensing Direction", name="STB_TOUCH_DIR"), wx.VERTICAL)
        hTouchdir1 = wx.BoxSizer(wx.HORIZONTAL)
        self.rbDirXPlus = OptiRadioButton(self, wx.ID_ANY, "X", style=wx.RB_GROUP, name="PAR_5")
        self.rbDirYPlus = OptiRadioButton(self, wx.ID_ANY, "Y", style=0, name="RB_DIR_Y")
        hTouchdir1.Add(self.rbDirXPlus,  1, wx.EXPAND, SMALLBORDER)
        hTouchdir1.Add(self.rbDirYPlus,  1, wx.EXPAND, SMALLBORDER)
        self.stbTouchDir.Add(hTouchdir1, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        
        self.vBagMain.Add(self.stbTouchDir, (1, 0), (1, 1), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)

        # Profile Sizers - Save/Load  
        vProfile = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Profiles", name="STB_PROFILE"), wx.VERTICAL) # 
        hProfile = wx.BoxSizer(wx.HORIZONTAL)
        
        toolTipString="Transfer these entries to a database."
        self.btnProfileSave = NormalButton(self, wx.ID_ANY, "Save", wx.DefaultPosition, wx.DefaultSize, style=0, name='BTN_PROFILE_SAVE',toolTipString=toolTipString )
        toolTipString="View saved entries / load in the dialog."
        self.btnProfileLoad = NormalButton(self, wx.ID_ANY, "Load", wx.DefaultPosition, wx.DefaultSize, style=0, name='BTN_PROFILE_LOAD',toolTipString=toolTipString)
        hProfile.Add(self.btnProfileSave,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        hProfile.Add(self.btnProfileLoad,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        vProfile.Add(hProfile, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        self.vBagMain.Add(vProfile, (2, 1), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Info text marking the start of for cycle specific params
        self.MeasureInfo=TextField(self, wx.ID_ANY, "Groove Width Center Positioning", wx.DefaultPosition, wx.DefaultSize,style=0, name='Info Text MID')
        self.vBagMain.Add(self.MeasureInfo, (3, 0), flag=wx.EXPAND | wx.ALL, border=SMALLBORDER)
        
        # Approach distance X
        toolTipString="Touch Sensing distance in X direction to work piece"
        self.lefApprX= LeftLabeledEditField(self, wx.ID_ANY, "Touch sensing distance X", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_9', toolTipString=toolTipString, bWithCheckbox=False)
        self.lefApprX.typeOfValue = float
        self.lefApprX.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefApprX, (4, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Fast Advance I (X-axis) and J (Y-axis)
        toolTipString="Fast Advance I (X-axis), optional to shorten measurement time"
        self.lefFastAdvI= LeftLabeledEditField(self, wx.ID_ANY, "Fast Advance 'I' (X-axis)", min=0.0, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_10', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefFastAdvI.typeOfValue = float
        self.lefFastAdvI.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefFastAdvI, (5, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Approach distance Y
        toolTipString="Touch Sensing distance in Y direction to work piece"
        self.lefApprY= LeftLabeledEditField(self, wx.ID_ANY, "Touch sensing distance Y", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_11', toolTipString=toolTipString, bWithCheckbox=False)
        self.lefApprY.typeOfValue = float
        self.lefApprY.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefApprY, (6, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
             
        # Fast Advance J (Y-axis) 
        toolTipString="Fast Advance J (Y-axis), optional to shorten measurement time"
        self.lefFastAdvJ= LeftLabeledEditField(self, wx.ID_ANY, "Fast Advance 'J' (Y-axis)", min=0.0, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_12', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefFastAdvJ.typeOfValue = float
        self.lefFastAdvJ.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefFastAdvJ, (7, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Touching Angle (A)
        toolTipString="Specifies the angle for measurement direction."
        self.lefPosAng = LeftLabeledEditField(self, wx.ID_ANY, "Touching Angle (A) | (Possible values: -90.0° to 90.0°)", min=-90.0000, max=90.0000,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.ANGLE_VALUE, name='PAR_8', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefPosAng.typeOfValue = float
        self.lefPosAng.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefPosAng, (8, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
              
        # G92
        toolTipString="Temporarily Shift Coordinate System to current (measured) Wire Position."
        self.lefG92 = RealLeftLabeledDobbleEditFieldPickPos2(self, wx.ID_ANY, wx.ID_ANY, extraLabel = "G92", label1="X", label2="Y", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name1='PAR_6', name2='PAR_7', 
                                             toolTipString=toolTipString, bWithCheckbox=True, name="LLEFPP_G92")
        self.lefG92.typeOfValue = float
        self.lefG92.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefG92, (9, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Status Bar for string preview
        if not parent.statusbar:
            toolTipString="Preview of NC Code String."
            self.sttOutput = wx.StaticText(self, wx.ID_ANY, label="xxxxxxxxxx", pos=wx.DefaultPosition,
               size=wx.DefaultSize, style=0, name="STT_OUTPUT_COMMON", toolTipString=toolTipString) 
            self.sttOutput.SetFont(objFont)
            self.vBagMain.Add(self.sttOutput, (10, 0), (1, 2), flag=wx.EXPAND | wx.TOP, border=BORDER)
        
        # Make all rows and columns of the GridBagSizer dynamically change with panel size
        self.vBagMain.Layout()
        for col in range(self.vBagMain.GetCols()):
            self.vBagMain.AddGrowableCol(col)
        for row in range(self.vBagMain.GetRows()):
            self.vBagMain.AddGrowableRow(row)
        
        self.SetSizerAndFit(self.vBagMain)
            
        #### Bind events ####    
        self.Bind(wx.EVT_CHECKBOX, parent.OnLabeledEFCheckboxChecked)
        # Wire Settings Check Box
        self.cbCutWire.Bind(wx.EVT_CHECKBOX, parent.OnCutWireCheckboxChecked)
        self.cbThreadWire.Bind(wx.EVT_CHECKBOX, parent.OnThreadWireCheckboxChecked)
        # Text Field changes
        self.Bind(wx.EVT_TEXT, parent.OnLabeledEFTextCtrlChanged)
        # Profile Buttons
        self.btnProfileSave.Bind(wx.EVT_BUTTON, parent.OnSaveProfileButtonClicked)
        self.btnProfileLoad.Bind(wx.EVT_BUTTON, parent.OnLoadProfileButtonClicked)
        # Position Pick Buttons
        self.buttonPickPos.Bind(wx.EVT_BUTTON, parent.OnPickPositionPointButtonClicked)
        self.lefG92.Bind(wx.EVT_BUTTON, parent.OnPickPositionG92ButtonClicked)
        # Radio Rotation Buttons
        self.rbDirXPlus.Bind(wx.EVT_RADIOBUTTON, partial(parent.OnRadioBoxMeasureDirectionClicked, vDir='+X'))
        self.rbDirYPlus.Bind(wx.EVT_RADIOBUTTON, partial(parent.OnRadioBoxMeasureDirectionClicked, vDir='+Y'))
        ####################
        
        
class MyPanelMeasureCycleType5(scrolled.ScrolledPanel):
    def __init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL, name=""):  # @ReservedAssignment
        """
        This class defines and creates widgets for the sub dialog for measure cycle Type 5: 
        """
        self.isMainPanel=True
        self.parent = parent
        self.name=name
        self.title="PLM"
        scrolled.ScrolledPanel.__init__(self, parent, id=id, style=style, name=name)
        ##self.SetBackgroundColour('PINK')
        self.SetupScrolling(scroll_x=True, scroll_y=True)

        objFont = self.GetFont()

        self.vBagMain = wx.GridBagSizer(0, 0) # vgap 0, hgab 0
        
        # Sizer for wire cut settings
        vBoxWireSettings = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Wire Settings", name="STB_WIRE_SETTINGS"), wx.VERTICAL) # Draht Einstellungen
        self.cbThreadWire = OptiCheckBox(self, wx.ID_ANY, label="Thread wire before measurement (M06)", name='PAR_3') # de, Draht einfädeln
        vBoxWireSettings.Add(self.cbThreadWire, 1, wx.ALL | wx.EXPAND, SMALLBORDER)
        self.cbCutWire = OptiCheckBox(self, wx.ID_ANY, label="Cut wire after measurement (M07)", name='PAR_4') # de, Draht abscheiden  
        vBoxWireSettings.Add(self.cbCutWire, 1, wx.ALL | wx.EXPAND, SMALLBORDER)    
      
        self.vBagMain.Add(vBoxWireSettings, (0, 0), flag=wx.ALL | wx.EXPAND, border=MINIBORDER)
        
        # Main Sizer for First Point
        self.stbPickStart = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Measurement Start Point", name="STB_MEASURE_POINT_1"), wx.HORIZONTAL)              
        # Sub sizer for selection and position
        vBoxSubStartPos = wx.BoxSizer(wx.VERTICAL)
        hBoxSubStartPos = wx.BoxSizer(wx.HORIZONTAL)
        vBoxSubStartPos.Add(hBoxSubStartPos, 1, flag= wx.EXPAND|wx.ALL)
        
        # X Position
        toolTipString="X Coordinate of Startpoint"
        self.lLEFXStart = LabeledEditField(self, wx.ID_ANY, "X", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_1',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFXStart.typeOfValue = float
        self.lLEFXStart.decimalDigitsOfOuput = 3
        hBoxSubStartPos.Add(self.lLEFXStart, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)      
        # Y Position
        toolTipString="Y Coordinate of Startpoint"
        self.lLEFYStart = LabeledEditField(self, wx.ID_ANY, "Y", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_2',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFYStart.typeOfValue = float
        self.lLEFYStart.decimalDigitsOfOuput = 3    
        hBoxSubStartPos.Add(self.lLEFYStart, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)  
        # Position choice button
        toolTipString="Catch Coordinates"
        self.buttonPickPos = NormalButton(self, wx.ID_ANY, "XY>>",wx.DefaultPosition , size=(50, 25), style=0, name="_BTN_MEASURE_POINT_1XY", toolTipString=toolTipString)
        hBoxSubStartPos.Add(self.buttonPickPos, 0, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)
        # Reset or Keep Distances
        self.cbDistReset = OptiCheckBox(self, wx.ID_ANY, label="Reset Distances on Start Point change", name='STB_DISTANCE_RESET')
        self.cbDistReset.SetValue(False)
        vBoxSubStartPos.Add(self.cbDistReset, 1, wx.ALL | wx.EXPAND, SMALLBORDER)
        
        self.stbPickStart.Add(vBoxSubStartPos, 1, flag= wx.EXPAND|wx.ALL)
              
        self.vBagMain.Add(self.stbPickStart, (1, 0), flag=wx.ALL|wx.EXPAND, border=MINIBORDER)
        
        # Main Sizer for Second Point
        self.stbTouchP = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Touch Sensing Start Points", name="STB_MEASURE_POINT_2"), wx.VERTICAL)              
        # Sub sizer for selection and position
        hBoxSubP2 = wx.BoxSizer(wx.HORIZONTAL)
        hBoxSubP3 = wx.BoxSizer(wx.HORIZONTAL)
        self.stbTouchP.Add(hBoxSubP2, 1, flag= wx.EXPAND|wx.ALL)
        self.stbTouchP.Add(hBoxSubP3, 1, flag= wx.EXPAND|wx.ALL)
              
        # X Position P2
        toolTipString="X Coordinate of P2"
        self.lLEFXP2 = LabeledEditField(self, wx.ID_ANY, "X", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_17',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFXP2.typeOfValue = float
        self.lLEFXP2.decimalDigitsOfOuput = 3
        hBoxSubP2.Add(self.lLEFXP2, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)      
        # Y Position P2
        toolTipString="Y Coordinate of P2"
        self.lLEFYP2 = LabeledEditField(self, wx.ID_ANY, "Y", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_18',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFYP2.typeOfValue = float
        self.lLEFYP2.decimalDigitsOfOuput = 3    
        hBoxSubP2.Add(self.lLEFYP2, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER) 
            
        # X Position P3
        toolTipString="X Coordinate of P3"
        self.lLEFXP3 = LabeledEditField(self, wx.ID_ANY, "X", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_15',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFXP3.typeOfValue = float
        self.lLEFXP3.decimalDigitsOfOuput = 3
        hBoxSubP3.Add(self.lLEFXP3, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)      
        # Y Position P3
        toolTipString="Y Coordinate of P3"
        self.lLEFYP3 = LabeledEditField(self, wx.ID_ANY, "Y", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_16',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFYP3.typeOfValue = float
        self.lLEFYP3.decimalDigitsOfOuput = 3    
        hBoxSubP3.Add(self.lLEFYP3, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER) 

        self.vBagMain.Add(self.stbTouchP, (2, 0), (2, 1), flag=wx.ALL|wx.EXPAND, border=MINIBORDER)
     
        # Image part
        self.bmpX = getOpticamIcon('Makino_PLM_1.bmp')
        self.bmpY = getOpticamIcon('Makino_PLM_2.bmp')

        self.stBitmap = wx.StaticBitmap(self, id=wx.ID_ANY, bitmap=self.bmpX, pos=wx.DefaultPosition,
                                        size=wx.DefaultSize, style=0, name="IMG_MCY_TYPE5")

        self.vBagMain.Add(self.stBitmap, (0, 1), (2, 1), flag=wx.ALIGN_CENTER | wx.ALL , border=MINIBORDER)
        
        # Cycle Rotation part
        self.stbTouchDir = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Touching Direction", name="STB_TOUCH_DIR"), wx.VERTICAL)
        hTouchDir1 = wx.BoxSizer(wx.HORIZONTAL)
        self.rbDirXPlus = OptiRadioButton(self, wx.ID_ANY, "X", style=wx.RB_GROUP, name="PAR_5")
        self.rbDirYPlus = OptiRadioButton(self, wx.ID_ANY, "Y", style=0, name="RB_DIR_Y")
        hTouchDir1.Add(self.rbDirXPlus,  1, wx.EXPAND, SMALLBORDER)
        hTouchDir1.Add(self.rbDirYPlus,  1, wx.EXPAND, SMALLBORDER)
        self.stbTouchDir.Add(hTouchDir1, 1, wx.EXPAND | wx.ALL, SMALLBORDER)

        self.vBagMain.Add(self.stbTouchDir, (2, 1), (1, 1), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)

        # Profile Sizers - Save/Load  
        vProfile = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Profiles", name="STB_PROFILE"), wx.VERTICAL) # 
        hProfile = wx.BoxSizer(wx.HORIZONTAL)
        
        toolTipString="Transfer these entries to a database."
        self.btnProfileSave = NormalButton(self, wx.ID_ANY, "Save", wx.DefaultPosition, wx.DefaultSize, style=0, name='BTN_PROFILE_SAVE',toolTipString=toolTipString )
        toolTipString="View saved entries / load in the dialog."
        self.btnProfileLoad = NormalButton(self, wx.ID_ANY, "Load", wx.DefaultPosition, wx.DefaultSize, style=0, name='BTN_PROFILE_LOAD',toolTipString=toolTipString)
        hProfile.Add(self.btnProfileSave,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        hProfile.Add(self.btnProfileLoad,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        vProfile.Add(hProfile, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        self.vBagMain.Add(vProfile, (3, 1), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Info text marking the start of for cycle specific params
        self.MeasureInfo=TextField(self, wx.ID_ANY, "Plate Width Centering", wx.DefaultPosition, wx.DefaultSize,style=0, name='Info Text PLM')
        self.vBagMain.Add(self.MeasureInfo, (4, 0), flag=wx.EXPAND | wx.ALL, border=SMALLBORDER)
        
        # Approach distance X
        toolTipString="Moving distance in X direction | D1 and Moving distance in Y direction | D2"
        self.rlefApprXY= RealLeftLabeledDobbleEditFieldPickPos(self, wx.ID_ANY, wx.ID_ANY, label1="Moving distance X | D1", label2 = "Moving distance Y | D2", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name1='PAR_9', name2="PAR_11", name="_RLLEF_DISTANCE_DXY",
                                             toolTipString=toolTipString, bWithCheckbox=False)
        self.rlefApprXY.typeOfValue = float
        self.rlefApprXY.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.rlefApprXY, (5, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Fast Advance I (X-axis) and J (Y-axis)
        toolTipString="Fast Advance I (X-axis), optional to shorten measurement time"
        self.lefFastAdvI= LeftLabeledEditField(self, wx.ID_ANY, "Fast Advance I (X-axis)", min=0.0, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_10', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefFastAdvI.typeOfValue = float
        self.lefFastAdvI.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefFastAdvI, (6, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
             
        # Fast Advance J (Y-axis) 
        toolTipString="Fast Advance J (Y-axis), optional to shorten measurement time"
        self.lefFastAdvJ= LeftLabeledEditField(self, wx.ID_ANY, "Fast Advance J (Y-axis)", min=0.0, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_12', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefFastAdvJ.typeOfValue = float
        self.lefFastAdvJ.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefFastAdvJ, (7, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Touching Angle (A)
        toolTipString="Specifies the angle for measurement direction."
        self.lefPosAng = LeftLabeledEditField(self, wx.ID_ANY, "Touching Angle (A) | (Possible values: -90.0° to 90.0°)", min=-90.0000, max=90.0000,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.ANGLE_VALUE, name='PAR_8', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefPosAng.typeOfValue = float
        self.lefPosAng.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefPosAng, (8, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
              
        # G92
        toolTipString="Temporarily Shift Coordinate System to current (measured) Wire Position."
        self.lefG92 = RealLeftLabeledDobbleEditFieldPickPos2(self, wx.ID_ANY, wx.ID_ANY, extraLabel = "G92", label1="X", label2="Y", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name1='PAR_6', name2='PAR_7', 
                                             toolTipString=toolTipString, bWithCheckbox=True, name="LLEFPP_G92")
        self.lefG92.typeOfValue = float
        self.lefG92.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefG92, (9, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Status Bar for string preview
        if not parent.statusbar:
            toolTipString="Preview of NC Code String."
            self.sttOutput = wx.StaticText(self, wx.ID_ANY, label="xxxxxxxxxx", pos=wx.DefaultPosition,
               size=wx.DefaultSize, style=0, name="STT_OUTPUT_COMMON", toolTipString=toolTipString) 
            self.sttOutput.SetFont(objFont)
            self.vBagMain.Add(self.sttOutput, (10, 0), (1, 2), flag=wx.EXPAND | wx.TOP, border=BORDER)
        
        # Make all rows and columns of the GridBagSizer dynamically change with panel size
        self.vBagMain.Layout()
        for col in range(self.vBagMain.GetCols()):
            self.vBagMain.AddGrowableCol(col)
        for row in range(self.vBagMain.GetRows()):
            self.vBagMain.AddGrowableRow(row)
        
        self.SetSizerAndFit(self.vBagMain)
            
        #### Bind events ####    
        self.Bind(wx.EVT_CHECKBOX, parent.OnLabeledEFCheckboxChecked)
        self.cbDistReset.Bind(wx.EVT_CHECKBOX, parent.OnDistanceResetCheckboxChecked)
        # Wire Settings Check Box
        self.cbCutWire.Bind(wx.EVT_CHECKBOX, parent.OnCutWireCheckboxChecked)
        self.cbThreadWire.Bind(wx.EVT_CHECKBOX, parent.OnThreadWireCheckboxChecked)
        # Text Field changes
        self.rlefApprXY.Bind(wx.EVT_TEXT, parent.OnLabeledEFTextCtrlChanged)
        self.lLEFXStart.Bind(wx.EVT_TEXT, parent.OnLabeledEFTextCtrlChanged)
        self.lLEFYStart.Bind(wx.EVT_TEXT, parent.OnLabeledEFTextCtrlChanged)
        self.lefFastAdvI.Bind(wx.EVT_TEXT, parent.OnLabeledEFTextCtrlChanged)
        self.lefFastAdvJ.Bind(wx.EVT_TEXT, parent.OnLabeledEFTextCtrlChanged)
        self.lefPosAng.Bind(wx.EVT_TEXT, parent.OnLabeledEFTextCtrlChanged)
        # Profile Buttons
        self.btnProfileSave.Bind(wx.EVT_BUTTON, parent.OnSaveProfileButtonClicked)
        self.btnProfileLoad.Bind(wx.EVT_BUTTON, parent.OnLoadProfileButtonClicked)
        # Position Pick Buttons
        self.buttonPickPos.Bind(wx.EVT_BUTTON, parent.OnPickPositionPointButtonClicked)
        self.rlefApprXY.Bind(wx.EVT_BUTTON, parent.OnPickPositionPointButtonClicked)
        self.lefG92.Bind(wx.EVT_BUTTON, parent.OnPickPositionG92ButtonClicked)
        # Radio Rotation Buttons
        self.rbDirXPlus.Bind(wx.EVT_RADIOBUTTON, partial(parent.OnRadioBoxMeasureDirectionClicked, vDir='+X'))
        self.rbDirYPlus.Bind(wx.EVT_RADIOBUTTON, partial(parent.OnRadioBoxMeasureDirectionClicked, vDir='+Y'))
        ####################
        
    def WriteDistances(self, x2=None, y3=None):
        # Get Values of Start point
        setattr(self, "x1", (self.lLEFXStart.GetValue()))
        setattr(self, "y1", (self.lLEFYStart.GetValue()))
        
        if self.rbDirXPlus.Value == True:
            x_fac = 2
            y_fac = 1
        else:
            x_fac = 1
            y_fac = 2
        
        # P1 must exist 
        if getattr(self, "x1", None) is not None and getattr(self, "y1", None) is not None:               
            # Calculate and set D1
            if x2 is not None:
                d1 = round((x2 - self.x1), self.rlefApprXY.decimalDigitsOfOuput)*x_fac
                if x_fac == 2:
                    d1=abs(d1)
                self.rlefApprXY.llef1.edit.SetValue(d1)
            # Calculate and set D2
            if y3 is not None:
                d2 = round((y3 - self.y1), self.rlefApprXY.decimalDigitsOfOuput)*y_fac
                if y_fac == 2:
                    d2=abs(d2)
                self.rlefApprXY.llef2.edit.SetValue(d2)
                
        
class MyPanelMeasureCycleType6(scrolled.ScrolledPanel):
    def __init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL, name=""):  # @ReservedAssignment
        """
        This class defines and creates widgets for the sub dialog for measure cycle Type 6: 
        """
        self.isMainPanel=True
        self.parent = parent
        self.name=name
        self.title="EXC"
        scrolled.ScrolledPanel.__init__(self, parent, id=id, style=style, name=name)
        #self.SetBackgroundColour('SKY BLUE')
        self.SetupScrolling(scroll_x=True, scroll_y=True)

        objFont = self.GetFont()

        self.vBagMain = wx.GridBagSizer(0, 0) # vgap 0, hgab 0
        
        # Sizer for wire cut settings
        vBoxWireSettings = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Wire Settings", name="STB_WIRE_SETTINGS"), wx.VERTICAL) # Draht Einstellungen
        self.cbThreadWire = OptiCheckBox(self, wx.ID_ANY, label="Thread wire before measurement (M06)", name='PAR_3') # de, Draht einfädeln
        vBoxWireSettings.Add(self.cbThreadWire, 1, wx.ALL | wx.EXPAND, SMALLBORDER)
        self.cbCutWire = OptiCheckBox(self, wx.ID_ANY, label="Cut wire after measurement (M07)", name='PAR_4') # de, Draht abscheiden  
        vBoxWireSettings.Add(self.cbCutWire, 1, wx.ALL | wx.EXPAND, SMALLBORDER)    
      
        self.vBagMain.Add(vBoxWireSettings, (0, 0), flag=wx.ALL | wx.EXPAND, border=MINIBORDER)
        
        # Main Sizer for First Point
        self.stbPickStart = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Measurement Circle Start Point (1)", name="STB_MEASURE_POINT_1"), wx.HORIZONTAL)              
        # Sub sizer for selection and position
        vBoxSubStartPos = wx.BoxSizer(wx.VERTICAL)
        self.stbPickStart.Add(vBoxSubStartPos, 1, flag= wx.EXPAND|wx.ALL)
              
        # X Position
        toolTipString="X Coordinate of Startpoint"
        self.lLEFXStart = LabeledEditField(self, wx.ID_ANY, "X", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_1',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFXStart.typeOfValue = float
        self.lLEFXStart.decimalDigitsOfOuput = 3
        self.stbPickStart.Add(self.lLEFXStart, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)      
        # Y Position
        toolTipString="Y Coordinate of Startpoint"
        self.lLEFYStart = LabeledEditField(self, wx.ID_ANY, "Y", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_2',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFYStart.typeOfValue = float
        self.lLEFYStart.decimalDigitsOfOuput = 3    
        self.stbPickStart.Add(self.lLEFYStart, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)
        # Position choice button
        toolTipString="Catch Coordinates"
        self.buttonPickPos = NormalButton(self, wx.ID_ANY, "XY>>",wx.DefaultPosition , size=(50, 25), style=0, name="_BTN_MEASURE_POINT_1XY", toolTipString=toolTipString)
        self.stbPickStart.Add(self.buttonPickPos, 0, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)  
        
        self.vBagMain.Add(self.stbPickStart, (1, 0), flag=wx.ALL|wx.EXPAND, border=MINIBORDER)
        
        # Main Sizer for Second Point
        self.stbPickP2 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Measurement Circle Center Point (2)", name="STB_MEASURE_POINT_2"), wx.HORIZONTAL)              
        # Sub sizer for selection and position
        vBoxSubP2 = wx.BoxSizer(wx.VERTICAL)
        self.stbPickP2.Add(vBoxSubP2, 1, flag= wx.EXPAND|wx.ALL)
              
        # X Position
        toolTipString="X Coordinate of circle center point"
        self.lLEFXP2 = LabeledEditField(self, wx.ID_ANY, "X", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_17',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFXP2.typeOfValue = float
        self.lLEFXP2.decimalDigitsOfOuput = 3
        self.stbPickP2.Add(self.lLEFXP2, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)      
        # Y Position
        toolTipString="Y Coordinate of circle center point"
        self.lLEFYP2 = LabeledEditField(self, wx.ID_ANY, "Y", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_18',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFYP2.typeOfValue = float
        self.lLEFYP2.decimalDigitsOfOuput = 3    
        self.stbPickP2.Add(self.lLEFYP2, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER) 
        # Position choice button
        toolTipString="Catch Coordinates of circle center point"
        self.buttonPickP2 = NormalButton(self, wx.ID_ANY, "XY>>",wx.DefaultPosition , size=(50, 25), style=0, name="_BTN_MEASURE_POINT_2XY", toolTipString=toolTipString)
        self.stbPickP2.Add(self.buttonPickP2, 0, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)      
        self.vBagMain.Add(self.stbPickP2, (2, 0), flag=wx.ALL|wx.EXPAND, border=MINIBORDER)
        
        # Main Sizer for Third Point
        self.stbPickP3 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Measurement Circle End Point (3)", name="STB_MEASURE_POINT_3"), wx.HORIZONTAL)              
        # Sub sizer for selection and position
        vBoxSubP3 = wx.BoxSizer(wx.VERTICAL)
        self.stbPickP3.Add(vBoxSubP3, 1, flag= wx.EXPAND|wx.ALL)
              
        # X Position
        toolTipString="X Coordinate of end point"
        self.lLEFXP3 = LabeledEditField(self, wx.ID_ANY, "X", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_15',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFXP3.typeOfValue = float
        self.lLEFXP3.decimalDigitsOfOuput = 3
        self.stbPickP3.Add(self.lLEFXP3, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)      
        # Y Position
        toolTipString="Y Coordinate of end point"
        self.lLEFYP3 = LabeledEditField(self, wx.ID_ANY, "Y", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_16',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFYP3.typeOfValue = float
        self.lLEFYP3.decimalDigitsOfOuput = 3    
        self.stbPickP3.Add(self.lLEFYP3, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER) 
        # Position choice button
        toolTipString="Catch Coordinates of end point"
        self.buttonPickP3 = NormalButton(self, wx.ID_ANY, "XY>>",wx.DefaultPosition , size=(50, 25), style=0, name="_BTN_MEASURE_POINT_3XY", toolTipString=toolTipString)
        self.stbPickP3.Add(self.buttonPickP3, 0, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)       
        self.vBagMain.Add(self.stbPickP3, (3, 0), flag=wx.ALL|wx.EXPAND, border=MINIBORDER)
     
        # Image part
        self.bmpCW = getOpticamIcon('Makino_EXC_CW_R.bmp')
        self.bmpCCW = getOpticamIcon('Makino_EXC_CCW_R.bmp')

        self.stBitmap = wx.StaticBitmap(self, id=wx.ID_ANY, bitmap=self.bmpCW, pos=wx.DefaultPosition,
                                        size=wx.DefaultSize, style=0, name="IMG_MCY_TYPE6")
        self.vBagMain.Add(self.stBitmap, (0, 1), (2, 1), flag=wx.ALIGN_CENTER | wx.ALL , border=MINIBORDER)
        
        # Measurement Direction
        #stbDir = wx.StaticBox(self, wx.ID_ANY, "Direction", name="STB_DIRECTION") 
        self.stbDir = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Direction", name="STB_DIRECTION"), wx.VERTICAL)
        vDirection1 = wx.BoxSizer(wx.VERTICAL)
        hDirection2 = wx.BoxSizer(wx.HORIZONTAL)
        self.rbCW = OptiRadioButton(self, wx.ID_ANY, "Clockwise", style=wx.RB_GROUP, name="PAR_5")
        self.rbCCW = OptiRadioButton(self, wx.ID_ANY, "Counterclockwise", style=0, name="RB_CCW")
        self.cbCylHole = OptiCheckBox(self, wx.ID_ANY, label="Cylindrical Hole", name='PAR_20')
        vDirection1.Add(self.rbCW,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        vDirection1.Add(self.rbCCW,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        hDirection2.Add(self.cbCylHole, 1, wx.EXPAND | wx.LEFT, SMALLBORDER)
        self.stbDir.Add(vDirection1, 1, wx.EXPAND)
        self.stbDir.Add(hDirection2, 1, wx.EXPAND)
        self.vBagMain.Add(self.stbDir, (2, 1), (1, 1), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)

        # Profile Sizers - Save/Load  
        vProfile = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Profiles", name="STB_PROFILE"), wx.VERTICAL) # 
        hProfile = wx.BoxSizer(wx.HORIZONTAL)
        
        toolTipString="Transfer these entries to a database."
        self.btnProfileSave = NormalButton(self, wx.ID_ANY, "Save", wx.DefaultPosition, wx.DefaultSize, style=0, name='BTN_PROFILE_SAVE',toolTipString=toolTipString )
        toolTipString="View saved entries / load in the dialog."
        self.btnProfileLoad = NormalButton(self, wx.ID_ANY, "Load", wx.DefaultPosition, wx.DefaultSize, style=0, name='BTN_PROFILE_LOAD',toolTipString=toolTipString)
        hProfile.Add(self.btnProfileSave,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        hProfile.Add(self.btnProfileLoad,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        vProfile.Add(hProfile, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        self.vBagMain.Add(vProfile, (3, 1), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Info text marking the start of for cycle specific params
        self.MeasureInfo=TextField(self, wx.ID_ANY, "Cylinder Center Measurement", wx.DefaultPosition, wx.DefaultSize,style=0, name='Info Text EXC')
        self.vBagMain.Add(self.MeasureInfo, (4, 0), flag=wx.EXPAND | wx.ALL, border=SMALLBORDER)
        
        # Fast Advance I (X-axis) and J (Y-axis)
        toolTipString="Position of Measuring Circle Center 'I' (X-axis) relative to Start Point"
        self.lefCycCenI= LeftLabeledEditField(self, wx.ID_ANY, "Position of Measuring Circle Center 'I' (X-axis) relative to Start Point", min=0.0, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_10', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefCycCenI.typeOfValue = float
        self.lefCycCenI.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefCycCenI, (5, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
             
        # Fast Advance J (Y-axis) 
        toolTipString="Position of Measuring Circle Center 'J' (Y-axis) relative to Start Point"
        self.lefCycCenJ= LeftLabeledEditField(self, wx.ID_ANY, "Position of Measuring Circle Center 'J' (Y-axis) relative to Start Point", min=0.0, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_12', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefCycCenJ.typeOfValue = float
        self.lefCycCenJ.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefCycCenJ, (6, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Measuring Circle Radius (R)
        toolTipString="Specifies the radius of the measuring circle"
        self.lefCircRad = LeftLabeledEditField(self, wx.ID_ANY, "Measurement Circle Radius (R)", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_19', toolTipString=toolTipString, bWithCheckbox=False)
        self.lefCircRad.typeOfValue = float
        self.lefCircRad.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefCircRad, (7, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # G92
        toolTipString="Temporarily Shift Coordinate System to current (measured) Wire Position."
        self.lefG92 = RealLeftLabeledDobbleEditFieldPickPos2(self, wx.ID_ANY, wx.ID_ANY, extraLabel = "G92", label1="X", label2="Y", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name1='PAR_6', name2='PAR_7', 
                                             toolTipString=toolTipString, bWithCheckbox=True, name="LLEFPP_G92")
        self.lefG92.typeOfValue = float
        self.lefG92.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefG92, (8, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Status Bar for string preview
        if not parent.statusbar:
            toolTipString="Preview of NC Code String."
            self.sttOutput = wx.StaticText(self, wx.ID_ANY, label="xxxxxxxxxx", pos=wx.DefaultPosition,
               size=wx.DefaultSize, style=0, name="STT_OUTPUT_COMMON", toolTipString=toolTipString) 
            self.sttOutput.SetFont(objFont)
            self.vBagMain.Add(self.sttOutput, (9, 0), (1, 2), flag=wx.EXPAND | wx.TOP, border=BORDER)
        
        # Make all rows and columns of the GridBagSizer dynamically change with panel size
        self.vBagMain.Layout()
        for col in range(self.vBagMain.GetCols()):
            self.vBagMain.AddGrowableCol(col)
        for row in range(self.vBagMain.GetRows()):
            self.vBagMain.AddGrowableRow(row)
        
        self.SetSizerAndFit(self.vBagMain)
            
        #### Bind events ####    
        self.Bind(wx.EVT_CHECKBOX, parent.OnLabeledEFCheckboxChecked)
        # Wire Settings Check Box
        self.cbCutWire.Bind(wx.EVT_CHECKBOX, parent.OnCutWireCheckboxChecked)
        self.cbThreadWire.Bind(wx.EVT_CHECKBOX, parent.OnThreadWireCheckboxChecked)
        self.cbCylHole.Bind(wx.EVT_CHECKBOX, parent.OnCylHoleCheckboxChecked)
        # Text Field changes
        self.Bind(wx.EVT_TEXT, parent.OnLabeledEFTextCtrlChanged)
        # Profile Buttons
        self.btnProfileSave.Bind(wx.EVT_BUTTON, parent.OnSaveProfileButtonClicked)
        self.buttonPickP2.Bind(wx.EVT_BUTTON, parent.OnPickPositionPointButtonClicked)
        self.buttonPickP3.Bind(wx.EVT_BUTTON, parent.OnPickPositionPointButtonClicked)
        self.btnProfileLoad.Bind(wx.EVT_BUTTON, parent.OnLoadProfileButtonClicked)
        # Position Pick Buttons
        self.buttonPickPos.Bind(wx.EVT_BUTTON, parent.OnPickPositionPointButtonClicked)
        self.lefG92.Bind(wx.EVT_BUTTON, parent.OnPickPositionG92ButtonClicked)
        # Radio Rotation Buttons
        self.rbCW.Bind(wx.EVT_RADIOBUTTON, partial(parent.OnRadioBoxMeasureDirectionClicked, vDir='CW'))
        self.rbCCW.Bind(wx.EVT_RADIOBUTTON, partial(parent.OnRadioBoxMeasureDirectionClicked, vDir='CCW'))
        ####################
        
    def WriteDistances(self, x2=None, y2=None):
        # Get Values of Start point
        setattr(self, "x1", (self.lLEFXStart.GetValue()))
        setattr(self, "y1", (self.lLEFYStart.GetValue()))
        
        # P1 must exist 
        if getattr(self, "x1", None) is not None and getattr(self, "y1", None) is not None:               
            # Calculate and set I
            if x2 is not None:
                self.i = round((x2 - self.x1), self.lefCycCenI.decimalDigitsOfOuput)
                self.lefCycCenI.edit.SetValue(self.i)
            # Calculate and set J
            if y2 is not None:
                self.j = round((y2 - self.y1), self.lefCycCenJ.decimalDigitsOfOuput)
                self.lefCycCenJ.edit.SetValue(self.j)
                
        
class MyPanelMeasureCycleType7(scrolled.ScrolledPanel):
    def __init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL, name=""):  # @ReservedAssignment
        """
        This class defines and creates widgets for the sub dialog for measure cycle Type 7: 
        """
        self.isMainPanel=True
        self.parent = parent
        self.name=name
        self.title="PAL"
        scrolled.ScrolledPanel.__init__(self, parent, id=id, style=style, name=name)
        ##self.SetBackgroundColour('PINK')
        self.SetupScrolling(scroll_x=True, scroll_y=True)

        objFont = self.GetFont()

        self.vBagMain = wx.GridBagSizer(0, 0) # vgap 0, hgab 0
        
        # Sizer for wire cut settings
        vBoxWireSettings = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Wire Settings", name="STB_WIRE_SETTINGS"), wx.VERTICAL) # Draht Einstellungen
        self.cbThreadWire = OptiCheckBox(self, wx.ID_ANY, label="Thread wire before measurement (M06)", name='PAR_3') # de, Draht einfädeln
        vBoxWireSettings.Add(self.cbThreadWire, 1, wx.ALL | wx.EXPAND, SMALLBORDER)
        self.cbCutWire = OptiCheckBox(self, wx.ID_ANY, label="Cut wire after measurement (M07)", name='PAR_4') # de, Draht abscheiden  
        vBoxWireSettings.Add(self.cbCutWire, 1, wx.ALL | wx.EXPAND, SMALLBORDER)    
      
        self.vBagMain.Add(vBoxWireSettings, (0, 0), flag=wx.ALL | wx.EXPAND, border=MINIBORDER)
        
        # Main Sizer for First Point
        self.stbPickStart = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Measurement Start Point", name="STB_MEASURE_POINT_1"), wx.HORIZONTAL)              
        # Sub sizer for selection and position
        vBoxSubStartPos = wx.BoxSizer(wx.VERTICAL)
        self.stbPickStart.Add(vBoxSubStartPos, 1, flag= wx.EXPAND|wx.ALL)
              
        # X Position
        toolTipString="X Coordinate of Startpoint"
        self.lLEFXStart = LabeledEditField(self, wx.ID_ANY, "X", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_1',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFXStart.typeOfValue = float
        self.lLEFXStart.decimalDigitsOfOuput = 3
        self.stbPickStart.Add(self.lLEFXStart, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)      
        # Y Position
        toolTipString="Y Coordinate of Startpoint"
        self.lLEFYStart = LabeledEditField(self, wx.ID_ANY, "Y", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, min=-9999.0, max=9999.0, name='PAR_2',toolTipString=toolTipString, minSizeLabel=(-1,-1), minSizeEdit=EDIT_FIELD_SIZE)
        self.lLEFYStart.typeOfValue = float
        self.lLEFYStart.decimalDigitsOfOuput = 3    
        self.stbPickStart.Add(self.lLEFYStart, 1, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)  
        # Position choice button
        toolTipString="Catch Coordinates"
        self.buttonPickPos = NormalButton(self, wx.ID_ANY, "XY>>",wx.DefaultPosition , size=(50, 25), style=0, name="_BTN_MEASURE_POINT_1XY", toolTipString=toolTipString)
        self.stbPickStart.Add(self.buttonPickPos, 0, flag=wx.ALL|wx.ALIGN_CENTER, border=SMALLBORDER)
        
        self.vBagMain.Add(self.stbPickStart, (2, 0), flag=wx.ALL|wx.EXPAND, border=MINIBORDER)
     
        # Image part
        self.bmpX = getOpticamIcon('Makino_PAL_1.bmp')
        self.bmpY = getOpticamIcon('Makino_PAL_2.bmp')
        # self.bmp180 = getOpticamIcon('d_ausricht_3seit_180_0.bmp')
        # self.bmp270 = getOpticamIcon('d_ausricht_3seit_270_0.bmp')

        self.stBitmap = wx.StaticBitmap(self, id=wx.ID_ANY, bitmap=self.bmpX, pos=wx.DefaultPosition,
                                        size=wx.DefaultSize, style=0, name="IMG_MCY_TYPE5")

        self.vBagMain.Add(self.stBitmap, (0, 1), (2, 1), flag=wx.ALIGN_CENTER | wx.ALL , border=MINIBORDER)
        
        # Cycle Rotation/Movement Direction part
        self.stbMovDir = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY,"Movement Direction", name="STB_MOV_DIR"), wx.VERTICAL)
        hTouchDir1 = wx.BoxSizer(wx.HORIZONTAL)
        self.rbDirXPlus = OptiRadioButton(self, wx.ID_ANY, "X", style=wx.RB_GROUP, name="PAR_5")
        self.rbDirYPlus = OptiRadioButton(self, wx.ID_ANY, "Y", style=0, name="RB_DIR_Y")
        hTouchDir1.Add(self.rbDirXPlus,  1, wx.EXPAND, SMALLBORDER)
        hTouchDir1.Add(self.rbDirYPlus,  1, wx.EXPAND, SMALLBORDER)
        self.stbMovDir.Add(hTouchDir1, 1, wx.EXPAND | wx.ALL, SMALLBORDER)

        self.vBagMain.Add(self.stbMovDir, (1, 0), (1, 1), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)

        # Profile Sizers - Save/Load  
        vProfile = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Profiles", name="STB_PROFILE"), wx.VERTICAL) # 
        hProfile = wx.BoxSizer(wx.HORIZONTAL)
        
        toolTipString="Transfer these entries to a database."
        self.btnProfileSave = NormalButton(self, wx.ID_ANY, "Save", wx.DefaultPosition, wx.DefaultSize, style=0, name='BTN_PROFILE_SAVE',toolTipString=toolTipString )
        toolTipString="View saved entries / load in the dialog."
        self.btnProfileLoad = NormalButton(self, wx.ID_ANY, "Load", wx.DefaultPosition, wx.DefaultSize, style=0, name='BTN_PROFILE_LOAD',toolTipString=toolTipString)
        hProfile.Add(self.btnProfileSave,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        hProfile.Add(self.btnProfileLoad,  1, wx.EXPAND | wx.ALL, SMALLBORDER)
        vProfile.Add(hProfile, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        self.vBagMain.Add(vProfile, (2, 1), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Info text marking the start of for cycle specific params
        self.MeasureInfo=TextField(self, wx.ID_ANY, "Work Piece Parallelism", wx.DefaultPosition, wx.DefaultSize,style=0, name='Info Text PAL')
        self.vBagMain.Add(self.MeasureInfo, (3, 0), flag=wx.EXPAND | wx.ALL, border=SMALLBORDER)
        
        # Approach distance X
        toolTipString="Movement/Approach distance in X direction to work piece"
        self.lefApprX= LeftLabeledEditField(self, wx.ID_ANY, "Movement/Approach distance X", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_9', toolTipString=toolTipString, bWithCheckbox=False)
        self.lefApprX.typeOfValue = float
        self.lefApprX.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefApprX, (4, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Fast Advance I (X-axis) and J (Y-axis)
        toolTipString="Fast Advance I (X-axis), optional to shorten measurement time"
        self.lefFastAdvI= LeftLabeledEditField(self, wx.ID_ANY, "Fast Advance 'I' (X-axis)", min=0.0, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_10', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefFastAdvI.typeOfValue = float
        self.lefFastAdvI.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefFastAdvI, (5, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Approach distance Y
        toolTipString="Movement/Approach distance in Y direction to work piece"
        self.lefApprY= LeftLabeledEditField(self, wx.ID_ANY, "Movement/Approach distance Y", min=-9999.9, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_11', toolTipString=toolTipString, bWithCheckbox=False)
        self.lefApprY.typeOfValue = float
        self.lefApprY.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefApprY, (6, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
             
        # Fast Advance J (Y-axis) 
        toolTipString="Fast Advance J (Y-axis), optional to shorten measurement time"
        self.lefFastAdvJ= LeftLabeledEditField(self, wx.ID_ANY, "Fast Advance 'J' (Y-axis)", min=0.0, max=9999.9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='PAR_12', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefFastAdvJ.typeOfValue = float
        self.lefFastAdvJ.decimalDigitsOfOuput = 3
        self.vBagMain.Add(self.lefFastAdvJ, (7, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Measured Angle (A)
        toolTipString="Specifies the value in which the measured angle will be saved (A0 - A9)"
        self.lefMeasdAng = LeftLabeledEditField(self, wx.ID_ANY, "Measured Angle Value (A) | (Possible values: 0 to 9)", min=0, max=9,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.INTEGER, name='PAR_13', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefMeasdAng.typeOfValue = int
        self.vBagMain.Add(self.lefMeasdAng, (8, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Travel Movement Amount (R)
        toolTipString="Specifies the number of travel movements in the given direction"
        self.lefMovAmt = LeftLabeledEditField(self, wx.ID_ANY, "Number of travel movements (R) | (Possible values: 1 to 5)", min=1, max=5,
                                             behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.INTEGER, name='PAR_14', toolTipString=toolTipString, bWithCheckbox=True)
        self.lefMovAmt.typeOfValue = int
        self.vBagMain.Add(self.lefMovAmt, (9, 0), (1, 2), flag=wx.EXPAND | wx.ALL, border=MINIBORDER)
        
        # Status Bar for string preview
        if not parent.statusbar:
            toolTipString="Preview of NC Code String."
            self.sttOutput = wx.StaticText(self, wx.ID_ANY, label="xxxxxxxxxx", pos=wx.DefaultPosition,
               size=wx.DefaultSize, style=0, name="STT_OUTPUT_COMMON", toolTipString=toolTipString) 
            self.sttOutput.SetFont(objFont)
            self.vBagMain.Add(self.sttOutput, (10, 0), (1, 2), flag=wx.EXPAND | wx.TOP, border=BORDER)
        
        # Make all rows and columns of the GridBagSizer dynamically change with panel size
        self.vBagMain.Layout()
        for col in range(self.vBagMain.GetCols()):
            self.vBagMain.AddGrowableCol(col)
        for row in range(self.vBagMain.GetRows()):
            self.vBagMain.AddGrowableRow(row)
        
        self.SetSizerAndFit(self.vBagMain)
            
        #### Bind events ####    
        self.Bind(wx.EVT_CHECKBOX, parent.OnLabeledEFCheckboxChecked)
        # Wire Settings Check Box
        self.cbCutWire.Bind(wx.EVT_CHECKBOX, parent.OnCutWireCheckboxChecked)
        self.cbThreadWire.Bind(wx.EVT_CHECKBOX, parent.OnThreadWireCheckboxChecked)
        # Text Field changes
        self.Bind(wx.EVT_TEXT, parent.OnLabeledEFTextCtrlChanged)
        # Profile Buttons
        self.btnProfileSave.Bind(wx.EVT_BUTTON, parent.OnSaveProfileButtonClicked)
        self.btnProfileLoad.Bind(wx.EVT_BUTTON, parent.OnLoadProfileButtonClicked)
        # Position Pick Buttons
        self.buttonPickPos.Bind(wx.EVT_BUTTON, parent.OnPickPositionPointButtonClicked)
        # Radio Rotation Buttons
        self.rbDirXPlus.Bind(wx.EVT_RADIOBUTTON, partial(parent.OnRadioBoxMeasureDirectionClicked, vDir='+X'))
        self.rbDirYPlus.Bind(wx.EVT_RADIOBUTTON, partial(parent.OnRadioBoxMeasureDirectionClicked, vDir='+Y'))
        ####################
        


class MakinoMeasureCycleSubDialog(MeasureCycleBaseDialog, MeasureCycleMixin):
    """
    This function handles the functionalities of the measure cycle sub dialogs.
    
    Notes:
    Now, It works with the version 38 profile database table, see SQLITE3_MUSTER_DICT_TYPE_38
    """
    def __init__(self, *args, **kwargs):
        
        #Init Base class
        self.title = getText(kwargs["title"], "DLG_MEASURE_CYCLIE_SUB")
        MeasureCycleBaseDialog.__init__(self, *args, **kwargs)
        MeasureCycleMixin.__init__(self)
        self.sys = cad.System()
        #dictionary for load parameters from main system, xml file (as default), profile (database)
        # it is used also for save the parameters into main system, xml file (as default), profile (database)
        # so, if the value of dialog's widgets change, please also update the dictionary
        self.tmpParams = {} 
        #dictionary for reset button, it is a backup of tempPrams, if tmpParmas loaded/reload, please re-copy it also 
        self.resetParams = {} 
        #dictionary for all measure cycle panels
        self.pnldic = {}
        # Guard Flags
        self.fromWritePickPosition = False
        self.fromActivate = False
        self.fromP2 = False
        self.fromP3 = False
        self.fromStart = False
        self.fromIJ = False
        #boolean flag, store the call mode, call the dialog from the main measurement loop dialog or call the dialog directly from the main system.
        # If you call this dialog from the main measure cycle dialog, you first need to hide it, and then if you leave ecs ( Not ok) this dialog 
        # you needs to show the main dialog again. 
        self.bCallFromPyMain = False
        # if click "Save" button after called "load", please set this attribute "false" 
        # if the new value successfully saved into database then set it "true" 
        self.bInsertIntoSQLiteAsNewRecord = True
        #3. Create Widgets with the measure type object 
        if not self.initialized:
            self.CreateWidgets()
            self.initialized = True
            
            
    def GetLabel(self):
        """
        This function returns the label of the measure cycle sub dialog, which is the "title" in this case.
        """
        #self.title = getText(kwargs["title"], "DLG_MEASURE_CYCLIE_SUB")
        return self.title 
      
    
    def SetLabel(self, labelString):
        """
        This function sets the label (title) of the measure cycle sub dialog.
        """
        wx.Dialog.SetTitle(self, labelString)
        self.title=labelString
        

    def Activate(self, Measureobject=None, dummy=None):
        """ 
        Jump in point for measure cycle sub dialog (can come from main dialog or C++)
        
        Notes:
        bCallFromPyMain: boolean flag, store the call mode, call the dialog from the main measurement loop dialog or call the dialog directly from the main system.
        If you call this dialog from the main measure cycle dialog, you first need to hide it and then, if you "leave escape" (Not OK) this dialog,
        you need to show the main dialog again. 
        Put here all the values we need and which are not already in the base-class
        """
        # globals
        global measureObject, measureString
        global originObject
        global strVersion, strMeasureCycleType

        if inPeps():    # Get Peps DB path
            try:
                dbpath = BaseDialog.kwargsBuffer.get("dbpath", "").strip()
                dbfile = BaseDialog.kwargsBuffer.get("dbfile", "opticam_wire_version1.OPTICAMdb").strip()
                postVar["DbPathField"] = os.path.join(dbpath, dbfile) 
                logger.info("     DB_Path : {} {}".format(postVar["DbPathField"], "exists" if os.path.exists(postVar["DbPathField"]) else ""))
            except:
                logger.error("     DB_Path : {}".format(" error in getting DB path"))

        if inPeps() and BaseDialog.kwargsBuffer.get("measureString"):   # we are called from peps workspace and receive a measureString
            measureString = BaseDialog.kwargsBuffer.get("measureString")
            self.bCallFromPyMain = False
            # get type
            s3 = measureString[74:].strip()
            s  = s3.split()
            strMeasureCycleType = GetMeasureCycleTypeString(int(s[1]))
        elif Measureobject is not None:   # we are called from C++ and receive a Measureobject
            logger.info(LOG_TAG + "MakinoMeasureCycleSubDialogActivate() [CALL FROM C++]")
            measureObject = Measureobject
            # boolean flag, call modus 
            self.bCallFromPyMain = False
        
            enum = measureObject.GetType()              # get the enum from C++ Measureobject
            strMeasureCycleType = str(enum).replace('eMEASURETYPE_', '')
        elif strMeasureCycleType:                       # we are called from python main-dialog (with the choices) and use the measureObject remaining in buffer from prev. python-maindialog
            logger.info(LOG_TAG + "MakinoMeasureCycleSubDialogActivate() [CALL FROM PYTHON SELECTION MENUE]")
            self.bCallFromPyMain = True
        else:                   # not good
            return
            
        # dummy will be used for origin!
        if dummy is not None:
            originObject = dummy
            pass
        
        ### THIS IS FOR TESTING NEW DATA SCHEME ############################################################################################################################
        self.typeData = MEASURETYPE(measureObject)          # not used atm. , experimental...
        self.paramData = MEASUREPARAM(measureObject)        # ...same
        # ##################################################################################################################################################################
        self.measureObject = measureObject
        #object measure cycle type
        self.strMType = strMeasureCycleType
        #object measure strVersion
        self.strVersion = strVersion
        #1. eval the string type name to object
        # user strMType from init or from other way
        # Set guard flag for Text events (SetValue())
        self.fromActivate = True
        
        #check if old version of USER-DEFAULT.XML is used and change it
        #self.ChangeUserDefaultXML()
        try:
            logger.info(LOG_TAG + " * Create the instance of measure cycle type: %s." % self.strMType)
            self.mType = eval(self.strMType)()
        except:
            logger.error(LOG_TAG + " * Can not reate the instance of measure cycle type: %s." % self.strMType)
            self.mType = None 
        #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        #2. detect the dialog parameter source 1. from xml, 2 from main system
        self.LoadParams(self.bCallFromPyMain)
        #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        #
        #3.1 Switch Panel
        rts = self.SwitchMeasureCyclePanel(self.mType) # @UnusedVariable
        #rts=self._common_regenerate_output(self.mType)
        #3.2 Update data
        if self.strMType in self.tmpParams:# and self.bCallFromPyMain == True:
            logger.info(LOG_TAG + " * TransferDataToWindow(), found params from tmpParams dictionary, set windows control value from this dict.")
            dictType = self.tmpParams[self.strMType]
            TransferDataToWindow(self.MainPanel, dictType)
            
            if self.bCallFromPyMain == True:
                # Turn off some Parameters by default
                if hasattr(self.MainPanel, "lefWorkpInc"):
                    if strMeasureCycleType in self.tmpParams:                
                        self.MainPanel.lefWorkpInc.cbCheck.SetValue(False)
                        self.MainPanel.lefWorkpInc.edit.SetValue("")
                        self.MainPanel.lefWorkpInc.Enable(False)
                
                # Check if different LEF check boxes were selected previously
                if hasattr(self.MainPanel, "lefApprX") and hasattr(self.MainPanel, "lefApprY") and (hasattr(self.MainPanel, "stbTouchDir") or hasattr(self.MainPanel, "stbMovDir")):
                    if strMeasureCycleType in self.tmpParams and strMeasureCycleType not in ['CRN', 'PLM', 'PAL']: # don't do this for defined cycle types
                        # Approach X
                        if self.MainPanel.rbDirXPlus.GetValue() == True:
                            # Widgets to be deactivated
                            self.MainPanel.lefApprY.edit.SetValue("")
                            self.MainPanel.lefApprY.Enable(False)
                            self.MainPanel.lefFastAdvJ.cbCheck.SetValue(False)
                            self.MainPanel.lefFastAdvJ.cbCheck.Enable(False)
                            self.MainPanel.lefFastAdvJ.edit.SetValue("")
                            self.MainPanel.lefFastAdvJ.Enable(False)
                            # Widgets to be activated
                            self.MainPanel.lefApprX.edit.SetValue("0")
                            self.MainPanel.lefApprX.Enable(True)
                            self.MainPanel.lefFastAdvI.cbCheck.SetValue(True)
                            self.MainPanel.lefFastAdvI.cbCheck.Enable(True)
                            self.MainPanel.lefFastAdvI.edit.SetValue("0")
                            self.MainPanel.lefFastAdvI.Enable(True)
                        # Approach Y
                        if self.MainPanel.rbDirYPlus.GetValue() == True:
                            # Widgets to be deactivated
                            self.MainPanel.lefApprX.edit.SetValue("")
                            self.MainPanel.lefApprX.Enable(False)
                            self.MainPanel.lefFastAdvI.cbCheck.SetValue(False)
                            self.MainPanel.lefFastAdvI.cbCheck.Enable(False)
                            self.MainPanel.lefFastAdvI.edit.SetValue("")
                            self.MainPanel.lefFastAdvI.Enable(False)
                            # Widgets to be activated
                            self.MainPanel.lefApprY.edit.SetValue("0")
                            self.MainPanel.lefApprY.Enable(True)
                            self.MainPanel.lefFastAdvJ.cbCheck.SetValue(True)
                            self.MainPanel.lefFastAdvJ.cbCheck.Enable(True)
                            self.MainPanel.lefFastAdvJ.edit.SetValue("0")
                            self.MainPanel.lefFastAdvJ.Enable(True)
                    if strMeasureCycleType in self.tmpParams and strMeasureCycleType in ['PAL']: # Only do this for PAL
                        # Approach X
                        if self.MainPanel.rbDirXPlus.GetValue() == True:
                            # Widgets to be deactivated
                            self.MainPanel.lefFastAdvI.cbCheck.SetValue(False)
                            self.MainPanel.lefFastAdvI.cbCheck.Enable(False)
                            self.MainPanel.lefFastAdvI.edit.SetValue("")
                            self.MainPanel.lefFastAdvI.Enable(False)
                            # Widgets to be activated
                            self.MainPanel.lefFastAdvJ.cbCheck.SetValue(True)
                            self.MainPanel.lefFastAdvJ.cbCheck.Enable(True)
                            self.MainPanel.lefFastAdvJ.edit.SetValue("0")
                            self.MainPanel.lefFastAdvJ.Enable(True)
                        # Approach Y
                        if self.MainPanel.rbDirYPlus.GetValue() == True:
                            # Widgets to be deactivated
                            self.MainPanel.lefFastAdvJ.cbCheck.SetValue(False)
                            self.MainPanel.lefFastAdvJ.cbCheck.Enable(False)
                            self.MainPanel.lefFastAdvJ.edit.SetValue("")
                            self.MainPanel.lefFastAdvJ.Enable(False)
                            # Widgets to be activated
                            self.MainPanel.lefFastAdvI.cbCheck.SetValue(True)
                            self.MainPanel.lefFastAdvI.cbCheck.Enable(True)
                            self.MainPanel.lefFastAdvI.edit.SetValue("0")
                            self.MainPanel.lefFastAdvI.Enable(True)
                
                # Only do this for Center Hole, here some default widgets have to be activated/deactivated         
                if strMeasureCycleType in self.tmpParams and strMeasureCycleType == 'CEN':
                    if hasattr(self.MainPanel, "lefApprX") and hasattr(self.MainPanel, "lefApprY"):
                        # Initially disable Y if both are activated, this should only happen once at the start
                        if self.MainPanel.lefApprX.cbCheck.Value == True and self.MainPanel.lefApprY.cbCheck.Value == True:
                            self.MainPanel.lefApprY.edit.SetValue("")
                            self.MainPanel.lefApprY.Enable(False)
                            self.MainPanel.lefApprY.cbCheck.SetValue(False)
                            self.MainPanel.lefApprX.cbCheck.Enable(False)
                            self.MainPanel.lefApprY.cbCheck.Enable(True)
                        # If X is active, disable Y
                        elif self.MainPanel.lefApprX.cbCheck.Value == True and self.MainPanel.lefApprY.cbCheck.Value == False:
                            self.MainPanel.lefApprY.edit.SetValue("")
                            self.MainPanel.lefApprY.Enable(False)
                            self.MainPanel.lefApprY.cbCheck.SetValue(False)
                            self.MainPanel.lefApprX.cbCheck.Enable(False)
                            self.MainPanel.lefApprY.cbCheck.Enable(True)
                        # If Y is active, disable X
                        elif self.MainPanel.lefApprX.cbCheck.Value == False and self.MainPanel.lefApprY.cbCheck.Value == True:
                            self.MainPanel.lefApprX.edit.SetValue("")
                            self.MainPanel.lefApprX.Enable(False)
                            self.MainPanel.lefApprX.cbCheck.SetValue(False)
                            self.MainPanel.lefApprY.cbCheck.Enable(False)
                            self.MainPanel.lefApprX.cbCheck.Enable(True)
                
                # Only do this Cylinder Center, here some default widgets have to be activated/deactivated         
                # if strMeasureCycleType in self.tmpParams and strMeasureCycleType == 'EXC':
                #     if hasattr(self.MainPanel, "lefCycCenI") and hasattr(self.MainPanel, "lefCycCenJ"):
                #         # Initially disable R if both are activated, this should only happen once at the start
                #         if self.MainPanel.lefCycCenI.cbCheck.Value == True and self.MainPanel.lefCycCenJ.cbCheck.Value == True:
                #             self.MainPanel.lefCircRad.edit.SetValue("")
                #             self.MainPanel.lefCircRad.Enable(False)
                #             self.MainPanel.lefCircRad.cbCheck.SetValue(False)
                #             #self.MainPanel.lefCircRad.cbCheck.Enable(False)
                #         # If R is active, disable I and J
                #         elif self.MainPanel.lefCircRad.cbCheck.Value == True:
                #             self.MainPanel.lefCycCenI.edit.SetValue("")
                #             self.MainPanel.lefCycCenI.Enable(False)
                #             self.MainPanel.lefCycCenI.cbCheck.SetValue(False)
                #             #self.MainPanel.lefCycCenI.cbCheck.Enable(False)
                #             self.MainPanel.lefCycCenJ.edit.SetValue("")
                #             self.MainPanel.lefCycCenJ.Enable(False)
                #             self.MainPanel.lefCycCenJ.cbCheck.SetValue(False)
                #             #self.MainPanel.lefCycCenJ.cbCheck.Enable(False)
                #     if hasattr(self.MainPanel, "rbCW") and hasattr(self.MainPanel, "rbCCW"):
                #         if self.MainPanel.rbCW.Value == False:
                #             self.MainPanel.rbCCW.SetValue(True)
                
    
    
                # Check if G92 check boxes were selected previously
                if hasattr(self.MainPanel, "lefG92"):
                    if strMeasureCycleType in self.tmpParams:
                        # G92 X
                        if self.MainPanel.lefG92.llef1.cbCheck.GetValue() == True:
                            self.MainPanel.lefG92.llef1.Enable(True)
                        else:
                            self.MainPanel.lefG92.llef1.Enable(False)
                        # G92 Y
                        if self.MainPanel.lefG92.llef2.cbCheck.GetValue() == True:
                            self.MainPanel.lefG92.llef2.Enable(True)
                        else:
                            self.MainPanel.lefG92.llef2.Enable(False)
    
                        # Disable G92 for the time being
                        # self.MainPanel.lefG92.llef1.Enable(False)
                        # self.MainPanel.lefG92.llef1.cbCheck.Enable(False)
                        # self.MainPanel.lefG92.llef2.Enable(False)
                        # self.MainPanel.lefG92.llef2.cbCheck.Enable(False)                                  
                        # self.MainPanel.lefG92.btnPickPos.Enable(False)
            
            # Load the correct probing direction bitmap fitting to the saved value     
            # if hasattr(self.MainPanel, "stBitmap"):
            #     if hasattr(self.MainPanel, "lefProbeDir"):
            #         if strMeasureCycleType in self.tmpParams:
            #             position = ""
            #             addStr = ""                    
            #             position = self.MainPanel.lefProbeDir.edit.Value.lstrip("0") or "0" # get probing direction value from edit field
            #             if self.strMType == "CEN":
            #                 pass
            #             else:
            #                 addStr = ""
            #             bmpStr = "makino_" + self.strMType + "_" + addStr + position + ".bmp"
            #             self.MainPanel.stBitmap.SetBitmap(getOpticamIcon(bmpStr))
            #             self.MainPanel.Refresh()
                        
        
        # Reset guard flag for Text events (SetValue())
        self.fromActivate = False  
        # Set same position as main Dialog
        if not self.docked:
            if 'WindowPosition' in self.kwargsBuffer:
                self.SetPosition(self.kwargsBuffer['WindowPosition'])
        # else:
        #     if self.bCallFromPyMain:
        #         self.docked = False
        #         wx.CallAfter(self.FireDockEvent)
        #size=wx.Size(1200,800)
        #self.SetSize(size)
        self.Fit()
        self.MainPanel.vBagMain.Layout()
        self._common_regenerate_output(self.mType)#generate statusbar text for measure cycle
        
        # IMPORTANT: CALL BASE-CLASS METHOD (puts the data to the controls)
        # the ShowModal will fire the method TransferDataToWindow
        super(self.__class__, self).Activate()
    
    def ActivateAfterLoadProfile(self, dictType):
        """ 
        This function writes the data from a previously saved and now to be loaded profile to the window.
        """
        
        global strMeasureCycleType
        
        TransferDataToWindow(self.MainPanel, dictType)
                
        # Load the correct probing direction bitmap fitting to the saved value 
        # if hasattr(self.MainPanel, "stBitmap"):
        #     if hasattr(self.MainPanel, "lefProbeDir"):
        #         if strMeasureCycleType in self.tmpParams:
        #             position = ""
        #             addStr = ""                    
        #             position = self.MainPanel.lefProbeDir.edit.Value.lstrip("0") or "0" # get probing direction value from edit field
        #             if self.strMType == "CEN":
        #                 pass
        #             else:
        #                 addStr = ""
        #             bmpStr = "makino_" + self.strMType + "_" + addStr + position + ".bmp"
        #             self.MainPanel.stBitmap.SetBitmap(getOpticamIcon(bmpStr))
        #             self.MainPanel.Refresh()
                   
        if hasattr(self.MainPanel, "cbCutWire"):
            val=dictType.get("PAR_4")
            self.MainPanel.cbCutWire.SetValue(val.get("value"))
            
        if hasattr(self.MainPanel, "cbThreadWire"):
            val=dictType.get("PAR_3")
            self.MainPanel.cbThreadWire.SetValue(val.get("value"))
        
        # Check if G92 check boxes were selected previously
        if hasattr(self.MainPanel, "lefG92"):
            if strMeasureCycleType in self.tmpParams:
                    dictType = self.tmpParams[strMeasureCycleType]
                    # G92 X
                    if self.MainPanel.lefG92.llef1.cbCheck.GetValue() == True:
                        self.MainPanel.lefG92.llef1.Enable(True)
                    else:
                        self.MainPanel.lefG92.llef1.Enable(False)
                    # G92 Y
                    if self.MainPanel.lefG92.llef2.cbCheck.GetValue() == True:
                        self.MainPanel.lefG92.llef2.Enable(True)
                    else:
                        self.MainPanel.lefG92.llef2.Enable(False)

                    # Disable G92 for the time being
                    # self.MainPanel.lefG92.llef1.Enable(False)
                    # self.MainPanel.lefG92.llef1.cbCheck.Enable(False)
                    # self.MainPanel.lefG92.llef2.Enable(False)
                    # self.MainPanel.lefG92.llef2.cbCheck.Enable(False)                                  
                    # self.MainPanel.lefG92.btnPickPos.Enable(False)
                
                         
        #if hasattr(self.MainPanel, "gmixed"):
        #    self.setWorkpieceControls(self.MainPanel.gmixed)
                                        #   
        #3.3 Position Center
        self.MainPanel.vBagMain.Layout()
        if not self.docked:
            self.CenterOnScreen()  
        self._common_regenerate_output(self.mType)#generate statusbar text for measure cycle
               
    
    def LoadParams(self, bCallFromPyMain):
        """
        This function Loads the defined parameters either from .xml or from main C++ system.
        
        Notes:
        1, Start this dialog from main control dialog, then load parameters from xml file
        2, Start from tree widget control, or similar  position, load parameter from object of main system
        
        call TransferDataToWindow after that 
        """
        if bCallFromPyMain:
            logger.info(LOG_TAG + " * Start Load params value from xml file.")
            # use the local variable for debug
            if os.path.exists(GetUserDataXMLFile()):
                strXMLPath = GetUserDataXMLFile()
            else:
                strXMLPath = GetDefaultDataXMLFile()
            strMeasureType = self.strMType
            dictTemp = GeneralReadMeasureCycleDefaultParams(strXMLPath, MEASURECYCLEMACHINENAME, strMeasureType, strVersion)
            self.tmpParams = dictTemp.copy()
            self.resetParams = dictTemp.copy()
            logger.info(LOG_TAG + " * Success Load params value from xml file.")
        else: # source 2 from main system object
            logger.info(LOG_TAG + " * Load params value from main system.")
            if inPeps():
                dictTemp = MakinoMeasureCycleSubDialog.ReadParamsFromPepsString(self)
            else:
                dictTemp = MakinoMeasureCycleSubDialog.ReadParamsFromCplusplus(self)
            self.tmpParams = dictTemp.copy()
            self.resetParams = dictTemp.copy()
            logger.info(LOG_TAG + " * Success Load params value from main system.")

        return True
        
    def ReloadParams(self, inputDict={}):
        """
        This function reloads the defined parameter from profile database.
        
        Notes:
        inputDict, type SQLITE3_MUSTER_DICT_TYPE_XX
        
        Reload/Refresh the params from tmpSQLite dictionary to tmpParams dictionary and 
        create a copy for tmpParams into resetParams dictionary
        
        inputDict = {'VERSION': '38', 'KEY_PART1': '0001', 'SEARCHTERM': '4', 'KEY': '00014', 'COMMENT1': 'swswswsw', ...}
        self.tmpParams = {'EDG': {'PAR_1': {'widgets': '0', 'value': '-32768', 'name': 'X Momentary', 'comment': 'not used'}, ... }
         
        call TransferDataToWindow after that 
        """
        strType = self.strMType
        if not inputDict: # empty
            logger.warning(LOG_TAG + " * Cannot reLoad params value from tmpSQLite dictionary. it is empty")
            return False
        else: 
            logger.info(LOG_TAG + " * Start reload params value from tmpSQLite dictionary.")
            dictType = self.tmpParams[strType]
            for kyParam, valDict in dictType.items():
                if kyParam in inputDict:
                    logger.info(LOG_TAG + " * Found key: %s from tmpSQLite dictionary." % kyParam)
                    vValue = inputDict[kyParam]
                    try:
                        # database is float, so some int value would have the decimal point and zero, 
                        # dialog represents the value as string, if so, that will be show on dialog likes ""
                        # When calling from C++ somehow some values are an empty string '' --> these will be set to NOT_SET
                        if vValue == '':
                            vValue = NOT_SET                        
                        elif float(vValue) % 1 == 0:
                            vValue = "%d" % float(vValue)
                        else:
                            pass
                    except Exception as e: 
                        logger.error(LOG_TAG + " * ReloadParams() - Exception: %s , when trying to access data from DB." % e)                     
                    
                    if float(vValue) == NOT_SET:
                        valDict["widgets"] = '0'
                    else:
                        valDict["widgets"] = '1'
                    valDict["value"] = vValue
                else:
                    logger.warning(LOG_TAG + " * Not found key: %s from tmpSQLite dictionary." % kyParam)
                    valDict["widgets"] = '0'
                    valDict["value"] = '-32768'
            logger.info(LOG_TAG + " * Success reload params value from tmpSQLite dictionary.")
            # make copy for reset 
            self.resetParams = self.tmpParams.copy()
            return True

    def SaveParamsToCplusplus(self):
        """
        This functions saves the defined parameters to the main C++ system.
        
        Notes:
        self.tmpParams = {'EDG': {'PAR_1': {'widgets': '0', 'value': '-32768', 'name': 'X Momentary', 'comment': 'not used'}, ... }
        """
        if self.strMType in self.tmpParams:
            measureObject.SetType(self.mType.enum) 
            dictType = self.tmpParams[self.strMType]
            enum = measureObject.GetType()
            logger.info(LOG_TAG + " * Start transfering {} params to C++.".format(self.strMType))

            def _SetFunction(keyParam, func, enm, typ):
                if keyParam in dictType:
                    vValue = dictType[keyParam]["value"]
                    if typ == bool:
                        func(enm, True if vValue != '0' else False)
                    else:
                        func(enm, typ(vValue))
                    enabled    = dictType[keyParam]["widgets"] != '0'
                    #enabled = vValue != str(NOT_SET) # and used  # False                    
                    measureObject.SetParam_Enabled(enm, enabled)  # State of the widget
                    #measureObject.SetParam_Used(enm, used)        # not quite sure (enabled state of widget?)
                    return True
                return False
                    
        # Set C++ Parameters which are not defined in the default .xml and rather by widget values
        # if hasattr(self.MainPanel, "rbPosAxisX") and hasattr(self.MainPanel, "rbPosAxisY"):
        #     if self.MainPanel.rbPosAxisX.Value == True:
        #         measureObject.SetParam_Int(cad.eMEASUREPARAM_iAxisDirection, 1)# X
        #     elif self.MainPanel.rbPosAxisY.Value == True:
        #         measureObject.SetParam_Int(cad.eMEASUREPARAM_iAxisDirection, 0)# Y    
        ################################################################################
        
        if enum == cad.eMEASURETYPE_EDG:
            _SetFunction("PAR_1",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dStartPointX, float)#X Position
            _SetFunction("PAR_2",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dStartPointY, float)#Y Position
            _SetFunction("PAR_3",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bTE, bool)#Thread Wire
            _SetFunction("PAR_4",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool)#Cut Wire
            _SetFunction("PAR_5",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bFinalMove, bool)#Circle direction
            _SetFunction("PAR_6",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dXMomentary, float)#G92 X
            _SetFunction("PAR_7",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dYMomentary, float)#G92 Y          
            _SetFunction("PAR_8",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dTouchAngle, float)#Touch Angle
            _SetFunction("PAR_9",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float)#Approach Distance X
            _SetFunction("PAR_10", measureObject.SetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float)#Fast Advance I (X)
            _SetFunction("PAR_11", measureObject.SetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float)#Approach Distance Y
            _SetFunction("PAR_12", measureObject.SetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float)#Fast Advance J (Y)
            
        elif enum == cad.eMEASURETYPE_CEN:
            _SetFunction("PAR_1",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dStartPointX, float)#X Position
            _SetFunction("PAR_2",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dStartPointY, float)#Y Position
            _SetFunction("PAR_3",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bTE, bool)#Thread Wire
            _SetFunction("PAR_4",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool)#Cut Wire
            _SetFunction("PAR_6",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dXMomentary, float)#G92 X
            _SetFunction("PAR_7",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dYMomentary, float)#G92 Y          
            _SetFunction("PAR_8",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dTouchAngle, float)#Touch Angle
            _SetFunction("PAR_9",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float)#Approach Distance X
            _SetFunction("PAR_10", measureObject.SetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float)#Fast Advance I (X)
            _SetFunction("PAR_11", measureObject.SetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float)#Approach Distance Y
            _SetFunction("PAR_12", measureObject.SetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float)#Fast Advance J (Y)
        
        elif enum == cad.eMEASURETYPE_CRN:
            _SetFunction("PAR_1",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dStartPointX, float)#X Position
            _SetFunction("PAR_2",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dStartPointY, float)#Y Position
            _SetFunction("PAR_3",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bTE, bool)#Thread Wire
            _SetFunction("PAR_4",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool)#Cut Wire
            _SetFunction("PAR_6",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dXMomentary, float)#G92 X
            _SetFunction("PAR_7",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dYMomentary, float)#G92 Y          
            _SetFunction("PAR_9",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float)#Approach Distance X
            _SetFunction("PAR_10", measureObject.SetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float)#Fast Advance I (X)
            _SetFunction("PAR_11", measureObject.SetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float)#Approach Distance Y
            _SetFunction("PAR_12", measureObject.SetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float)#Fast Advance J (Y)
            _SetFunction("PAR_13", measureObject.SetParam_Int,    cad.eMEASUREPARAM_iMeasureSide, int)#Work piece Inclination
            
        elif enum == cad.eMEASURETYPE_MID:
            _SetFunction("PAR_1",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dStartPointX, float)#X Position
            _SetFunction("PAR_2",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dStartPointY, float)#Y Position
            _SetFunction("PAR_3",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bTE, bool)#Thread Wire
            _SetFunction("PAR_4",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool)#Cut Wire
            _SetFunction("PAR_5",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bFinalMove, bool)#Circle direction
            _SetFunction("PAR_6",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dXMomentary, float)#G92 X
            _SetFunction("PAR_7",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dYMomentary, float)#G92 Y          
            _SetFunction("PAR_8",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dTouchAngle, float)#Touch Angle
            _SetFunction("PAR_9",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float)#Approach Distance X
            _SetFunction("PAR_10", measureObject.SetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float)#Fast Advance I (X)
            _SetFunction("PAR_11", measureObject.SetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float)#Approach Distance Y
            _SetFunction("PAR_12", measureObject.SetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float)#Fast Advance J (Y)
            
        elif enum == cad.eMEASURETYPE_PLM:
            _SetFunction("PAR_1",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dStartPointX, float)#X Position
            _SetFunction("PAR_2",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dStartPointY, float)#Y Position
            _SetFunction("PAR_3",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bTE, bool)#Thread Wire
            _SetFunction("PAR_4",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool)#Cut Wire
            _SetFunction("PAR_5",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bFinalMove, bool)#Circle direction
            _SetFunction("PAR_6",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dXMomentary, float)#G92 X
            _SetFunction("PAR_7",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dYMomentary, float)#G92 Y          
            _SetFunction("PAR_8",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dTouchAngle, float)#Touch Angle
            _SetFunction("PAR_9",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float)#Approach Distance X
            _SetFunction("PAR_10", measureObject.SetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float)#Fast Advance I (X)
            _SetFunction("PAR_11", measureObject.SetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float)#Approach Distance Y
            _SetFunction("PAR_12", measureObject.SetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float)#Fast Advance J (Y)
            _SetFunction("PAR_15", measureObject.SetParam_Double, cad.eMEASUREPARAM_dThirdPointX, float)#Measurement Point 3 X
            _SetFunction("PAR_16", measureObject.SetParam_Double, cad.eMEASUREPARAM_dThirdPointY, float)#Measurement Point 3 Y
            _SetFunction("PAR_17", measureObject.SetParam_Double, cad.eMEASUREPARAM_dSecondPointX, float)#Measurement Point 2 X
            _SetFunction("PAR_18", measureObject.SetParam_Double, cad.eMEASUREPARAM_dSecondPointY, float)#Measurement Point 2 Y
            
        elif enum == cad.eMEASURETYPE_EXC:
            _SetFunction("PAR_1",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dStartPointX, float)#X Position
            _SetFunction("PAR_2",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dStartPointY, float)#Y Position
            _SetFunction("PAR_3",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bTE, bool)#Thread Wire
            _SetFunction("PAR_4",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool)#Cut Wire
            _SetFunction("PAR_5",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bFinalMove, bool)#Circle direction (1=CW/0=CCW)
            _SetFunction("PAR_6",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dXMomentary, float)#G92 X
            _SetFunction("PAR_7",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dYMomentary, float)#G92 Y          
            _SetFunction("PAR_9",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float)#Approach Distance X
            _SetFunction("PAR_10", measureObject.SetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float)#Fast Advance I (X)
            _SetFunction("PAR_11", measureObject.SetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float)#Approach Distance Y
            _SetFunction("PAR_12", measureObject.SetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float)#Fast Advance J (Y)
            _SetFunction("PAR_15", measureObject.SetParam_Double, cad.eMEASUREPARAM_dThirdPointX, float)#Measurement Endpoint X
            _SetFunction("PAR_16", measureObject.SetParam_Double, cad.eMEASUREPARAM_dThirdPointY, float)#Measurement Endpoint Y
            _SetFunction("PAR_17", measureObject.SetParam_Double, cad.eMEASUREPARAM_dSecondPointX, float)#Measurement Point 2 X
            _SetFunction("PAR_18", measureObject.SetParam_Double, cad.eMEASUREPARAM_dSecondPointY, float)#Measurement Point 2 Y
            _SetFunction("PAR_19", measureObject.SetParam_Double, cad.eMEASUREPARAM_dSphericalRadius, float)#Measure Circle radius
            _SetFunction("PAR_20", measureObject.SetParam_Bool, cad.eMEASUREPARAM_bDontZeroXYCorrection, bool)#Cylindrical Hole
            
        elif enum == cad.eMEASURETYPE_PAL:
            _SetFunction("PAR_1",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dStartPointX, float)#X Position
            _SetFunction("PAR_2",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dStartPointY, float)#Y Position
            _SetFunction("PAR_3",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bTE, bool)#Thread Wire
            _SetFunction("PAR_4",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool)#Cut Wire
            _SetFunction("PAR_5",  measureObject.SetParam_Bool,   cad.eMEASUREPARAM_bFinalMove, bool)#Circle direction
            _SetFunction("PAR_6",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dXMomentary, float)#G92 X
            _SetFunction("PAR_7",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dYMomentary, float)#G92 Y          
            _SetFunction("PAR_8",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dTouchAngle, float)#Touch Angle
            _SetFunction("PAR_9",  measureObject.SetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float)#Approach Distance X
            _SetFunction("PAR_10", measureObject.SetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float)#Fast Advance I (X)
            _SetFunction("PAR_11", measureObject.SetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float)#Approach Distance Y
            _SetFunction("PAR_12", measureObject.SetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float)#Fast Advance J (Y)
            _SetFunction("PAR_13", measureObject.SetParam_Int,    cad.eMEASUREPARAM_iMeasureSide, int)#Measured Angle
            _SetFunction("PAR_14", measureObject.SetParam_Int,    cad.eMEASUREPARAM_iMeasurementPoints, int)#Movement Amount
                
        logger.info(LOG_TAG + " * Success transferring {} params to C++.".format(self.strMType))

        # Fill the rest up to 27 with empty entries
        # for i in range(1, 28):
        #     key = "PAR_{}".format(i)
        #     if key not in dictType:
        #         dictType[key] = {"widgets": "0", "value": '-32768', "name": "", "comment": ""}
        measureObject.SetParam_String(cad.eMEASUREPARAM_szVDMVersion, cad.String(self.strVersion))
        measureObject.SetParam_Enabled(cad.eMEASUREPARAM_szVDMVersion, True)
        # make copy for reset 
        self.resetParams = self.tmpParams.copy()
        return True
        
    def WriteParamsToPepsString(self, dictType):
        """
        This function writes the defined parameters to the PEPS string.
        """
        global measureString

        description = self.MainPanel.title
        
        # NimkeL/23.01.26: 
        # We need this "wrong" assignment in this Version because some Measure Types were switched...
        # Type 5 PLM --> EXN
        # ...and it would break OC serialization and PEPS Strings with already saved files if we change this on a higher level.
        if description == "PLM":
            description = "EXN"
            
        ### Find out what is the highest PAR-Number defined in the xml file
        # Get the data out of the xml-file and put it into a dict
        if os.path.exists(GetUserDataXMLFile()):
            strXMLPath = GetUserDataXMLFile()
        else:
            strXMLPath = GetDefaultDataXMLFile()
        dictTemp = GeneralReadMeasureCycleDefaultParams(strXMLPath, MEASURECYCLEMACHINENAME, "", strVersion)
        
        # Find out which is the highest number of Parameter in the whole dictionary
        numbers = set()
        for sub_dict in dictTemp.values():  # iterate all sub-dictionaries
            for key in sub_dict.keys():
                if key.startswith("PAR_"):
                    try:
                        number = int(key.split("PAR_")[1])
                        numbers.add(number)
                    except ValueError:
                        pass
        # Get highest number
        if numbers:
            max_number = max(numbers)
        else: # Or set default
            max_number = 20
        ###

        s1 = '{:11}: {:51}'.format('MESSZYKLUS', description)
        s2 = '{:10}'.format('mcy')
        s3 = '{} {}'.format('20401', int(self.mType.type_id))
        
        # List of all available Parameters
        listParAvailable = [key for key in dictType if key.startswith("PAR_")]
        # List of all theoretically available Parameters - in MAKINO we should have 16 parameters
        listParComplete = [f"PAR_{i}" for i in range(1, max_number+1)]
        
        # Build/Add s3 part of string which contains the widget values
        for par in listParComplete:
            # If the Parameter exists, get the related value       
            if par in listParAvailable:
                if dictType[par]['widgets'] == "1":
                    s3 += " {}".format(dictType[par]['value'])
                else: # disabled widgets shall be NOT_SET
                    s3 += " {}".format("-32768")
            # If it is a "padded" one, set to default value (NOT_SET) which later leads to "widget" being "0"
            else:
                s3 += " {}".format("-32768")
                
        # Build the string for PEPS  
        measureString = "{:64.64}{:10.10}{}".format(s1, s2, s3)

    def ReadParamsFromCplusplus(self):
        """
        This functions loads the previously defined and saved parameters from the main C++ system to the Python Dialog.
        
        Notes:
        self.tmpParams = {'EDG': {'PAR_1': {'widgets': '0', 'value': '-32768', 'name': 'X Momentary', 'comment': 'not used'}, ... }
        """
        global strMeasureCycleType
        logger.info(LOG_TAG + " * Start reading {} params from C++.".format(strMeasureCycleType))
        #
        if strMeasureCycleType in self.tmpParams:
            dictType = self.tmpParams[strMeasureCycleType]
        else:
            dictType = {}
        enum = measureObject.GetType()
#
        def _GetFunction(keyParam, func, enm, typ):
            vValue = func(enm)
            enabled = measureObject.GetParam_Enabled(enm)
            if not enabled:
                vValue = '0'
                if keyParam == "PAR_14": # Special case for Movement Amount in PAL ... should be default "1" when coming from "NOT_SET"
                    vValue = '1'
            elif typ == cad.String:
                vValue = vValue.getPyString()
            elif typ == bool:
                vValue = "1" if vValue == True else "0"
            else:
                vValue = str(vValue)
            #used    = measureObject.GetParam_Used(enm)
            widgets = '1' if enabled else '0'
            name = ""
            comment = enm.__str__()
            valDict = {"widgets": widgets, "value": vValue, "name": name, "comment": comment}
            dictType[keyParam] = valDict
            
        if enum == cad.eMEASURETYPE_EDG:
            _GetFunction("PAR_1",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointX, float)#X Position
            _GetFunction("PAR_2",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointY, float)#Y Position
            _GetFunction("PAR_3",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bTE, bool)#Thread Wire
            _GetFunction("PAR_4",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool)#Cut Wire
            _GetFunction("PAR_5",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bFinalMove, bool)#Circle direction
            _GetFunction("PAR_6",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dXMomentary, float)#G92 X
            _GetFunction("PAR_7",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dYMomentary, float)#G92 Y          
            _GetFunction("PAR_8",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dTouchAngle, float)#Touch Angle
            _GetFunction("PAR_9",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float)#Approach Distance X
            _GetFunction("PAR_10", measureObject.GetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float)#Fast Advance I (X)
            _GetFunction("PAR_11", measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float)#Approach Distance Y
            _GetFunction("PAR_12", measureObject.GetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float)#Fast Advance J (Y)
            
        elif enum == cad.eMEASURETYPE_CEN:
            _GetFunction("PAR_1",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointX, float)#X Position
            _GetFunction("PAR_2",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointY, float)#Y Position
            _GetFunction("PAR_3",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bTE, bool)#Thread Wire
            _GetFunction("PAR_4",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool)#Cut Wire
            _GetFunction("PAR_6",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dXMomentary, float)#G92 X
            _GetFunction("PAR_7",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dYMomentary, float)#G92 Y          
            _GetFunction("PAR_8",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dTouchAngle, float)#Touch Angle
            _GetFunction("PAR_9",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float)#Approach Distance X
            _GetFunction("PAR_10", measureObject.GetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float)#Fast Advance I (X)
            _GetFunction("PAR_11", measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float)#Approach Distance Y
            _GetFunction("PAR_12", measureObject.GetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float)#Fast Advance J (Y)
        
        elif enum == cad.eMEASURETYPE_CRN:
            _GetFunction("PAR_1",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointX, float)#X Position
            _GetFunction("PAR_2",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointY, float)#Y Position
            _GetFunction("PAR_3",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bTE, bool)#Thread Wire
            _GetFunction("PAR_4",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool)#Cut Wire
            _GetFunction("PAR_6",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dXMomentary, float)#G92 X
            _GetFunction("PAR_7",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dYMomentary, float)#G92 Y          
            _GetFunction("PAR_9",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float)#Approach Distance X
            _GetFunction("PAR_10", measureObject.GetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float)#Fast Advance I (X)
            _GetFunction("PAR_11", measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float)#Approach Distance Y
            _GetFunction("PAR_12", measureObject.GetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float)#Fast Advance J (Y)
            _GetFunction("PAR_13", measureObject.GetParam_Int,    cad.eMEASUREPARAM_iMeasureSide, int)#Work piece Inclination
            # _GetFunction("PAR_15", measureObject.GetParam_Double, cad.eMEASUREPARAM_dThirdPointX, float)#Measurement Point 3 X
            # _GetFunction("PAR_16", measureObject.GetParam_Double, cad.eMEASUREPARAM_dThirdPointY, float)#Measurement Point 3 Y
            # _GetFunction("PAR_17", measureObject.GetParam_Double, cad.eMEASUREPARAM_dSecondPointX, float)#Measurement Point 2 X
            # _GetFunction("PAR_18", measureObject.GetParam_Double, cad.eMEASUREPARAM_dSecondPointY, float)#Measurement Point 2 Y
            
        elif enum == cad.eMEASURETYPE_MID:
            _GetFunction("PAR_1",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointX, float)#X Position
            _GetFunction("PAR_2",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointY, float)#Y Position
            _GetFunction("PAR_3",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bTE, bool)#Thread Wire
            _GetFunction("PAR_4",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool)#Cut Wire
            _GetFunction("PAR_5",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bFinalMove, bool)#Circle direction
            _GetFunction("PAR_6",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dXMomentary, float)#G92 X
            _GetFunction("PAR_7",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dYMomentary, float)#G92 Y          
            _GetFunction("PAR_8",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dTouchAngle, float)#Touch Angle
            _GetFunction("PAR_9",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float)#Approach Distance X
            _GetFunction("PAR_10", measureObject.GetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float)#Fast Advance I (X)
            _GetFunction("PAR_11", measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float)#Approach Distance Y
            _GetFunction("PAR_12", measureObject.GetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float)#Fast Advance J (Y)
            
        elif enum == cad.eMEASURETYPE_PLM:
            _GetFunction("PAR_1",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointX, float)#X Position
            _GetFunction("PAR_2",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointY, float)#Y Position
            _GetFunction("PAR_3",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bTE, bool)#Thread Wire
            _GetFunction("PAR_4",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool)#Cut Wire
            _GetFunction("PAR_5",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bFinalMove, bool)#Circle direction
            _GetFunction("PAR_6",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dXMomentary, float)#G92 X
            _GetFunction("PAR_7",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dYMomentary, float)#G92 Y          
            _GetFunction("PAR_8",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dTouchAngle, float)#Touch Angle
            _GetFunction("PAR_9",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float)#Approach Distance X
            _GetFunction("PAR_10", measureObject.GetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float)#Fast Advance I (X)
            _GetFunction("PAR_11", measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float)#Approach Distance Y
            _GetFunction("PAR_12", measureObject.GetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float)#Fast Advance J (Y)
            _GetFunction("PAR_15", measureObject.GetParam_Double, cad.eMEASUREPARAM_dThirdPointX, float)#Measurement Point 3 X
            _GetFunction("PAR_16", measureObject.GetParam_Double, cad.eMEASUREPARAM_dThirdPointY, float)#Measurement Point 3 Y
            _GetFunction("PAR_17", measureObject.GetParam_Double, cad.eMEASUREPARAM_dSecondPointX, float)#Measurement Point 2 X
            _GetFunction("PAR_18", measureObject.GetParam_Double, cad.eMEASUREPARAM_dSecondPointY, float)#Measurement Point 2 Y
            
        elif enum == cad.eMEASURETYPE_EXC:
            _GetFunction("PAR_1",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointX, float)#X Position
            _GetFunction("PAR_2",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointY, float)#Y Position
            _GetFunction("PAR_3",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bTE, bool)#Thread Wire
            _GetFunction("PAR_4",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool)#Cut Wire
            _GetFunction("PAR_5",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bFinalMove, bool)#Circle direction (1=CW/0=CCW)
            _GetFunction("PAR_6",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dXMomentary, float)#G92 X
            _GetFunction("PAR_7",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dYMomentary, float)#G92 Y          
            _GetFunction("PAR_9",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float)#Approach Distance X
            _GetFunction("PAR_10", measureObject.GetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float)#Fast Advance I (X)
            _GetFunction("PAR_11", measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float)#Approach Distance Y
            _GetFunction("PAR_12", measureObject.GetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float)#Fast Advance J (Y)
            _GetFunction("PAR_15", measureObject.GetParam_Double, cad.eMEASUREPARAM_dThirdPointX, float)#Measurement Endpoint X
            _GetFunction("PAR_16", measureObject.GetParam_Double, cad.eMEASUREPARAM_dThirdPointY, float)#Measurement Endpoint Y
            _GetFunction("PAR_17", measureObject.GetParam_Double, cad.eMEASUREPARAM_dSecondPointX, float)#Measurement Point 2 X
            _GetFunction("PAR_18", measureObject.GetParam_Double, cad.eMEASUREPARAM_dSecondPointY, float)#Measurement Point 2 Y
            _GetFunction("PAR_19", measureObject.GetParam_Double, cad.eMEASUREPARAM_dSphericalRadius, float)#Measure Circle radius
            _GetFunction("PAR_20", measureObject.GetParam_Bool, cad.eMEASUREPARAM_bDontZeroXYCorrection, bool)#Cylindrical Hole
            
        elif enum == cad.eMEASURETYPE_PAL:
            _GetFunction("PAR_1",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointX, float)#X Position
            _GetFunction("PAR_2",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointY, float)#Y Position
            _GetFunction("PAR_3",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bTE, bool)#Thread Wire
            _GetFunction("PAR_4",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool)#Cut Wire
            _GetFunction("PAR_5",  measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bFinalMove, bool)#Circle direction
            _GetFunction("PAR_6",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dXMomentary, float)#G92 X
            _GetFunction("PAR_7",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dYMomentary, float)#G92 Y          
            _GetFunction("PAR_8",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dTouchAngle, float)#Touch Angle
            _GetFunction("PAR_9",  measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float)#Approach Distance X
            _GetFunction("PAR_10", measureObject.GetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float)#Fast Advance I (X)
            _GetFunction("PAR_11", measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float)#Approach Distance Y
            _GetFunction("PAR_12", measureObject.GetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float)#Fast Advance J (Y)
            _GetFunction("PAR_13", measureObject.GetParam_Int,    cad.eMEASUREPARAM_iMeasureSide, int)#Measured Angle
            _GetFunction("PAR_14", measureObject.GetParam_Int,    cad.eMEASUREPARAM_iMeasurementPoints, int)#Movement Amount

        # Fill the rest up to  with empty entry
        for i in range(1, 21):
            key = "PAR_{}".format(i)
            if key not in dictType:
                dictType[key] = {"widgets": "0", "value": '-32768', "name": "", "comment": ""}
       

        logger.info(LOG_TAG + " * Success reading {} params from C++.".format(strMeasureCycleType))
        #
        return {strMeasureCycleType : dictType}
    
    def ReadParamsFromPepsString(self):
        """
        This function reads the paramter data from PEPS string.
        """
        global strMeasureCycleType
        
        # TESTSTRING hart reingeschrieben: 'C:\Program Files\PEPS_2023\post\wire\UNIQUA\Common\init_pp.ovm'
        # 'MESSZYKLUS : EDG - Kante antuschieren (+X)                      mcy       20400 1 -9.1 -9.1 0 1 0 2 2 1 -99.1 -99.1 -9.1 1 -99.1 -9.1 -9.1 -9.1 -9.1 -9.1 -9.1 -9.2 -9.2 -9.2 -9.2 -9.2 -9.2 -9.2 -9.2 2.82'
        # self.tmpParams = {'EDG': {'PAR_1': {'widgets': '0', 'value': '-32768', 'name': 'X Momentary', 'comment': 'not used'}, ... }
        
        logger.info(LOG_TAG + " * Start reading {} params from Peps.".format(strMeasureCycleType))
        #
        # if strMeasureCycleType in self.tmpParams:
        #     dictType = self.tmpParams[strMeasureCycleType]
        # else:
        dictType = {}

        s1 = measureString[0:64]            # 'MESSZYKLUS : EDG - Kante antuschieren (+X)' # @UnusedVariable
        s2 = measureString[64:74]           # 'mcy       ' # @UnusedVariable
        s3 = measureString[74:].strip()     # '20401 1 -9.1 -9.1 0 1 0 2 2 1 -99.1 -99.1 -9.1 1 -99.1 -9.1 -9.1 -9.1 -9.1 -9.1 -9.1 -9.2 -9.2 -9.2 -9.2 -9.2 -9.2 -9.2 -9.2 2.82'
        if '\'' in s3 or '\"' in s3:
            P2CMessageBox("Illegal quotes in measure string!")
            return

        for i, s in enumerate(s3.split()):
            if i == 0:
                pepsID = s # @UnusedVariable --> 20401
            elif i == 1:
                strMeasureCycleType = GetMeasureCycleTypeString(int(s))
            else:
                kyParam = "PAR_{}".format(i - 1)
                
                # Set "widgets" to "0" if value is NOT_SET
                if s == "-32768":
                    w = "0"
                # Default: "widgets" set to "1"
                else:
                    w = "1"
                    
                if kyParam in dictType:
                    dictType[kyParam]["value"] = s
                else:
                    dictType[kyParam] = {"widgets": w, "value": s, "name": "", "comment": ""}

        logger.info(LOG_TAG + " * Success reading {} params from Peps.".format(strMeasureCycleType))
        #
        return {strMeasureCycleType : dictType}    
            
    def SaveParams(self, iSource=1):
        """
        This function saves changed parameter either to the User_XML file or the main C++ System.
        
        Notes:
        1, Save parameters into xml file
        2, Save parameter into object of main system
        
        call TransferDataFromWindow before that in case 2 
        """
        if iSource == 1:
            logger.info(LOG_TAG + " * Start Save params value into xml file.")
            # use the local variable for debug
            if not os.access(GetUserDataXMLPath(), os.W_OK):
                logger.error("{} Cannot write file - no permission in {}!".format(LOG_TAG, GetUserDataXMLPath()))
                P2CMessageBox("No permission in\n\n{}!".format(GetUserDataXMLPath()))
                return False
            
            if os.path.exists(GetUserDataXMLFile()):
                strXMLPath = GetUserDataXMLFile()
            else:
                #copy file "MeasureCycleDefaults.xml" to "MeasureCycleUserDefaults.xml" 
                strMusterXMLPath = GetDefaultDataXMLFile()
                strXMLPath = GetUserDataXMLFile()
                shutil.copy(strMusterXMLPath, strXMLPath)
            strMeasureType = self.strMType
            inputDict = self.tmpParams.copy()
            GeneralUpdateMeasureCycleDefaultParams(strXMLPath, MEASURECYCLEMACHINENAME, strMeasureType, strVersion, inputDict)
            logger.info(LOG_TAG + " * Success Save params value into xml file.")
            return True
        else: # destination 2 into main sytem object
            logger.info(LOG_TAG + " * Save params value into main system.")
            logger.info(LOG_TAG + " * Success Save params value into main system.")
            return True
        
           
    def GetUnitsOfParams(self,PanelDict):
        """
        This functions gets and saves all output units of all widgets in all panels to a dictionary.
        """
        for value in PanelDict.values():
            new_dict={}
            for child in value.GetChildren():
                if hasattr(child,"edit"):
                    if child.Name.find("PAR_")>=0:   
                        new_dict[child.Name]=child.edit.behaviour 
            self.OutputUnitDict[value.name]=new_dict
        return   
             
       
    def CreateWidgets(self):  # @UnusedVariable
        """
        This functions creates all sub-dialog widgets for each measure type. Initially they are hidden and are activated accordingly
        
        Notes:
        undocked best size (470, 910)
        """
        #self.panel.Layout()
        #self.unDockBestSize = (470 * ScreenScaleFactor, 910 * ScreenScaleFactor)
        #self.inDockBestSize = (450 * ScreenScaleFactor, 800 * ScreenScaleFactor)
        # Put everything in a VERTICAL wxBoxSizer       (Mainsizer)
        self.vbxV1 = wx.BoxSizer( wx.VERTICAL )
        # decide depending on scrolling-ability which BasePanel Class we have to use
        self.ButtonPanel = MyMainButtonsPanel(self, wx.ID_ANY)
#        self.ButtonPanel.btnOK.Disable()
        self.ButtonPanel.Layout()
        self.DummyPanel = DummyPanel(self, wx.ID_ANY)
        self.MainPanel = self.DummyPanel
        self.MainPanel.Layout()
        # add panel to into sizer
        self.vbxV1.Add(self.ButtonPanel, 0, wx.EXPAND)
        self.vbxV1.Add(self.MainPanel, 1, wx.EXPAND)
        if self.statusbar:

            self.stabar = CustomStatusBar(self, "Statusbar", style=wx.FULL_REPAINT_ON_RESIZE)
            self.vbxV1.Add(self.stabar, 0, wx.EXPAND)
            #self.stabar2 = CustomStatusBar(self, "Statusbar2")
            #self.vbxV1.Add(self.stabar2, 0, wx.EXPAND)
        
        self.OutputUnitDict={}

        
        self.SetSizerAndFit(self.vbxV1)
        
        Panel = MyPanelMeasureCycleType1(self, wx.ID_ANY, name="EDG")
        Panel.Hide()
        self.vbxV1.Add(Panel, 1, wx.EXPAND)
        self.pnldic['0001'] = Panel
        
        Panel = MyPanelMeasureCycleType2(self, wx.ID_ANY, name="CEN")
        Panel.Hide()
        self.vbxV1.Add(Panel, 1, wx.EXPAND)
        self.pnldic['0002'] = Panel
                  
        Panel = MyPanelMeasureCycleType3(self, wx.ID_ANY, name="CRN")
        Panel.Hide()
        self.vbxV1.Add(Panel, 1, wx.EXPAND)
        self.pnldic['0003'] = Panel
        
        Panel = MyPanelMeasureCycleType4(self, wx.ID_ANY, name="MID")
        Panel.Hide()
        self.vbxV1.Add(Panel, 1, wx.EXPAND)
        self.pnldic['0004'] = Panel
        
        Panel = MyPanelMeasureCycleType5(self, wx.ID_ANY, name="PLM")
        Panel.Hide()
        self.vbxV1.Add(Panel, 1, wx.EXPAND)
        self.pnldic['0005'] = Panel
        
        Panel = MyPanelMeasureCycleType6(self, wx.ID_ANY, name="EXC")
        Panel.Hide()
        self.vbxV1.Add(Panel, 1, wx.EXPAND)
        self.pnldic['0006'] = Panel
        
        Panel = MyPanelMeasureCycleType7(self, wx.ID_ANY, name="PAL")
        Panel.Hide()
        self.vbxV1.Add(Panel, 1, wx.EXPAND)
        self.pnldic['0007'] = Panel

        #
        # Panel = MyPanelMeasureCycleType8(self, wx.ID_ANY, name="CAL")
        # Panel.Hide()
        # self.vbxV1.Add(Panel, 1, wx.EXPAND)
        # self.pnldic['0008'] = Panel
        #
        # Panel = MyPanelMeasureCycleType9(self, wx.ID_ANY, name="EXC")
        # Panel.Hide()
        # self.vbxV1.Add(Panel, 1, wx.EXPAND)
        # self.pnldic['0009'] = Panel

        #self.Layout()
        self.GetUnitsOfParams(self.pnldic)
        
    
    def CreateMakinoMeasureCyclePreview(self, name):
        """
        This function creates the measure cycle NC code preview in the bottom left of the sub-dialog.
        """    
        return CreateMeasureCycleString(measurePreview=True, MeasureType=name, MainPanel=self.MainPanel)
    
    
    def _common_regenerate_output(self, mType):  # @UnusedVariable
        """
        This function regenerates the Measure cycle NC code output and preview.
        
        Notes:
        Type1 EDG, tuple style, (Key, Value, digits)
        Type2 CEN, tuple style, (Key, Value, digits)
        Type3 CRN, tuple style, (Key, Value, digits)
        Type4 MID, tuple style, (Key, Value, digits)
        Type5 PLM, tuple style, (Key, Value, digits)
        Type6 EXC, tuple style, (Key, Value, digits)
        Type7 PAL, tuple style, (Key, Value, digits)
        
        """
        if MainOptions.get('outputUnits') == 'inch':
            toOU = cad.toINCH # @UnusedVariable      
        else:
            toOU = cad.toMM # @UnusedVariable
        strOutput = "XXXXXXXXXXXXXXXXXXXXXXXX" # @UnusedVariable
        strOutput2=self.CreateMakinoMeasureCyclePreview(self.MainPanel.name)
        try:                     
            if self.statusbar:
                self.stabar.SetText1(strOutput2)
                # Note: 16.6.2025; NimkeL:
                # Trigger refresh/repaint of the statusbar, for some reason this is now needed, or the 2nd (empty) text field will appear...
                # This would lead to the 1st text field not showing fully on change until manual resize of window.
                self.stabar.Reposition()
                          
            return True
        
        except Exception as e:
            logger.warning(LOG_TAG + " * ReGenerateOutput(), Error %s" % str(e))
            if self.statusbar:
                self.stabar.SetText1(strOutput)
                self.stabar.Reposition()

            return False
    
    
    def SwitchMeasureCyclePanel(self, mType):
        """
        This function switches the panel to the selected measurement cycle type.
        """
        rts = False
        # 09/10/2024 jorgk!
        # That creates asserts in wx 32!
        # Need to solve it!
        self.vbxV1.Detach(self.ButtonPanel)
        self.vbxV1.Detach(self.MainPanel)
        if self.statusbar:
            self.vbxV1.Detach(self.stabar)
            #self.vbxV1.Detach(self.stabar2)
        # 09/10/2024
        # hide the main Panel
        self.MainPanel.Hide()
        
        # 09/10/2024 jorgk!
        # Remove it from original!!
        idType = mType.type_id 
        if idType in self.pnldic:
            self.MainPanel = self.pnldic[idType]
            # rts = True
        else:
            self.MainPanel = self.DummyPanel
            # rts = False
        
        self.vbxV1.Detach(self.MainPanel)
        # Remove it from original!!
        # 09/10/2024 jorgk!
        
        # re-create the sizer, keep one sizer instance of this dialog
        self.vbxV1 = wx.BoxSizer( wx.VERTICAL )
        # get id of type
        idType = mType.type_id 
        if idType in self.pnldic:
            self.MainPanel = self.pnldic[idType]
            rts = True
        else:
            self.MainPanel = self.DummyPanel
            rts = False
        

        #
        self.MainPanel.Layout()
        self.MainPanel.Show()
        #
        if rts:
            enum = mType.enum  
            if hasattr(self.MainPanel, "MeasureInfo"):
                typeDescription=self.MainPanel.MeasureInfo.GetValue()
            else:    
                typeDescription = getMessageW(strMeasureCycleType, cad.PYTHON_MESSAGES, enum + 1100)
            self.SetTitle("{} - {}".format(self.title, typeDescription))
        #            
        self.Layout()
        #
        # add panel to into sizer
        self.vbxV1.Add(self.ButtonPanel, 0, wx.EXPAND)
        # All have been added in CreateWidgets!
        # 09/10/2024 jorgk!
        self.vbxV1.Detach(self.MainPanel)
        self.vbxV1.Add(self.MainPanel, 1, wx.EXPAND)
        if self.statusbar:
            self.vbxV1.Add(self.stabar, 0, wx.EXPAND)
            #self.vbxV1.Add(self.stabar2, 0, wx.EXPAND)
            #self.strOutput = MeasureCycleString(self.measureObject)
            
            #self.stabar1.SetText1(self.strOutput)
            
        self.SetSizerAndFit(self.vbxV1)
        
        return rts

    def OnOK(self, event):
        """
        This function gets called whenever the "OK" button in the top left is pressed.
        """
        global strMeasureCycleType
        
        # Transfer value from windows to the attributes tmpParams and resetParams
        logger.info(LOG_TAG + " * OnOK(), transfer value from windows to the attributes tmpParams and resetParams")
        # dictType = self.tmpParams[self.strMType]
        # TransferDataFromWindow(self.MainPanel, dictType)
        # self.tmpParams[self.strMType] = dictType
        TransferDataFromWindow(self.MainPanel, self.tmpParams[self.strMType])
        #
        if inPeps():    # TODO ATM ONLY EXPERIMENTAL
            ### EXPERIMENTAL ########### (try working with a measureObject in peps also , but atm. I don't have one!!!
            #self.WriteParamsToMeasureObject()        # Update the measureObject
            ############################
            if self.strMType in self.tmpParams:
                self.WriteParamsToPepsString(self.tmpParams[self.strMType])
        else:
            self.SaveParamsToCplusplus()        # Update the measureObject
        #
        if self.bCallFromPyMain == True:    # we are called from python-maindialog (filled a new measureObject)
            cad.getCurrentDoc().NewMeasure(measureObject, True)
        else:                               # we are called from C++ (give back the updated measureObject)
            cad.getCurrentDoc().ChangeMeasure(measureObject, True)
        #
        # Terminate selection mode
        self.StopSelection()
        
        # Save the current dialog window position
        if "WindowPosition" in BaseDialog.kwargsBuffer:
            BaseDialog.kwargsBuffer['WindowPosition'] = self.GetScreenPosition()
        else:
            pass

        # Now hide the sub-dialog:
        if self.MainPanel:
            self.vbxV1.Show(self.MainPanel, show=False, recursive=True)

        super(self.__class__, self).OnOK(event)
        #
        strMeasureCycleType = ""    # reset for possible next call
        
        # Handle callbacks (used in peps, but also possible in all others)
        functiontocall = BaseDialog.kwargsBuffer.get("callbackoksub")
        if functiontocall and callable(functiontocall):
            BaseDialog.kwargsBuffer["measureString"] = measureString
            functiontocall(*BaseDialog.argsBuffer, **BaseDialog.kwargsBuffer)
            pass
        ResetTooltipHoldingTime()

    def OnESC(self, event):
        """
        This function gets called whenever the "ESCAPE - X" button in the top left is pressed.
        """
        if self.bCallFromPyMain == True:      # we are called from python-maindialog
            pass
        else:                               # we are called from C++
            cad.getCurrentDoc().ChangeMeasure(measureObject, True)

        # Terminate selection mode
        self.StopSelection()
        
        if "WindowPosition" in BaseDialog.kwargsBuffer:
            BaseDialog.kwargsBuffer['WindowPosition'] = self.GetScreenPosition()
        else:
            pass

        # ...and show the main dialog again (if we are not invoked directly from C++)
        if self.bCallFromPyMain:
            """ to show modeless dialogs from within python: """
            pyobj = cad.getCurrentDoc().GetPyObj()
            # Now show the dialog:
            pyobj.ShowModlessListObjectDlg("DLG_MEASURE_CYCLIE_MAIN")        # Use here the NAME of the dialog (not class name)
###            pyobj.ShowModlessListObject(self.parent)                        # use here the reference (BOTH WAYS ARE WORKING)

        # Now hide the sub-dialog:
    
        super(self.__class__, self).OnESC(event)
    
    def OnSave(self, event):  # @UnusedVariable
        """
        This function gets called whenever the "SAVE" button in the top left is pressed.
        """
        
        # Transfer value from windows to the attributes tmpParams and resetParams
        logger.info(LOG_TAG + " * OnSave(), transfer value from windows to the attributes tmpParams and resetParams")
        dictType = self.tmpParams[self.strMType]
        TransferDataFromWindow(self.MainPanel, dictType)
        # save the new value into xml file
        logger.info(LOG_TAG + " * OnSave(), save the new value into xml file")
        self.SaveParams(iSource=1)
        # save button states to class variables
        logger.info(LOG_TAG + " * OnSave(), save the new values into class variables")
       

    def OnReset(self, event):  # @UnusedVariable
        """
        This function gets called whenever the "RESET" button in the top left is pressed.
        """        
        # Clean the tmpParams dictionary
        logger.info(LOG_TAG + " * OnReset(), clean the tmpParams dictionary")
        self.tmpParams.clear()
        # Copy the params from resetParams dictionary to tmpParms dictionary
        logger.info(LOG_TAG + " * OnReset(), copy the params from resetParams dictionary to tmpParms dictionary")
        self.tmpParams = self.resetParams.copy()
        # transfer the value to windows   
        logger.info(LOG_TAG + " * OnReset(), transfer the value to windows")
        dictType = self.tmpParams[self.strMType]
        TransferDataToWindow(self.MainPanel, dictType)
        # Change widgets according to previously saved states
        logger.info(LOG_TAG + " * OnReset(), activate saved user or default widget values/states")
        # regenerate output for NC code and preview
        self.regenerate_output(self.mType)
        
        
    def SetDockState(self, state):
        """
        This function sets the "docked" state of the panel.
        """ 
        if state == True:
            self.docked = True
            self.ButtonPanel.btnDOC.SetBitmap( getOpticamIcon(PINBUTTON_DOCKED) )
        else:
            self.docked = False
            self.ButtonPanel.btnDOC.SetBitmap( getOpticamIcon(PINBUTTON_UNDOCKED) )
    
        
    # def OnRadioBoxRotationClicked(self, event):
    #     """
    #     This function handles the event of the "RadioBoxRotation" being clicked.
    #     """
    #     vDegree=self.MainPanel.rbSTDirection.GetSelection()
    #     vDegree=self.MainPanel.rbSTDirection.GetItemLabel(vDegree)
    #     vDegree=int(vDegree)
    #     axisVal=0 # @UnusedVariable
    #     if vDegree == 0:
    #         logger.info(LOG_TAG + " * OnRadioBoxRotationClicked(), The radio button for degree: %s " % 0)
    #         self.MainPanel.stBitmap.SetBitmap(self.MainPanel.bmpX)
    #
    #     elif vDegree == 1:
    #         logger.info(LOG_TAG + " * OnRadioBoxRotationClicked(), The radio button for degree: %s " % 90)
    #         self.MainPanel.stBitmap.SetBitmap(self.MainPanel.bmpY)
    #
    #     elif vDegree == 2:
    #         logger.info(LOG_TAG + " * OnRadioBoxRotationClicked(), The radio button for degree: %s " % 180)
    #         self.MainPanel.stBitmap.SetBitmap(self.MainPanel.bmp180)
    #
    #     else: # 270
    #         logger.info(LOG_TAG + " * OnRadioBoxRotationClicked(), The radio button for degree: %s " % 270)
    #         self.MainPanel.stBitmap.SetBitmap(self.MainPanel.bmp270)
    #
    #     self.MainPanel.stBitmap.Refresh()
    #     #update the new value to (added rotation)
    #     if hasattr(self.MainPanel, "lefSTDirection"):
    #         logger.info(LOG_TAG + " * OnRadioBoxRotationClicked(), Set the degree value in text ctrl: %s " % vDegree)
    #         #self.MainPanel.lefAxis.edit.ChangeValue("%s" % axisVal)
    #         self.MainPanel.lefSTDirection.edit.SetValue("%s" % vDegree)
    #         logger.info(LOG_TAG + " * OnRadioBoxRotationClicked(), Regenerate the command output, the value of : %s widgets was changed" % event.EventObject.GetName())
    #         self.regenerate_output(self.mType)
    #
    #     self.Refresh()
        
        
    def OnRadioBoxMeasureDirectionClicked(self, event, vDir):
        """
        This function handles the event of the "RadioBoxMeasureDirection" being clicked.
        """
        global strMeasureCycleType
        
        if hasattr(self.MainPanel, "lLEFXStart") and hasattr(self.MainPanel, "lLEFYStart"):     # senseless if no point 1
            logger.info(LOG_TAG + " * OnRadioButtonRotationClicked(), The radio button for direction: %s has been selected." % vDir)
            
            # if hasattr(self.MainPanel, "lefApprX"):
            #     self.MainPanel.lefApprX.edit.SetValue("")
            # if hasattr(self.MainPanel, "lefApprY"):
            #     self.MainPanel.lefApprY.edit.SetValue("")

            if hasattr(self.MainPanel, "stBitmap"):
                if vDir == '+X':
                    self.MainPanel.stBitmap.SetBitmap(self.MainPanel.bmpX)
                    if strMeasureCycleType in self.tmpParams and strMeasureCycleType not in ['CRN', 'PLM', 'PAL']: # don't do this for defined cycle types
                        # Widgets to be deactivated
                        self.MainPanel.lefApprY.edit.SetValue("")
                        self.MainPanel.lefApprY.Enable(False)
                        self.MainPanel.lefFastAdvJ.cbCheck.SetValue(False)
                        self.MainPanel.lefFastAdvJ.cbCheck.Enable(False)
                        self.MainPanel.lefFastAdvJ.edit.SetValue("")
                        self.MainPanel.lefFastAdvJ.Enable(False)
                        # Widgets to be activated
                        self.MainPanel.lefApprX.edit.SetValue("0")
                        self.MainPanel.lefApprX.Enable(True)
                        self.MainPanel.lefFastAdvI.cbCheck.SetValue(True)
                        self.MainPanel.lefFastAdvI.cbCheck.Enable(True)
                        self.MainPanel.lefFastAdvI.edit.SetValue("0")
                        self.MainPanel.lefFastAdvI.Enable(True)
                    if strMeasureCycleType in self.tmpParams and strMeasureCycleType in ['PAL']: # Only do this for PAL
                        # Widgets to be deactivated
                        self.MainPanel.lefFastAdvI.cbCheck.SetValue(False)
                        self.MainPanel.lefFastAdvI.cbCheck.Enable(False)
                        self.MainPanel.lefFastAdvI.edit.SetValue("")
                        self.MainPanel.lefFastAdvI.Enable(False)
                        # Widgets to be activated
                        self.MainPanel.lefFastAdvJ.cbCheck.SetValue(True)
                        self.MainPanel.lefFastAdvJ.cbCheck.Enable(True)
                        self.MainPanel.lefFastAdvJ.edit.SetValue("0")
                        self.MainPanel.lefFastAdvJ.Enable(True)
                elif vDir == '+Y':
                    self.MainPanel.stBitmap.SetBitmap(self.MainPanel.bmpY)
                    if strMeasureCycleType in self.tmpParams and strMeasureCycleType not in ['CRN', 'PLM', 'PAL']: # don't do this for defined cycle types
                        # Widgets to be deactivated
                        self.MainPanel.lefApprX.edit.SetValue("")
                        self.MainPanel.lefApprX.Enable(False)
                        self.MainPanel.lefFastAdvI.cbCheck.SetValue(False)
                        self.MainPanel.lefFastAdvI.cbCheck.Enable(False)
                        self.MainPanel.lefFastAdvI.edit.SetValue("")
                        self.MainPanel.lefFastAdvI.Enable(False)
                        # Widgets to be activated
                        self.MainPanel.lefApprY.edit.SetValue("0")
                        self.MainPanel.lefApprY.Enable(True)
                        self.MainPanel.lefFastAdvJ.cbCheck.SetValue(True)
                        self.MainPanel.lefFastAdvJ.cbCheck.Enable(True)
                        self.MainPanel.lefFastAdvJ.edit.SetValue("0")
                        self.MainPanel.lefFastAdvJ.Enable(True)
                    if strMeasureCycleType in self.tmpParams and strMeasureCycleType in ['PAL']: # Only do this for PAL
                        # Widgets to be deactivated
                        self.MainPanel.lefFastAdvJ.cbCheck.SetValue(False)
                        self.MainPanel.lefFastAdvJ.cbCheck.Enable(False)
                        self.MainPanel.lefFastAdvJ.edit.SetValue("")
                        self.MainPanel.lefFastAdvJ.Enable(False)
                        # Widgets to be activated
                        self.MainPanel.lefFastAdvI.cbCheck.SetValue(True)
                        self.MainPanel.lefFastAdvI.cbCheck.Enable(True)
                        self.MainPanel.lefFastAdvI.edit.SetValue("0")
                        self.MainPanel.lefFastAdvI.Enable(True)
                # elif vDir == '-X':
                #     self.MainPanel.stBitmap.SetBitmap(self.MainPanel.bmp180)
                #     if strMeasureCycleType in self.tmpParams and strMeasureCycleType not in ['CRN', 'PLM']: # don't do this for defined cycle types
                #     # Widgets to be deactivated
                #         self.MainPanel.lefApprY.edit.SetValue("")
                #         self.MainPanel.lefApprY.Enable(False)
                #         self.MainPanel.lefFastAdvJ.cbCheck.SetValue(False)
                #         self.MainPanel.lefFastAdvJ.cbCheck.Enable(False)
                #         self.MainPanel.lefFastAdvJ.edit.SetValue("")
                #         self.MainPanel.lefFastAdvJ.Enable(False)
                #         # Widgets to be activated
                #         self.MainPanel.lefApprX.edit.SetValue("0")
                #         self.MainPanel.lefApprX.Enable(True)
                #         self.MainPanel.lefFastAdvI.cbCheck.SetValue(True)
                #         self.MainPanel.lefFastAdvI.cbCheck.Enable(True)
                #         self.MainPanel.lefFastAdvI.edit.SetValue("0")
                #         self.MainPanel.lefFastAdvI.Enable(True)
                # elif vDir == '-Y':
                #     self.MainPanel.stBitmap.SetBitmap(self.MainPanel.bmp270)
                #     if strMeasureCycleType in self.tmpParams and strMeasureCycleType not in ['CRN', 'PLM']: # don't do this for corner measrement
                #         # Widgets to be deactivated
                #         self.MainPanel.lefApprX.edit.SetValue("")
                #         self.MainPanel.lefApprX.Enable(False)
                #         self.MainPanel.lefFastAdvI.cbCheck.SetValue(False)
                #         self.MainPanel.lefFastAdvI.cbCheck.Enable(False)
                #         self.MainPanel.lefFastAdvI.edit.SetValue("")
                #         self.MainPanel.lefFastAdvI.Enable(False)
                #         # Widgets to be activated
                #         self.MainPanel.lefApprY.edit.SetValue("0")
                #         self.MainPanel.lefApprY.Enable(True)
                #         self.MainPanel.lefFastAdvJ.cbCheck.SetValue(True)
                #         self.MainPanel.lefFastAdvJ.cbCheck.Enable(True)
                #         self.MainPanel.lefFastAdvJ.edit.SetValue("0")
                #         self.MainPanel.lefFastAdvJ.Enable(True)
        if hasattr(self.MainPanel, "rbCW") and hasattr(self.MainPanel, "rbCCW"):         
            if hasattr(self.MainPanel, "stBitmap"):
                if vDir == 'CW':
                    self.MainPanel.stBitmap.SetBitmap(self.MainPanel.bmpCW)
                elif vDir == 'CCW':
                    self.MainPanel.stBitmap.SetBitmap(self.MainPanel.bmpCCW)
                    
        self.MainPanel.stBitmap.Refresh()   
        
        self.MainPanel.Refresh()
        self._common_regenerate_output(self.mType)#generate statusbar text for measure cycle
    
    def OnSaveProfileButtonClicked(self, event):  # @UnusedVariable
        """
        This function handles the event of the "SaveProfileButton" being clicked.
        """
        
        dlg = MeasureCycleDialogSaveProfile(parent=self, modal=True, title="Save inputs to database",
                                              size=wx.DefaultSize, name="DLG_MEASURE_CYCLIE_SAVE_PROFILE", iconShowSave=False)
        # transfer value from windwos to tmpParams
        dictType = self.tmpParams[self.strMType]
        TransferDataFromWindow(self.MainPanel, dictType)
        # get dict of tmpSQLite, create the dict of this instance,  as a temporary storage area for those data
        tmpSQLiteDict = self.GetTempSQLiteDict()
        # Update the value of this dict from this measure type dialog
        strMtype = self.mType.name
        # get dict of this measure type
        dictMType = self.tmpParams[strMtype]
        # create a dict for all "PAR_X": value 
        dictParams = dict(map(lambda item: (item[0], item[1]['value']), dictMType.items()))
        UpdateDictRecursively(tmpSQLiteDict, dictParams)
        # Update KEY_PART1
        strMID = self.mType.type_id
        tmpSQLiteDict["KEY_PART1"] = strMID
        # Update machine id
        strMachineID = self.GetMachineID()
        tmpSQLiteDict["CUSTOMER1"] = strMachineID
        # get old index
        strIndex =  tmpSQLiteDict["SEARCHTERM"]
        # check if it need saved as a new record
        if self.bInsertIntoSQLiteAsNewRecord:
            # find free index i.e. SEARCHTERM
            # Create a connection with database
            self.ConnectSQLiteDatabase()
            # Check if the index of record is already exist in database
            while self.CheckIfSearchTermAlreadyExist(strIndex, strMID, strMachineID):
                strIndex = "%d" % (int(strIndex) + 1)
            tmpSQLiteDict["SEARCHTERM"] = strIndex
        # Update machine name
        strMachineName = self.GetMachineName()
        tmpSQLiteDict["CUSTOMER2"] = strMachineName
        # Update version
        #tmpSQLiteDict["PAR_28"] = self.strVersion
        # Create comment 2
        #strRts2 = self.create_comment2(self.mType)
        strRts2 = strMtype
        tmpSQLiteDict["COMMENT2"] = strRts2
        # Create comment 3
        #strRts3 = self.create_comment3(self.mType)
        strRts3 = strMachineName
        tmpSQLiteDict["COMMENT3"] = strRts3
        # Create comment 4
        #strRts4 = self.create_comment4(self.mType)
        strRts4 = datetime.now().strftime("%d.%m.%Y %H:%M:%S")
        tmpSQLiteDict["COMMENT4"] = strRts4
        # update the sqlite dict, it actually  transfers the values form the dictionary of 
        # this instance to the dictionary of the "save dialog" instance
        # the both dictionaries are equal now
        dlg.SetTempSQLiteDict(tmpSQLiteDict)
        # the ShowModal will fire the method TransferDataToWindow
        if dlg.ShowModal() == wx.ID_OK:
            # update the tmpSQLite dict by using the dictionay of dlg instance, for next open
            self.SetTempSQLiteDict(dlg.tmpSQLite)
            # set the flag True
            self.bInsertIntoSQLiteAsNewRecord = True
        else:
            # do nothing
            pass
    
    def OnLoadProfileButtonClicked(self, event):  # @UnusedVariable
        """
        This function handles the event of the "LoadProfileButton" being clicked.
        """

        # Update KEY_PART1
        strMID = self.mType.type_id
        # Update machine id
        strMachineID = self.GetMachineID()
        # Create a connection with database
        self.ConnectSQLiteDatabase()
        bEntriesExistByType = self.CheckIfEntriesOfMeasureTypeAlreadyExist(strMID, strMachineID)
        if bEntriesExistByType :
            dlg = MeasureCycleDialogLoadProfile(parent=self, modal=True, title="Load inputs from database",
                                                  size=wx.DefaultSize, name="DLG_MEASURE_CYCLIE_LOAD_PROFILE",
                                                   iconShowSave=False)
            # get tmpSQLite dictionary 
            tmpSQLiteDict = self.GetTempSQLiteDict()
            # Update KEY_PART1
            strMID = self.mType.type_id
            tmpSQLiteDict["KEY_PART1"] = strMID
            # Update machine id
            strMachineID = self.GetMachineID()
            tmpSQLiteDict["CUSTOMER1"] = strMachineID
            # Update machine name
            strMachineName = self.GetMachineName()
            tmpSQLiteDict["CUSTOMER2"] = strMachineName
            # Update version
            #tmpSQLiteDict["PAR_28"] = self.strVersion
            # update he dict 
            dlg.SetTempSQLiteDict(tmpSQLiteDict)
            # the ShowModal will fire the method TransferDataToWindow
            if dlg.ShowModal() == wx.ID_OK:
                # set the flag False
                self.bInsertIntoSQLiteAsNewRecord = False
                # update the tmpSQLite dict by using the dictionay of dlg instance, for next open
                self.SetTempSQLiteDict(dlg.tmpSQLite)
                # Reload the params from tmpSQLite
                dummy_rts = self.ReloadParams(dlg.tmpSQLite)
                # transfer the value to windows
                dictType = self.tmpParams[self.strMType]
                #TransferDataToWindow(self.MainPanel, dictType)
                self.ActivateAfterLoadProfile(dictType)#TransferDataToWindow is not sufficient to update the window and statusbar
            else:
                # set the flag True
                self.bInsertIntoSQLiteAsNewRecord = True
        else:
            strMsgLabel = getText("Warning", "MSG_LABEL_WARNING")
            strMsgContent = getText("No data has been saved yet", "MSG_CONTENT_NO_DATA_SAVED_YET")
            dlg = wx.MessageDialog(self, strMsgContent, strMsgLabel, wx.OK | wx.ICON_WARNING)
            dlg.ShowModal()
            dlg.Destroy()
               
    def OnImgBtnMeasureTypeNotToggleCaseClicked(self, event):
        """
        This functions handles the event when "ImgBtnMeasureTypeNotToggleCase" happens.
        """
        strMsgLabel = getText("Warning", "MSG_LABEL_WARNING")
        if event.EventObject.bMeasureWithWire:
            strMsgContent =  getText("Works only with wire", "STT_SHORT_DESC_COMMON_ONLY_WIRE")
            return
        else:
            strMsgContent =  getText("Works only with probe", "STT_SHORT_DESC_COMMON_ONLY_PROBE")
        dlg = wx.MessageDialog(self, strMsgContent, strMsgLabel, wx.OK | wx.ICON_WARNING)
        dlg.ShowModal()
        dlg.Destroy()
             
    def OnPickPositionPointButtonClicked(self, event):
        """
        This functions handles the event when on of the "PickPositionPointButton" is clicked.
        """
        global POINT_PICK

        objName = event.GetEventObject().GetName()
        
        if objName.endswith("1XY"):
            POINT_PICK[0]=True
            
        elif objName.endswith("2XY"):
            POINT_PICK[1]=True
            
        elif objName.endswith("3XY"):
            POINT_PICK[2]=True
            
        elif objName.endswith("DXY"):
            POINT_PICK[1]=True
            POINT_PICK[2]=True
        
        logger.info(LOG_TAG + " * OnPickPositionPointButtonClicked(), Picking position with: %s" % objName)
        
        # Start selection mode
        self.StartSelection()
       
    def OnPickPositionG92ButtonClicked(self, event):
        """
        This functions handles the event when the "PickPositionG92Button" is clicked.
        """
        global G92_PICK
        G92_PICK=True
        objName = event.GetEventObject().GetName()

        logger.info(LOG_TAG + " * OnPickPositionG92ButtonClicked(), Picking position with: %s" % objName)
        
        # Start selection mode
        self.StartSelection()
        
    def OnCutWireCheckboxChecked(self, event):
        """
        This function handles the event when the "CutWireCheckbox" is checked.
        """
        objControl = event.GetEventObject()  # @UnusedVariable
        if not event.IsChecked(): # the state false will be set
            logger.info(LOG_TAG + " * OnCutWireCheckboxChecked(), Set Checkbox False")
        else: # 
            logger.info(LOG_TAG + " * OnCutWireCheckboxChecked(), Set Checkbox True")
                      
    def OnThreadWireCheckboxChecked(self, event):
        """
        This function handles the event when the "ThreadWireCheckbox" is checked.
        """
        objControl = event.GetEventObject()  # @UnusedVariable
        if not event.IsChecked(): # the state false will be set
            logger.info(LOG_TAG + " * OnWireThreadWireCheckboxChecked(), Set Checkbox False")
        else: # 
            logger.info(LOG_TAG + " * OnWireThreadWireCheckboxChecked(), Set Checkbox True")
            
    def OnCylHoleCheckboxChecked(self, event):
        """
        This function handles the event when the "Cylindrical Hole Check Box" is checked.
        """
        objControl = event.GetEventObject()  # @UnusedVariable
        if not event.IsChecked(): # the state false will be set
            logger.info(LOG_TAG + " * OnCylHoleCheckboxChecked(), Set Checkbox False")
        else: # 
            logger.info(LOG_TAG + " * OnCylHoleCheckboxChecked(), Set Checkbox True")
        
        self._common_regenerate_output(self.mType)
            
    def OnDistanceResetCheckboxChecked(self, event):
        """
        This function handles the event when the "Distance Reset" is checked.
        """
        objControl = event.GetEventObject()  # @UnusedVariable
        if not event.IsChecked(): # the state false will be set
            logger.info(LOG_TAG + " * OnDistanceResetCheckboxChecked(), Set Checkbox False")
        else: # 
            logger.info(LOG_TAG + " * OnDistanceResetCheckboxChecked(), Set Checkbox True")
                
    def OnDistanceSettingsClicked(self, event):
        """
        This function handles the event when the "Lock Distance Radio Button" is clicked.
        """
        objControl = event.GetEventObject()  # @UnusedVariable
          
        if objControl.Name == "RB_KEEP":
            logger.info(LOG_TAG + " * OnDistanceSettingsClicked(), Option: Keep Distances")
        elif objControl.Name == "RB_ADJ":
            logger.info(LOG_TAG + " * OnDistanceSettingsClicked(), Option: Adjust Distances")
        elif objControl.Name == "RB_RESET":
            logger.info(LOG_TAG + " * OnDistanceSettingsClicked(), Option: Reset Distances")
            
    
    def OnPosAxisRadioButtonSelectionChanged(self, event):
        """
        This function handles the event when the Position Axis Radio Button is changed.
        """
        # objControl = event.GetEventObject()
        # objLabel = objControl.GetLabel()
        # logger.info(LOG_TAG + " * OnPosAxisRadioButtonSelectionChanged(), Radio Button for Position Axis selection was changed to %s" % objLabel)
        #
        # # X
        # if self.MainPanel.rbPosAxisX.GetValue():
        #     #self.MainPanel.lefFastAdvI.Enable(True)
        #     self.MainPanel.lefFastAdvI.cbCheck.Enable(True)
        #     self.MainPanel.lefFastAdvJ.SetValue("0")
        #     self.MainPanel.lefFastAdvJ.Enable(False)
        #     self.MainPanel.lefFastAdvJ.cbCheck.Enable(False)
        #     self.MainPanel.lefFastAdvJ.cbCheck.SetValue(False)
        #
        # # Y
        # if self.MainPanel.rbPosAxisY.GetValue():
        #     #self.MainPanel.lefFastAdvJ.Enable(True)
        #     self.MainPanel.lefFastAdvJ.cbCheck.Enable(True)
        #     self.MainPanel.lefFastAdvI.SetValue("0")
        #     self.MainPanel.lefFastAdvI.Enable(False)
        #     self.MainPanel.lefFastAdvI.cbCheck.Enable(False)
        #     self.MainPanel.lefFastAdvI.cbCheck.SetValue(False)
          
        self.regenerate_output(self.mType)
            

    def OnLabeledEFCheckboxChecked(self, event):
        """
        This function handles the event when a "LabeledEFCheckbox" is checked.
        """
        objControl = event.GetEventObject().GetParent()
        if isinstance(objControl, RealLeftLabeledDobbleEditFieldPickPos) or isinstance(objControl, RealLeftLabeledDobbleEditFieldPickPos2):
            #storeVal = event.GetEventObject().edit.GetValue()
            if not event.IsChecked(): # Box is unchecked
                event.GetEventObject().edit.Disable()
                #event.GetEventObject().lbl.Disable()
                #objControl.btnPickPos.Disable()
                #event.GetEventObject().edit.ChangeValue("-")
                logger.info(LOG_TAG + " * OnLabeledEFCheckboxChecked(), Set Checkbox %s set to False" % event.GetEventObject().Name)
            
            else: # Box is checked
                event.GetEventObject().edit.Enable()
                #event.GetEventObject().lbl.Enable()
                #objControl.btnPickPos.Enable()
                #event.GetEventObject().edit.ChangeValue(str(storeVal))
                # vMinVal = event.GetEventObject().edit.GetMinValue() # GetMinValue() return float or int
                # if vMinVal < 0:
                #     vMinValue = "0"
                # else:
                #     vMinValue = str(vMinVal)
                #logger.info(LOG_TAG + " * OnLabeledEFCheckboxChecked(), Set Checkbox True, Set (Min) Value: %s" % vMinValue)
                # if hasattr(event.GetEventObject().edit, "bWidgetLinkage"):
                #     if event.GetEventObject().edit.bWidgetLinkage:
                #         event.GetEventObject().edit.SetValue(vMinValue)  # to avoid the event handler
                #         # the code ret = wx.Dialog.ShowModal(self) will fire the function twice, can not solve the issue
                #         objControl.bWidgetLinkage(objControl, vMinValue)
                #     else:
                #         event.GetEventObject().edit.SetValue(vMinValue)  # to avoid the event handler    
                # else:
                #     event.GetEventObject().edit.SetValue(vMinValue)  # to avoid the event handler                
                logger.info(LOG_TAG + " * OnLabeledEFCheckboxChecked(), Set Checkbox %s set to True" % event.GetEventObject().Name)
                
            # Re-generate the command output
            logger.info(LOG_TAG + " * OnLabeledEFCheckboxChecked(), Regenerate the command output, the value of : %s widgets was changed" % objControl.GetName())
            self.regenerate_output(self.mType)
            
        else:
            # Only for EXC - Calculate the circle radius, if we come from a main system activate and there is no radius yet available
            if self.strMType == 'EXC' and not hasattr(self, 'r'):
                x1 = self.MainPanel.lLEFXStart.edit.GetValue()
                y1 = self.MainPanel.lLEFYStart.edit.GetValue()
                x2 = self.MainPanel.lLEFXP2.edit.GetValue()
                y2 = self.MainPanel.lLEFYP2.edit.GetValue()
                # Calculate measurement circle radius
                self.r = round(self.radius_from_points(x1, y1, x2, y2), self.MainPanel.lLEFXP3.decimalDigitsOfOuput)
            
            if not event.IsChecked(): # if unchecked
                objControl.Disable()
                objControl.edit.PrevValue = objControl.edit.GetValue()
                # Set edit field to the default value defined in the .xml-file
                defaultValue = "" #self.tmpParams[self.strMType][objControl.Name]['value']
                objControl.edit.SetValue(defaultValue) # if defaultValue != str(NOT_SET) else "0")
                logger.info(LOG_TAG + " * OnLabeledEFCheckboxChecked(), Set Checkbox False, Set empty Value: %s" % defaultValue)
                
                # if self.strMType in self.tmpParams and self.strMType == 'EXC':
                #     if hasattr(self.MainPanel, "lefCycCenI") and hasattr(self.MainPanel, "lefCycCenJ") and hasattr(self.MainPanel, "lefCircRad"):
                #         if objControl.Name == 'PAR_10' and self.MainPanel.lefCycCenJ.cbCheck.GetValue() == False:
                #             self.MainPanel.lefCircRad.Enable(True)
                #             self.MainPanel.lefCircRad.cbCheck.SetValue(True)
                #             self.MainPanel.lefCircRad.edit.SetValue(str(getattr(self, 'r', 0)))                       
                #         elif objControl.Name == 'PAR_12' and self.MainPanel.lefCycCenI.cbCheck.GetValue() == False:
                #             self.MainPanel.lefCircRad.Enable(True)
                #             self.MainPanel.lefCircRad.cbCheck.SetValue(True)
                #             self.MainPanel.lefCircRad.edit.SetValue(str(getattr(self, 'r', 0)))                
                #         elif objControl.Name == 'PAR_19':
                #             self.MainPanel.lefCycCenI.Enable(True)
                #             self.MainPanel.lefCycCenI.cbCheck.SetValue(True)
                #             self.MainPanel.lefCycCenI.edit.SetValue(str(getattr(self.MainPanel, 'i', 0)))
                #             self.MainPanel.lefCycCenJ.Enable(True)
                #             self.MainPanel.lefCycCenJ.cbCheck.SetValue(True)
                #             self.MainPanel.lefCycCenJ.edit.SetValue(str(getattr(self.MainPanel, 'j', 0)))
                            
            else: # if checked
                objControl.Enable()
                defaultValue = self.resetParams[self.strMType][objControl.Name]["value"]
                
                # Special case for PEPS, as the string contains NOT_SET value as an indication, that the widget is disabled.
                if inPeps() and defaultValue == str(NOT_SET):
                    if self.strMType == 'PAL' and objControl.Name == 'PAR_14': # This value is default 1
                        defaultValue = "1"
                    else:
                        defaultValue = "0"

                objControl.edit.SetValue(defaultValue)
                logger.info(LOG_TAG + " * OnLabeledEFCheckboxChecked(), Set Checkbox True, Set Default Value: %s" % defaultValue)
                
                if self.strMType in self.tmpParams and self.strMType == 'EXC':
                    if hasattr(self.MainPanel, "WriteDistances"):
                        x_center = self.MainPanel.lLEFXP2.edit.GetValue()
                        y_center = self.MainPanel.lLEFYP2.edit.GetValue()
                        if objControl.Name == 'PAR_10':
                            self.MainPanel.WriteDistances(x2=x_center)
                        elif objControl.Name == 'PAR_12':
                            self.MainPanel.WriteDistances(y2=y_center)
                 
                if self.strMType in self.tmpParams and self.strMType == 'CEN':
                    if hasattr(self.MainPanel, "lefApprX") and hasattr(self.MainPanel, "lefApprY"):
                        if objControl.Name == 'PAR_9':
                            self.MainPanel.lefApprY.edit.SetValue("")
                            self.MainPanel.lefApprY.Enable(False)
                            self.MainPanel.lefApprY.cbCheck.SetValue(False)
                            self.MainPanel.lefApprX.cbCheck.Enable(False)
                            self.MainPanel.lefApprY.cbCheck.Enable(True)
                        elif objControl.Name == 'PAR_11':
                            self.MainPanel.lefApprX.edit.SetValue("")
                            self.MainPanel.lefApprX.Enable(False)
                            self.MainPanel.lefApprX.cbCheck.SetValue(False)
                            self.MainPanel.lefApprY.cbCheck.Enable(False)
                            self.MainPanel.lefApprX.cbCheck.Enable(True)
                            
                # if self.strMType in self.tmpParams and self.strMType == 'EXC':
                #     if hasattr(self.MainPanel, "lefCycCenI") and hasattr(self.MainPanel, "lefCycCenJ") and hasattr(self.MainPanel, "lefCircRad"):
                #         if objControl.Name == 'PAR_10':
                #             self.MainPanel.lefCircRad.Enable(False)
                #             self.MainPanel.lefCircRad.cbCheck.SetValue(False)
                #             self.MainPanel.lefCircRad.edit.SetValue("")
                #             self.MainPanel.lefCycCenI.edit.SetValue(str(getattr(self.MainPanel, 'i', 0)))
                #         elif objControl.Name == 'PAR_12':
                #             self.MainPanel.lefCircRad.Enable(False)
                #             self.MainPanel.lefCircRad.cbCheck.SetValue(False)
                #             self.MainPanel.lefCircRad.edit.SetValue("")
                #             self.MainPanel.lefCycCenJ.edit.SetValue(str(getattr(self.MainPanel, 'j', 0)))
                #         elif objControl.Name == 'PAR_19':
                #             self.MainPanel.lefCycCenI.Enable(False)
                #             self.MainPanel.lefCycCenI.cbCheck.SetValue(False)
                #             self.MainPanel.lefCycCenI.edit.SetValue("")
                #             self.MainPanel.lefCycCenJ.Enable(False)
                #             self.MainPanel.lefCycCenJ.cbCheck.SetValue(False)
                #             self.MainPanel.lefCycCenJ.edit.SetValue("")
                #             self.MainPanel.lefCircRad.edit.SetValue(str(getattr(self, 'r', 0)))
                            
                            
            # Re-generate the command output
            logger.info(LOG_TAG + " * OnLabeledEFCheckboxChecked(), Regenerate the command output, the value of : %s widgets was changed" % objControl.GetName())
            self.regenerate_output(self.mType)
                         
        
    def OnLabeledEFTextCtrlChanged(self, event):
        """
        This function handles the event when the text in a "LabeledEFTextCtrl" is changed.
        It then for example updates the NC code preview and output.
        """
        #Reset guard flags
        # self.fromP2 = False
        # self.fromP3 = False
        # self.fromStart = False
        objControl = event.GetEventObject().GetParent()
        logger.info(LOG_TAG + " * OnLabeledEFTextCtrlChanged(), The state of : %s widget was changed" % objControl.GetName())
        if isinstance(objControl, RealLeftLabeledDobbleEditFieldPickPos) or isinstance(objControl, RealLeftLabeledDobbleEditFieldPickPos2):
            flValid = True
            event.GetEventObject().errMsg = " INVALID INPUT"
    #        if self.flRequired and val == '':
    #            flValid = False
            if flValid:
                flValid = event.GetEventObject().GetWindowValue()

            event.GetEventObject().SetError(not flValid)
            if flValid:
                # call linkage method if necessary
                if hasattr(event.GetEventObject(), "bWidgetLinkage"):
                    if event.GetEventObject().bWidgetLinkage:
                        event.GetEventObject().bWidgetLinkage(event.GetEventObject(),  event.GetEventObject().value)           
                # Re-generate the command output         
                logger.info(LOG_TAG + " * OnLabeledEFTextCtrlChanged(), Regenerate the command output, the value of : %s widgets was changed" % objControl.GetName())
                self.regenerate_output(self.mType)
                
        else:
            flValid = True
            objControl.edit.errMsg = " INVALID INPUT"

            if flValid:
                flValid = objControl.edit.GetWindowValue()
                
            objControl.edit.SetError(not flValid)
            # Only go here if we are called from an actual text change, and not by any SetValue()
            if flValid and not self.fromWritePickPosition and not self.fromActivate:
                # call linkage method if necessary
                if hasattr(objControl, "bWidgetLinkage"):
                    if objControl.bWidgetLinkage:
                        objControl.bWidgetLinkage(objControl,  objControl.edit.value)
                        
                # Special Case for PLM      
                if self.strMType in ["PLM"]:
                    x_start = self.MainPanel.lLEFXStart.edit.GetValue() or 0.0
                    y_start = self.MainPanel.lLEFYStart.edit.GetValue() or 0.0
                    if objControl.Name == "PAR_9": # D1   
                        d1_new = float(re.match(r"(-?\d+(?:\.\d+)?)", event.String).group(1)) # Get rid of "mm" or any unit after the value
                        if self.MainPanel.rbDirXPlus.Value == True: # X
                            if hasattr(self.MainPanel, "lLEFXP2"):
                                self.MainPanel.lLEFXP2.edit.SetValue(round(x_start-d1_new/2, self.MainPanel.lLEFXP2.decimalDigitsOfOuput))
                            if hasattr(self.MainPanel, "lLEFXP3"):
                                self.MainPanel.lLEFXP3.edit.SetValue(round(x_start+d1_new/2, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))                       
                        else: # Y
                            if hasattr(self.MainPanel, "lLEFXP2"):
                                self.MainPanel.lLEFXP2.edit.SetValue(round(x_start+d1_new, self.MainPanel.lLEFXP2.decimalDigitsOfOuput))
                            if hasattr(self.MainPanel, "lLEFXP3"):
                                self.MainPanel.lLEFXP3.edit.SetValue(round(x_start+d1_new, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))
                            
                    elif objControl.Name == "PAR_11": # D2
                        d2_new = float(re.match(r"(-?\d+(?:\.\d+)?)", event.String).group(1))
                        if self.MainPanel.rbDirXPlus.Value == True: # X
                            if hasattr(self.MainPanel, "lLEFYP2"):
                                self.MainPanel.lLEFYP2.edit.SetValue(round(y_start+d2_new, self.MainPanel.lLEFYP2.decimalDigitsOfOuput))
                            if hasattr(self.MainPanel, "lLEFYP3"):
                                self.MainPanel.lLEFYP3.edit.SetValue(round(y_start+d2_new, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))
                        else: # Y
                            if hasattr(self.MainPanel, "lLEFYP2"):
                                self.MainPanel.lLEFYP2.edit.SetValue(round(y_start-d2_new/2, self.MainPanel.lLEFYP2.decimalDigitsOfOuput))
                            if hasattr(self.MainPanel, "lLEFYP3"):
                                self.MainPanel.lLEFYP3.edit.SetValue(round(y_start+d2_new/2, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))
                    
                    elif objControl.Name in ["PAR_1","PAR_2"]: # X Start or Y Start
                        if hasattr(self.MainPanel, "cbDistReset"):
                            if self.MainPanel.cbDistReset.Value == True:
                                if hasattr(self.MainPanel, "lLEFXP2"):
                                    self.MainPanel.lLEFXP2.edit.SetValue(0)
                                if hasattr(self.MainPanel, "lLEFYP2"):
                                    self.MainPanel.lLEFYP2.edit.SetValue(0)
                                if hasattr(self.MainPanel, "lLEFXP3"):
                                    self.MainPanel.lLEFXP3.edit.SetValue(0)
                                if hasattr(self.MainPanel, "lLEFYP3"):
                                    self.MainPanel.lLEFYP3.edit.SetValue(0)
                                if hasattr(self.MainPanel, "rlefApprXY"):
                                    self.MainPanel.rlefApprXY.llef1.edit.SetValue(0)
                                    self.MainPanel.rlefApprXY.llef2.edit.SetValue(0)
                            else:
                                d1 = self.MainPanel.rlefApprXY.llef1.edit.GetValue() or 0.0
                                d2 = self.MainPanel.rlefApprXY.llef2.edit.GetValue() or 0.0
                                if self.MainPanel.rbDirXPlus.Value == True:
                                    if hasattr(self.MainPanel, "lLEFXP2"):
                                        self.MainPanel.lLEFXP2.edit.SetValue(round(-(d1/2)+x_start, self.MainPanel.lLEFXP2.decimalDigitsOfOuput))
                                    if hasattr(self.MainPanel, "lLEFYP2"):
                                        self.MainPanel.lLEFYP2.edit.SetValue(round(d2+y_start, self.MainPanel.lLEFYP2.decimalDigitsOfOuput))
                                    if hasattr(self.MainPanel, "lLEFXP3"):
                                        self.MainPanel.lLEFXP3.edit.SetValue(round(d1/2+x_start, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))
                                    if hasattr(self.MainPanel, "lLEFYP3"):
                                        self.MainPanel.lLEFYP3.edit.SetValue(round(d2+y_start, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))                            
                                else:
                                    if hasattr(self.MainPanel, "lLEFXP2"):
                                        self.MainPanel.lLEFXP2.edit.SetValue(round(d1+x_start, self.MainPanel.lLEFXP2.decimalDigitsOfOuput))
                                    if hasattr(self.MainPanel, "lLEFYP2"):
                                        self.MainPanel.lLEFYP2.edit.SetValue(round(-(d2/2)+y_start, self.MainPanel.lLEFYP2.decimalDigitsOfOuput))
                                    if hasattr(self.MainPanel, "lLEFXP3"):
                                        self.MainPanel.lLEFXP3.edit.SetValue(round(d1+x_start, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))
                                    if hasattr(self.MainPanel, "lLEFYP3"):
                                        self.MainPanel.lLEFYP3.edit.SetValue(round(d2/2+y_start, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))
                                                                       
                # Special Case for EXC      
                elif self.strMType in ["EXC"]:
                    # X Start or Y Start
                    if objControl.Name in ["PAR_1","PAR_2"]:
                        self.fromStart = True
                        if objControl.Name == "PAR_1":
                            x_new = float(re.match(r"(-?\d+(?:\.\d+)?)", event.String).group(1))
                            y_new = self.MainPanel.lLEFYStart.edit.GetValue() or 0.0
                        else:
                            x_new = self.MainPanel.lLEFXStart.edit.GetValue() or 0.0
                            y_new = float(re.match(r"(-?\d+(?:\.\d+)?)", event.String).group(1))
                        x_center = self.MainPanel.lLEFXP2.edit.GetValue() or 0.0
                        y_center = self.MainPanel.lLEFYP2.edit.GetValue() or 0.0
                        x3_old = self.MainPanel.lLEFXP3.edit.GetValue() or 0.0
                        y3_old = self.MainPanel.lLEFYP3.edit.GetValue() or 0.0
                        self.r, x3_new, y3_new = self.update_p3(x_center, y_center, x_new, y_new, x3_old, y3_old)
                        if hasattr(self.MainPanel, "lLEFXP3"):
                            self.MainPanel.lLEFXP3.edit.SetValue(round(x3_new, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lLEFYP3"):
                            self.MainPanel.lLEFYP3.edit.SetValue(round(y3_new, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lefCircRad"):
                            self.MainPanel.lefCircRad.edit.SetValue(round(self.r, self.MainPanel.lefCircRad.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "WriteDistances"):
                            self.MainPanel.WriteDistances(x2=x_center, y2=y_center)
                        self.fromStart = False 
                    # X P2 or Y P2 (Circle Center)
                    elif objControl.Name in ["PAR_17","PAR_18"] and not self.fromIJ:
                        self.fromP2 = True
                        if objControl.Name == "PAR_17":
                            xc_new = float(re.match(r"(-?\d+(?:\.\d+)?)", event.String).group(1))
                            yc_new = self.MainPanel.lLEFXP2.edit.GetValue() or 0.0
                        else:
                            xc_new = self.MainPanel.lLEFXP2.edit.GetValue() or 0.0
                            yc_new = float(re.match(r"(-?\d+(?:\.\d+)?)", event.String).group(1))          
                        # Calculate new Start point and P3 based on newly selected Center Point P2
                        x_start = self.MainPanel.lLEFXStart.edit.GetValue() or 0.0
                        y_start = self.MainPanel.lLEFYStart.edit.GetValue() or 0.0
                        x3_old = self.MainPanel.lLEFXP3.edit.GetValue() or 0.0
                        y3_old = self.MainPanel.lLEFYP3.edit.GetValue() or 0.0
                        self.r, x3_new, y3_new = self.update_p3(xc_new, yc_new, x_start, y_start, x3_old, y3_old)
                        if hasattr(self.MainPanel, "lLEFXP3"):
                            self.MainPanel.lLEFXP3.edit.SetValue(round(x3_new, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lLEFYP3"):
                            self.MainPanel.lLEFYP3.edit.SetValue(round(y3_new, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "WriteDistances"):
                            self.MainPanel.WriteDistances(x2=xc_new, y2=yc_new)
                        self.fromP2 = False
                    # X P3 or Y P3 (End point)
                    elif objControl.Name in ["PAR_15","PAR_16"] and not any([self.fromP2, self.fromStart, self.fromP3, self.fromIJ]): 
                        # Only go in here if we are called from the actual P3 text fields and not from any other "SetValue()" call
                        self.fromP3 = True
                        if objControl.Name == "PAR_15":
                            x3_new = float(re.match(r"(-?\d+(?:\.\d+)?)", event.String).group(1))
                            y3_new = self.MainPanel.lLEFYP3.edit.GetValue() or 0.0
                        else:
                            x3_new = self.MainPanel.lLEFXP3.edit.GetValue() or 0.0
                            y3_new = float(re.match(r"(-?\d+(?:\.\d+)?)", event.String).group(1))          
                        # Very special case for EXC, here we project the End-Point to the theoretical circle
                        x1 = self.MainPanel.lLEFXStart.edit.GetValue() or 0.0
                        y1 = self.MainPanel.lLEFYStart.edit.GetValue() or 0.0
                        x2 = self.MainPanel.lLEFXP2.edit.GetValue() or 0.0
                        y2 = self.MainPanel.lLEFYP2.edit.GetValue() or 0.0
                        # Calculate measurement circle radius
                        self.r = round(self.radius_from_points(x1, y1, x2, y2), self.MainPanel.lLEFXP3.decimalDigitsOfOuput)
                        # Project End point to measurement circle
                        x3, y3 = self.project_point_to_circle(x2, y2, self.r, x3_new, y3_new)
                        # Get correct unit for the string ("mm" or "in")
                        x3dVal = self.sys.FromCADUnitstoUser(x3)
                        x3 = self.sys.FormatUserUnits(x3dVal, FORMAT.DISTANCE).getPyString()
                        y3dVal = self.sys.FromCADUnitstoUser(y3)
                        y3 = self.sys.FormatUserUnits(y3dVal, FORMAT.DISTANCE).getPyString()
                        if hasattr(self.MainPanel, "lLEFXP3"):
                            self.MainPanel.lLEFXP3.edit.ChangeValue(x3) # Have to use ChangeValue() here in order for EVT_TEXT not to get triggered!
                        if hasattr(self.MainPanel, "lLEFYP3"):
                            self.MainPanel.lLEFYP3.edit.ChangeValue(y3)
                        self.fromP3 = False
                    # I and J
                    elif objControl.Name in ["PAR_10","PAR_12"] and not self.fromP2:
                        self.fromIJ = True
                        if objControl.Name == "PAR_10":
                            i_new = float(re.match(r"(-?\d+(?:\.\d+)?)", event.String).group(1))
                            j_new = self.MainPanel.lefCycCenJ.edit.GetValue() or 0.0
                        else:
                            i_new = self.MainPanel.lefCycCenI.edit.GetValue() or 0.0
                            j_new = float(re.match(r"(-?\d+(?:\.\d+)?)", event.String).group(1))
                        x_start = self.MainPanel.lLEFXStart.edit.GetValue() or 0.0
                        y_start = self.MainPanel.lLEFYStart.edit.GetValue() or 0.0
                        x2_new = x_start + i_new
                        y2_new = y_start + j_new
                        x3_old = self.MainPanel.lLEFXP3.edit.GetValue() or 0.0
                        y3_old = self.MainPanel.lLEFYP3.edit.GetValue() or 0.0
                        self.r, x3_new, y3_new = self.update_p3(x2_new, y2_new, x_start, y_start, x3_old, y3_old)
                        if hasattr(self.MainPanel, "lLEFXP2"):
                            self.MainPanel.lLEFXP2.edit.SetValue(round(x2_new, self.MainPanel.lLEFXP2.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lLEFYP2"):
                            self.MainPanel.lLEFYP2.edit.SetValue(round(y2_new, self.MainPanel.lLEFYP2.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lLEFXP3"):
                            self.MainPanel.lLEFXP3.edit.SetValue(round(x3_new, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lLEFYP3"):
                            self.MainPanel.lLEFYP3.edit.SetValue(round(y3_new, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))
                        self.fromIJ = False
                
                # Re-generate the command output
                logger.info(LOG_TAG + " * OnLabeledEFTextCtrlChanged(), Regenerate the command output, the value of : %s widgets was changed" % objControl.GetName())
                self.regenerate_output(self.mType)
                 
                    
        return flValid
    
    
    def WritePickPosition(self, x, y, z):
        """
        This functions handles the writing of a position selection dialog result (x,y,z) to the matching labeled edit field.
        """
        global POINT_PICK
        global G92_PICK
        
        self.fromWritePickPosition = True
        
        if hasattr(self, "MainPanel"):          
            if POINT_PICK[0] == True:
                if hasattr(self.MainPanel, "lLEFXStart"):
                    if self.strMType == 'CRN':
                        x_old = self.MainPanel.lLEFXStart.edit.GetValue()
                    self.MainPanel.lLEFXStart.edit.SetValue(round(x, self.MainPanel.lLEFXStart.decimalDigitsOfOuput))
                if hasattr(self.MainPanel, "lLEFYStart"):
                    if self.strMType == 'CRN':
                        y_old = self.MainPanel.lLEFYStart.edit.GetValue()
                    self.MainPanel.lLEFYStart.edit.SetValue(round(y, self.MainPanel.lLEFYStart.decimalDigitsOfOuput))
                # If this Option exists, go in here...
                if hasattr(self.MainPanel, "rbDistKeep") and hasattr(self.MainPanel, "rbDistReset") and hasattr(self.MainPanel, "rbDistAdj"):
                    # ... and reset the distances on Start Point change
                    if self.MainPanel.rbDistReset.Value == True:
                        self.MainPanel.lefApprX.llef1.edit.SetValue(0)
                        self.MainPanel.lefApprY.llef1.edit.SetValue(0)
                    # ... and adjust the distances on Start Point change
                    elif self.MainPanel.rbDistAdj.Value == True:
                        d1_old = self.MainPanel.lefApprX.llef1.edit.GetValue()
                        d2_old = self.MainPanel.lefApprY.llef1.edit.GetValue()
                        self.MainPanel.lefApprX.llef1.edit.SetValue(round((x_old - x + d1_old), self.MainPanel.lefApprX.decimalDigitsOfOuput))                
                        self.MainPanel.lefApprY.llef1.edit.SetValue(round((y_old - y + d2_old), self.MainPanel.lefApprY.decimalDigitsOfOuput))
                        
                # If this Option exists, go in here... (only for PLM)
                if hasattr(self.MainPanel, "cbDistReset"):
                    if self.MainPanel.cbDistReset.Value == True:
                        if hasattr(self.MainPanel, "lLEFXP2"):
                            self.MainPanel.lLEFXP2.edit.SetValue(0)
                        if hasattr(self.MainPanel, "lLEFYP2"):
                            self.MainPanel.lLEFYP2.edit.SetValue(0)
                        if hasattr(self.MainPanel, "lLEFXP3"):
                            self.MainPanel.lLEFXP3.edit.SetValue(0)
                        if hasattr(self.MainPanel, "lLEFYP3"):
                            self.MainPanel.lLEFYP3.edit.SetValue(0)
                        if hasattr(self.MainPanel, "rlefApprXY"):
                            self.MainPanel.rlefApprXY.llef1.edit.SetValue(0)
                            self.MainPanel.rlefApprXY.llef2.edit.SetValue(0)
                    else:
                        d1 = self.MainPanel.rlefApprXY.llef1.edit.GetValue()
                        d2 = self.MainPanel.rlefApprXY.llef2.edit.GetValue()
                        if self.MainPanel.rbDirXPlus.Value == True:
                            if hasattr(self.MainPanel, "lLEFXP2"):
                                self.MainPanel.lLEFXP2.edit.SetValue(round(-(d1/2)+x, self.MainPanel.lLEFXP2.decimalDigitsOfOuput))
                            if hasattr(self.MainPanel, "lLEFYP2"):
                                self.MainPanel.lLEFYP2.edit.SetValue(round(d2+y, self.MainPanel.lLEFYP2.decimalDigitsOfOuput))
                            if hasattr(self.MainPanel, "lLEFXP3"):
                                self.MainPanel.lLEFXP3.edit.SetValue(round(d1/2+x, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))
                            if hasattr(self.MainPanel, "lLEFYP3"):
                                self.MainPanel.lLEFYP3.edit.SetValue(round(d2+y, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))                            
                        else:
                            if hasattr(self.MainPanel, "lLEFXP2"):
                                self.MainPanel.lLEFXP2.edit.SetValue(round(d1+x, self.MainPanel.lLEFXP2.decimalDigitsOfOuput))
                            if hasattr(self.MainPanel, "lLEFYP2"):
                                self.MainPanel.lLEFYP2.edit.SetValue(round(-(d2/2)+y, self.MainPanel.lLEFYP2.decimalDigitsOfOuput))
                            if hasattr(self.MainPanel, "lLEFXP3"):
                                self.MainPanel.lLEFXP3.edit.SetValue(round(d1+x, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))
                            if hasattr(self.MainPanel, "lLEFYP3"):
                                self.MainPanel.lLEFYP3.edit.SetValue(round(d2/2+y, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))
                                
                if self.strMType == 'EXC': # Start Point
                    x_center = self.MainPanel.lLEFXP2.edit.GetValue()
                    y_center = self.MainPanel.lLEFYP2.edit.GetValue()
                    x3_old = self.MainPanel.lLEFXP3.edit.GetValue()
                    y3_old = self.MainPanel.lLEFYP3.edit.GetValue()
                    self.r, x3_new, y3_new = self.update_p3(x_center, y_center, x, y, x3_old, y3_old)
                    if hasattr(self.MainPanel, "lLEFXP3"):
                        self.MainPanel.lLEFXP3.edit.SetValue(round(x3_new, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))
                    if hasattr(self.MainPanel, "lLEFYP3"):
                        self.MainPanel.lLEFYP3.edit.SetValue(round(y3_new, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))
                    if hasattr(self.MainPanel, "lefCircRad"):
                        self.MainPanel.lefCircRad.edit.SetValue(round(self.r, self.MainPanel.lefCircRad.decimalDigitsOfOuput))
                    if hasattr(self.MainPanel, "WriteDistances"):
                        self.MainPanel.WriteDistances(x2=x_center, y2=y_center)

                
            if self.strMType == 'PLM':
                if POINT_PICK[1] == True and POINT_PICK[2] == True:
                    x_start = self.MainPanel.lLEFXStart.edit.GetValue()
                    y_start = self.MainPanel.lLEFYStart.edit.GetValue()
                    d1 = x-x_start
                    d2 = y-y_start
                    if self.MainPanel.rbDirXPlus.Value == True:             
                        if hasattr(self.MainPanel, "lLEFXP2"):
                            self.MainPanel.lLEFXP2.edit.SetValue(round(x_start+d1, self.MainPanel.lLEFXP2.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lLEFYP2"):
                            self.MainPanel.lLEFYP2.edit.SetValue(round(y_start+d2, self.MainPanel.lLEFYP2.decimalDigitsOfOuput))     
                        if hasattr(self.MainPanel, "lLEFXP3"):
                            self.MainPanel.lLEFXP3.edit.SetValue(round(x_start-d1, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lLEFYP3"):
                            self.MainPanel.lLEFYP3.edit.SetValue(round(y_start+d2, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))
                    else:
                        if hasattr(self.MainPanel, "lLEFXP2"):
                            self.MainPanel.lLEFXP2.edit.SetValue(round(x_start+d1, self.MainPanel.lLEFXP2.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lLEFYP2"):
                            self.MainPanel.lLEFYP2.edit.SetValue(round(y_start+d2, self.MainPanel.lLEFYP2.decimalDigitsOfOuput))     
                        if hasattr(self.MainPanel, "lLEFXP3"):
                            self.MainPanel.lLEFXP3.edit.SetValue(round(x_start+d1, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lLEFYP3"):
                            self.MainPanel.lLEFYP3.edit.SetValue(round(y_start-d2, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))

                    if hasattr(self.MainPanel, "WriteDistances"):
                        self.MainPanel.WriteDistances(x2=x, y3=y)
                        
            
            else:
                if POINT_PICK[1] == True: # Circle Center
                    if self.strMType == 'EXC':
                        if hasattr(self.MainPanel, "lLEFXP2"):
                            self.MainPanel.lLEFXP2.edit.SetValue(round(x, self.MainPanel.lLEFXP2.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lLEFYP2"):
                            self.MainPanel.lLEFYP2.edit.SetValue(round(y, self.MainPanel.lLEFYP2.decimalDigitsOfOuput))
                        # Calculate new Start point and P3 based on newly selected Center Point P2
                        x_start = self.MainPanel.lLEFXStart.edit.GetValue()
                        y_start = self.MainPanel.lLEFYStart.edit.GetValue()
                        x3_old = self.MainPanel.lLEFXP3.edit.GetValue()
                        y3_old = self.MainPanel.lLEFYP3.edit.GetValue()
                        self.r, x3_new, y3_new = self.update_p3(x, y, x_start, y_start, x3_old, y3_old)
                        if hasattr(self.MainPanel, "lLEFXP3"):
                            self.MainPanel.lLEFXP3.edit.SetValue(round(x3_new, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lLEFYP3"):
                            self.MainPanel.lLEFYP3.edit.SetValue(round(y3_new, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lefCircRad"):
                            self.MainPanel.lefCircRad.edit.SetValue(round(self.r, self.MainPanel.lefCircRad.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "WriteDistances"):
                            self.MainPanel.WriteDistances(x2=x, y2=y)
                    
                    else:
                        if hasattr(self.MainPanel, "lLEFXP2"):
                            self.MainPanel.lLEFXP2.edit.SetValue(round(x, self.MainPanel.lLEFXP2.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lLEFYP2"):
                            self.MainPanel.lLEFYP2.edit.SetValue(round(y, self.MainPanel.lLEFYP2.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "WriteDistances"):
                            self.MainPanel.WriteDistances(x2=x)
                        
                elif POINT_PICK[2] == True: # End point
                    if self.strMType == 'EXC': # Very special case for EXC, here we project the End-Point to the theoretical circle
                        x1 = self.MainPanel.lLEFXStart.edit.GetValue()
                        y1 = self.MainPanel.lLEFYStart.edit.GetValue()
                        x2 = self.MainPanel.lLEFXP2.edit.GetValue()
                        y2 = self.MainPanel.lLEFYP2.edit.GetValue()
                        # Calculate measurement circle radius
                        self.r = round(self.radius_from_points(x1, y1, x2, y2), self.MainPanel.lLEFXP3.decimalDigitsOfOuput)
                        # Project End point to measurement circle
                        x3, y3 = self.project_point_to_circle(x2, y2, self.r, x, y)
                        if hasattr(self.MainPanel, "lLEFXP3"):
                            self.MainPanel.lLEFXP3.edit.SetValue(round(x3, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lLEFYP3"):
                            self.MainPanel.lLEFYP3.edit.SetValue(round(y3, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))                 
                    else:
                        if hasattr(self.MainPanel, "lLEFXP3"):
                            self.MainPanel.lLEFXP3.edit.SetValue(round(x, self.MainPanel.lLEFXP3.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "lLEFYP3"):
                            self.MainPanel.lLEFYP3.edit.SetValue(round(y, self.MainPanel.lLEFYP3.decimalDigitsOfOuput))
                        if hasattr(self.MainPanel, "WriteDistances"):
                            self.MainPanel.WriteDistances(y3=y)
                        
            if G92_PICK:
                if hasattr(self.MainPanel, "lefG92"):
                    self.MainPanel.lefG92.llef1.edit.SetValue(round(x, self.MainPanel.lefG92.decimalDigitsOfOuput))
                    self.MainPanel.lefG92.llef2.edit.SetValue(round(y, self.MainPanel.lefG92.decimalDigitsOfOuput))
                    #self.MainPanel.lefG92.edit3.SetValue(round(z, self.MainPanel.lefG92.decimalDigitsOfOuput))
                    # If there is a position picked Enable both the edit fields and check boxes (if disabled before or not)
                    self.MainPanel.lefG92.llef1.edit.Enable()
                    self.MainPanel.lefG92.llef2.edit.Enable()
                    self.MainPanel.lefG92.llef1.cbCheck.SetValue(True)
                    self.MainPanel.lefG92.llef2.cbCheck.SetValue(True)
                    #pass
                
        # if not inPeps():     
        #     TransferDataFromWindow(self.MainPanel, self.tmpParams[self.strMType])
        #     self.SaveParamsToCplusplus()        # Update the measureObject
                 
        self.regenerate_output(self.mType)  
        # Reset global and guard Flags  
        self.fromWritePickPosition = False               
        POINT_PICK=[False, False, False]
        G92_PICK=False    
    
    ### Helper functions for measurement cycle EXC   
    def radius_from_points(self, x1, y1, x2, y2):
        '''
        Function for calculation of EXC Measure Circle Radius from Start Point (1) to Middle Point (2)
        '''    
        return round(math.hypot(x2 - x1, y2 - y1), 3)
       
    def project_point_to_circle(self, cx, cy, r, x, y):
        '''
        Function for EXC End-point P3 Projection to the measurement circle
        '''
        # Vector from center point
        vx = x - cx
        vy = y - cy            
        # Length of vector
        dist = math.hypot(vx, vy)        
        # if P3 was picked on the center point (dist=0)
        if dist == 0:
            # Set point to circle on positive x-axis
            return cx + r, cy   
        # normed vector
        nx = vx / dist
        ny = vy / dist   
        # point on circle
        px = cx + nx * r
        py = cy + ny * r
        
        return px, py      
    
    def update_p3(self, cx, cy, x1, y1, x3, y3):
        """
        This function updates Point 3 if the Start Point is changed and the center remains the same
        cx, cy = Center Point (unchanged)
        x1, y1 = new Start Point
        x3, y3 = old End Point (for angle definition)
        """    
        # New radius
        dx1 = x1 - cx
        dy1 = y1 - cy
        r_new = round(math.hypot(dx1, dy1), 3)
        # Check if P3 = Center, if yes no recalculation
        if abs(x3 - cx) < 1e-4 and abs(y3 - cy) < 1e-4:
            return r_new, x3, y3
        # Keep angle for Point 3
        angle_p3 = math.atan2(y3 - cy, x3 - cx)
        # Scale Point 3 to new radius
        x3_new = cx + r_new * math.cos(angle_p3)
        y3_new = cy + r_new * math.sin(angle_p3)
  
        return r_new, x3_new, y3_new
    ###

    ### Link to external functions ###
    @Methoddispatch
    def regenerate_output(self, Mtype): # @UnusedVariable
        pass

    @Methoddispatch
    def create_comment2(self, Mtype):  # @UnusedVariable
        return ""

    @Methoddispatch
    def create_comment3(self, Mtype):  # @UnusedVariable
        return ""

    @Methoddispatch
    def create_comment4(self, Mtype):  # @UnusedVariable
        return ""
    
    @regenerate_output.register(EDG)  # @UndefinedVariable
    @regenerate_output.register(MID)  # @UndefinedVariable
    @regenerate_output.register(CEN)  # @UndefinedVariable
    @regenerate_output.register(CRN)  # @UndefinedVariable
    @regenerate_output.register(EXM)  # @UndefinedVariable
    @regenerate_output.register(EXN)  # @UndefinedVariable
    @regenerate_output.register(EXC)  # @UndefinedVariable
    @regenerate_output.register(PAL)  # @UndefinedVariable
    @regenerate_output.register(CAL)  # @UndefinedVariable
    @regenerate_output.register(CEN3P)  # @UndefinedVariable
    @regenerate_output.register(PLM)  # @UndefinedVariable
    @regenerate_output.register(BAL)  # @UndefinedVariable
    def makino_regenerate_output(self, mtype):  # @UnusedVariable
        #super(MakinoMeasureCycleSubDialog, self).common_regerate_output(mtype)
        MakinoMeasureCycleSubDialog._common_regenerate_output(self,mtype)
       
    
    @create_comment2.register(EDG)  # @UndefinedVariable
    @create_comment2.register(MID)  # @UndefinedVariable
    @create_comment2.register(CEN)  # @UndefinedVariable
    @create_comment2.register(CRN)  # @UndefinedVariable
    @create_comment2.register(EXM)  # @UndefinedVariable
    @create_comment2.register(EXN)  # @UndefinedVariable
    @create_comment2.register(EXC)  # @UndefinedVariable
    @create_comment2.register(PAL)  # @UndefinedVariable
    @create_comment2.register(CAL)  # @UndefinedVariable
    @create_comment2.register(CEN3P)  # @UndefinedVariable
    @create_comment2.register(PLM)  # @UndefinedVariable
    @create_comment2.register(BAL)  # @UndefinedVariable
    def makino_create_comment2(self, mType):
        super(MakinoMeasureCycleSubDialog, self).common_create_comment2(mType)
    
    @create_comment3.register(EDG)  # @UndefinedVariable
    @create_comment3.register(MID)  # @UndefinedVariable
    @create_comment3.register(CEN)  # @UndefinedVariable
    @create_comment3.register(CRN)  # @UndefinedVariable
    @create_comment3.register(EXM)  # @UndefinedVariable
    @create_comment3.register(EXN)  # @UndefinedVariable
    @create_comment3.register(EXC)  # @UndefinedVariable
    @create_comment3.register(PAL)  # @UndefinedVariable
    @create_comment3.register(CAL)  # @UndefinedVariable
    @create_comment3.register(CEN3P)  # @UndefinedVariable
    @create_comment3.register(PLM)  # @UndefinedVariable
    @create_comment3.register(BAL)  # @UndefinedVariable
    def makino_create_comment3(self, mType):  # @UnusedVariable
        super(MakinoMeasureCycleSubDialog, self).common_create_comment3(mType)
    
    @create_comment4.register(EDG)  # @UndefinedVariable
    @create_comment4.register(MID)  # @UndefinedVariable
    @create_comment4.register(CEN)  # @UndefinedVariable
    @create_comment4.register(CRN)  # @UndefinedVariable
    @create_comment4.register(EXM)  # @UndefinedVariable
    @create_comment4.register(EXN)  # @UndefinedVariable
    @create_comment4.register(EXC)  # @UndefinedVariable
    @create_comment4.register(PAL)  # @UndefinedVariable
    @create_comment4.register(CAL)  # @UndefinedVariable
    @create_comment4.register(CEN3P)  # @UndefinedVariable
    @create_comment4.register(PLM)  # @UndefinedVariable
    @create_comment4.register(BAL)  # @UndefinedVariable
    def makino_create_comment4(self, mType):  # @UnusedVariable
        super(MakinoMeasureCycleSubDialog, self).common_create_comment4(mType)
    ### # ###
    
class ProfileDialog(object):
    """
    This class defines the Profile save and load dialog.
    """

    def LoadProfileFromSQLite(self):
        """
        This function depends on the version, please note the version number
        """
        pass
              
    def SaveProfileIntoSQLite(self):
        """
        This function depends on the version, please note the version number
        """
        pass

def TransferDataToWindow(root, postVar):
    """
    This functions transfers parameter data to the active window panel.
    """
    cadsys = cad.System() # @UnusedVariable
    # Write settings from postVar
    if root.Name in postVar:    # widget-name exists as key in postVar
        if isinstance(root, wx.Button) != True and root.Name.startswith("_") != True:
            valDict = postVar[root.Name]
            if root.__class__.__name__ in ['LabeledComboBox']:
                SetValue = getattr(root, "SetSelection", None)   # e.g. SetSelection for ComboBox
            else:
                SetValue = getattr(root, "SetValue", None)
            
            # Get functions
            SetValue = getattr(root, "SetValue", None)
            Enable   = getattr(root, "Enable", None)
            # Check if widget is enabled
            bEnable = valDict["widgets"] == '1' or valDict["widgets"] == 'true'

            if callable(SetValue):
                value = valDict["value"] if valDict["value"] != 'None' else None
                # If the widget is disabled
                if bEnable == False:
                    # Don't set any value, this leaves the edit field empty
                    pass
                else:
                    # If the root has an edit field set the saved values
                    if hasattr(root,"edit"):
                        if root.edit.behaviour==33:#in place for future use when DEFAUL-XML is changed to BASE UNITS
                            #value=cadsys.fromMMToCAD(float(value))
                            SetValue(value)
                        else:
                            SetValue(value) 
                    # If the root is an OptiRadioButton it only accepts Boolean "True" or "False" in SetValue()                    
                    elif root.__class__.__name__ in ['OptiRadioButton']:
                        value = True if value == "1" else False 
                        SetValue(value)                     
                    else:
                        SetValue(value)
                # valDict["name"] = ""
                # valDict["comment"] = root.Name
                logger.info("%s\t_transfer to : %s\tValue=%s %s" % (root.__class__.__name__, root.Name, str(postVar[root.Name]), type(postVar[root.Name])))
                
            # Enable or disable widgets
            if callable(Enable):
                Enable(bEnable)
            if hasattr(root, "cbCheck"):
                root.cbCheck.SetValue(bEnable)# and value != str(NOT_SET))
                #root.cbCheck.Enable(bEnable)
            if hasattr(root, "lbl"):
                root.lbl.Enable(bEnable)# and value != str(NOT_SET))
            if hasattr(root, "edit"):
                root.edit.Enable(bEnable)# and value != str(NOT_SET))
            if hasattr(root, "cb"):
                root.cb.Enable(bEnable)# and value != str(NOT_SET))
            if hasattr(root, "PrevValue"):
                delattr(root, "PrevValue")
                
    # Loop this function for every widget
    for child in root.GetChildren():
        if not TransferDataToWindow(child, postVar):
            return False

    return True


def TransferDataFromWindow(root, postVar):
    """
    This functions transfers parameter data from the active window panel to the postVars.
    """
    # Read settings into postVar
    if root.Name in postVar:    # widget-name exists as key in postVar
        if isinstance(root, wx.Button) != True and root.Name.startswith("_") != True:
            #valDict = postVar[root.Name]
            if root.__class__.__name__ in ['LabeledComboBox']:
                GetValue = getattr(root, "GetSelection", None)   # e.g. GetSelection for ComboBox
            else:
                GetValue = getattr(root, "GetValue", None)
                
            # Default enabled
            widgets = "1"
            
            if callable(GetValue):
                # Set widget to disabled if check box is unchecked
                if hasattr(root, "cbCheck") and not root.cbCheck.IsChecked():
                    #value = str(NOT_SET)
                    widgets = "0"
                # Set widget to disabled if the edit field is disabled (and there is no check box)
                if hasattr(root, "edit") and root.edit.Enabled == False:
                    #value = str(NOT_SET)
                    widgets = "0"
                    
                value = GetValue()
                if value is None:
                    value = "0"
                elif type(value) is bool:
                    value = "1" if value is True else "0"
                else:
                    value = value.__str__()
                    
                # Save data to postVars            
                #postVar[root.Name] = valDict
                #postVar[root.Name]["name"]
                #postVar[root.Name]["comment"]
                postVar[root.Name]["value"] = value
                postVar[root.Name]["widgets"] = widgets
                logger.info("%s\t_transfer from : %s\tValue=%s %s" % (root.__class__.__name__, root.Name, str(postVar[root.Name]), type(postVar[root.Name])))
                
    # Loop this function for every widget
    for child in root.GetChildren():
        if not TransferDataFromWindow(child, postVar):
            return False

    return True


def MeasureCycleString(measureObject, cycleCode=""):
    """
    This functions defines the measurement cycle NC code string.
    """
    
    return CreateMeasureCycleString(measureObject=measureObject)
    


def CreateMeasureCycleString(measureObject=None,measureString=None,measurePreview=None, MeasureType=None, MainPanel=None):
    """
    This functions creates the measurement cycle NC code string to be used in preview and post processor.
    """
    
    def _GetFunction(func, enm, typ, prefixOfParam="", OutputUnit=False):
        """
        This function gets and returns the values saved inside the C++ parameters or Python wx.Widgets.
        """
        # For PP run we only write out the values of the enabled widgets
        if func != "":
            enabled = measureObject.GetParam_Enabled(enm)
        else:
            enabled = True
            
        if MainOptions.get('outputUnits') == 'inch':
            toOU = cad.toINCH        
        else:
            toOU = cad.toMM
        
        if inPeps() or measurePreview:
            vValue=enm
        else:
            vValue = func(enm)
        
        if vValue != None and enabled: # For some reason sometimes the value is None... but the same value will then not be None right after that.
        
            if vValue == str(NOT_SET) or vValue == NOT_SET:
                return ""
        
            if typ == int:           
                return prefixOfParam+str(int(vValue))
                
            if vValue=="":
                return ""
                
            if typ == bool:
                vValue = "1" if vValue == True or vValue=="1" else "0"
                return prefixOfParam+vValue
                         
            if typ == float:
                if OutputUnit:
                    num=toOU(float(vValue))
                    return prefixOfParam+'{:.4f}'.format(num)
                else:
                    num=float(vValue)
                    return prefixOfParam+'{:.4f}'.format(num)
                
            else:
                if OutputUnit:
                    return  prefixOfParam+str(toOU(float(vValue)))
                else:
                    return  prefixOfParam+str(float(vValue))
                
        else:          
            return "" 
            
    def BuildGString(*args):
        """
        This functions build the NC Code string for the measurement cycle. (It always starts with "G")
        """
        # Build the "G String" for Makino NC-Code
        new_list=[]
        GString=""
        
        # Get list with valid arguments
        for ele in args:
            if ele !="" and ele != "-32768" and ele != "-32768.0000":
                new_list.append(ele)
                
        # Build G-Code String     
        for i,arg in enumerate(new_list):
            if i==0: # Space after first element, if needed
                GString += arg + " "                
            elif arg != "" and not arg.isalpha(): #and i != len(new_list)-1: # Space between variables which are not a character and the last one               
                if '.' in arg: # Check if the argument is a "float" and thus contains a '.'
                    # Split into prefix (part that is not a number) and rest (number). Prefix can also be empty "".
                    match = re.match(r"^([^\d]*)([\d.]+)$", arg)
                    if match:
                        prefix, number = match.groups()
                        try: # If we have a '.' in number, strip excess '0' and only leave the '.', e.g. "1.0000" --> "1."
                            f = float(number)
                            number = (f"{int(f)}." if f.is_integer() else str(f).rstrip('0').rstrip('.'))
                            # Put prefix and adjusted number back together
                            arg = prefix + number                        
                        except ValueError: # exception if value is not a float or integer but something like "A." ... The just keep it as such          
                            pass              
                GString += arg + " "             
            else: # alphabetical character
                GString += arg

        return GString               
    
    ################ Getting current output units ######################
    if MainOptions.get('outputUnits') == 'inch':
        toOU = cad.toINCH # @UnusedVariable     
    else:
        toOU = cad.toMM # @UnusedVariable
    ####################################################################
    #outVar = toOU(1.0)
    strOutput=""
    
    if measureObject is not None and measureString is None: # Coming from OPTICAM PP (NC file generation)
        
        enum = measureObject.GetType()
        MeasureType=str(enum).replace('eMEASURETYPE_', '')
             
        dStartX=_GetFunction(measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointX, float, OutputUnit = True)#Start Point X
        dStartY=_GetFunction(measureObject.GetParam_Double, cad.eMEASUREPARAM_dStartPointY, float, OutputUnit = True)#Start Point Y
        bThreadWire=_GetFunction(measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bTE, bool, OutputUnit = False)#Thread Wire
        bCutWire=_GetFunction(measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bCutWireAfter, bool, OutputUnit = False)#Cut Wire
        if MeasureType not in ['CEN', 'CRN']: # No direction in this types
            bCycDir=_GetFunction(measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bFinalMove, bool, OutputUnit = False)#Cycle Direction
        dTouchAng=_GetFunction(measureObject.GetParam_Double, cad.eMEASUREPARAM_dTouchAngle, float, prefixOfParam="A", OutputUnit = False)#Touching Angle
        dApprX=_GetFunction(measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DX, float, prefixOfParam="X",OutputUnit = True)#Approach Distance X
        dApprY=_GetFunction(measureObject.GetParam_Double, cad.eMEASUREPARAM_dDistance_DY, float, prefixOfParam="Y",OutputUnit = True)#Approach Distance Y
        if MeasureType == 'EXC':
            dCycCenX=_GetFunction(measureObject.GetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float, prefixOfParam="I",OutputUnit = True)#Position of the measurement cycle from Start Point X
            dCycCenY=_GetFunction(measureObject.GetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float, prefixOfParam="J",OutputUnit = True)#Position of the measurement cycle from Start Point Y
        else:
            dFastAdvX=_GetFunction(measureObject.GetParam_Double, cad.eMEASUREPARAM_dXAxisTravel, float, prefixOfParam="I",OutputUnit = True)#Fast Advance I (X-axis)  
            dFastAdvY=_GetFunction(measureObject.GetParam_Double, cad.eMEASUREPARAM_dYAxisTravel, float, prefixOfParam="J",OutputUnit = True)#Fast Advance J (Y-axis)  
        if MeasureType == 'EXC':
            dEndX=_GetFunction(measureObject.GetParam_Double, cad.eMEASUREPARAM_dThirdPointX, float, prefixOfParam="X",OutputUnit = True)#Measure Circle End Point X
            dEndY=_GetFunction(measureObject.GetParam_Double, cad.eMEASUREPARAM_dThirdPointY, float, prefixOfParam="Y",OutputUnit = True)#Measure Circle End Point Y
            bCylHole=_GetFunction(measureObject.GetParam_Bool,   cad.eMEASUREPARAM_bDontZeroXYCorrection, bool, OutputUnit = False)#Cylindrical Hole
            #iCircRad=_GetFunction(measureObject.GetParam_Double, cad.eMEASUREPARAM_dSphericalRadius, float, prefixOfParam="R",OutputUnit = True)#Measure Circle Radius R
        if MeasureType == 'CRN':    
            iWorkpInc=_GetFunction(measureObject.GetParam_Int, cad.eMEASUREPARAM_iMeasureSide, int, prefixOfParam="A",OutputUnit = False)#Parameter where measured angle is saved
        if MeasureType == 'PAL': 
            iMeasdAng=_GetFunction(measureObject.GetParam_Int, cad.eMEASUREPARAM_iMeasureSide, int, prefixOfParam="A",OutputUnit = False)#Parameter where measured angle is saved
            iMovAmt=_GetFunction(measureObject.GetParam_Int, cad.eMEASUREPARAM_iMeasurementPoints, int, prefixOfParam="R",OutputUnit = False)#Amount of travel Movement 
        dG92X=_GetFunction(measureObject.GetParam_Double, cad.eMEASUREPARAM_dXMomentary, float, OutputUnit = True)#G92 X
        dG92Y=_GetFunction(measureObject.GetParam_Double, cad.eMEASUREPARAM_dYMomentary, float, OutputUnit = True)#G92 Y         
       
    if measureString is not None: # Coming from PEPS PP
        
        s3 = measureString[74:].strip()
        if '\'' in s3 or '\"' in s3:
            P2CMessageBox("Illegal quotes in measure string!")
            return ""
        param = s3.split()[1:]  # get list of parameter list
        MeasureType = GetMeasureCycleTypeString(int(param[0]))
               
        dStartX=_GetFunction("", param[1], float, OutputUnit = True)#Start Point X
        dStartY=_GetFunction("", param[2], float, OutputUnit = True)#Start Point Y
        bThreadWire=_GetFunction("", param[3], bool, OutputUnit = False)#Thread Wire before Measure
        bCutWire=_GetFunction("", param[4], bool, OutputUnit = False)#Cut Wire after measure
        if MeasureType not in ['CEN', 'CRN']: # No direction in this types
            bCycDir=_GetFunction("", param[5], bool, OutputUnit = False)#cycle direction
        dG92X=_GetFunction("", param[6], float, OutputUnit = True)#G92 X
        dG92Y=_GetFunction("", param[7], float, OutputUnit = True)#G92 Y
        dTouchAng=_GetFunction("", param[8], float, prefixOfParam='A', OutputUnit = False)#Touching Angle
        dApprX=_GetFunction("", param[9], float, prefixOfParam='X', OutputUnit = True)#Approach Distance X
        dApprY=_GetFunction("", param[11], float, prefixOfParam='Y', OutputUnit = True)#Approach Distance Y
        if MeasureType == 'EXC':
            dCycCenX=_GetFunction("", param[10], float, prefixOfParam='I', OutputUnit = True)#Position of the measurement cycle from Start Point X
            dCycCenY=_GetFunction("", param[12], float, prefixOfParam='J', OutputUnit = True)#Position of the measurement cycle from Start Point Y     
        else:
            dFastAdvX=_GetFunction("", param[10], float, prefixOfParam='I', OutputUnit = True)#Fast Advance I (X-axis)
            dFastAdvY=_GetFunction("", param[12], float, prefixOfParam='J', OutputUnit = True)#Fast Advance J (Y-axis)
        if MeasureType == 'CRN':
            iWorkpInc=_GetFunction("", param[13], int, prefixOfParam='A', OutputUnit = False)#Work piece inclination
        elif MeasureType == 'PAL':
            iMeasdAng=_GetFunction("", param[13], int, prefixOfParam='A', OutputUnit = False)#Measured Angle
            iMovAmt=_GetFunction("", param[14], int, prefixOfParam='R', OutputUnit = False)#Amount of travel Movement  
        # For Cylindrical center only, this is the position of the "End-Point" and the Radius of the measurement circle
        if MeasureType == 'EXC':
            dEndX=_GetFunction("", param[15], float, prefixOfParam='X', OutputUnit = True)#End Point X
            dEndY=_GetFunction("", param[16], float, prefixOfParam='X', OutputUnit = True)#End Point Y
            #iCircRad=_GetFunction("", param[19], float, prefixOfParam='R', OutputUnit = True)#Measure Circle Radius R
            bCylHole=_GetFunction("", param[20], bool, OutputUnit = False)#Cylindrical Hole

    if measurePreview is not None: # Coming from OPTICAM/PEPS Sub Dialog Preview
            
        if hasattr(MainPanel, "lLEFXStart"): # X Coordinate for pre-position
            dStartX=_GetFunction("", MainPanel.lLEFXStart.edit.GetValue(), float, OutputUnit = True)           
        if hasattr(MainPanel, "lLEFYStart"): # Y Coordinate for pre-position
            dStartY=_GetFunction("", MainPanel.lLEFYStart.edit.GetValue(), float, OutputUnit = True)
        # Positioning Axis Approach Value
        if MeasureType == 'CRN':
            if hasattr(MainPanel, "lefApprX"):
                dApprX=_GetFunction("", MainPanel.lefApprX.llef1.edit.GetValue(), float, prefixOfParam="X", OutputUnit = True)
            if hasattr(MainPanel, "lefApprY"):
                dApprY=_GetFunction("", MainPanel.lefApprY.llef1.edit.GetValue(), float, prefixOfParam="Y", OutputUnit = True)
        elif MeasureType == 'PLM':
            if hasattr(MainPanel, "rlefApprXY"):
                dApprX=_GetFunction("", MainPanel.rlefApprXY.llef1.edit.GetValue(), float, prefixOfParam="X", OutputUnit = True)
                dApprY=_GetFunction("", MainPanel.rlefApprXY.llef2.edit.GetValue(), float, prefixOfParam="Y", OutputUnit = True)        
        else:
            if hasattr(MainPanel, "lefApprX"):
                dApprX=_GetFunction("", MainPanel.lefApprX.edit.GetValue(), float, prefixOfParam="X", OutputUnit = True)
            if hasattr(MainPanel, "lefApprY"):
                dApprY=_GetFunction("", MainPanel.lefApprY.edit.GetValue(), float, prefixOfParam="Y", OutputUnit = True)
        # For Cylindrical center only, this is the position of the "End-Point"
        if MeasureType == 'EXC':
            if hasattr(MainPanel, "lLEFXP3"):
                dEndX=_GetFunction("", MainPanel.lLEFXP3.edit.GetValue(), float, prefixOfParam="X", OutputUnit = True)
            if hasattr(MainPanel, "lLEFYP3"):
                dEndY=_GetFunction("", MainPanel.lLEFYP3.edit.GetValue(), float, prefixOfParam="Y", OutputUnit = True)
        # A - Positioning Angle or Measured Angle (for PAL)
        if hasattr(MainPanel, "lefPosAng"):
            dTouchAng=_GetFunction("", MainPanel.lefPosAng.edit.GetValue(), float, prefixOfParam="A", OutputUnit = False)
        if hasattr(MainPanel, "lefMeasdAng"):
            iMeasdAng=_GetFunction("", MainPanel.lefMeasdAng.edit.GetValue(), int, prefixOfParam="A", OutputUnit = False)
        if hasattr(MainPanel, "lefWorkpInc"):
            iWorkpInc=_GetFunction("", MainPanel.lefWorkpInc.edit.GetValue(), int, prefixOfParam="A", OutputUnit = False)
        # I - Fast Advance I (X-axis) | For Cylindrical center EXC, this is the X position of the measurement cycle from Start Point
        if MeasureType == 'EXC':
            if hasattr(MainPanel, "lefCycCenI"):
                dCycCenX=_GetFunction("", MainPanel.lefCycCenI.edit.GetValue(), float, prefixOfParam="I", OutputUnit = True)
        else:         
            if hasattr(MainPanel, "lefFastAdvI"):
                dFastAdvX=_GetFunction("", MainPanel.lefFastAdvI.edit.GetValue(), float, prefixOfParam="I", OutputUnit = True)
        # J - Fast Advance J (Y-axis) | For Cylindrical center EXC, this is the > position of the measurement cycle from Start Point
        if MeasureType == 'EXC':
            if hasattr(MainPanel, "lefCycCenJ"):
                dCycCenY=_GetFunction("", MainPanel.lefCycCenJ.edit.GetValue(), float, prefixOfParam="J", OutputUnit = True)
        else:
            if hasattr(MainPanel, "lefFastAdvJ"):
                dFastAdvY=_GetFunction("", MainPanel.lefFastAdvJ.edit.GetValue(), float, prefixOfParam="J", OutputUnit = True)
        # R - Number of travel movements for work piece parallelism
        if hasattr(MainPanel, "lefMovAmt"):
            iMovAmt=_GetFunction("", MainPanel.lefMovAmt.edit.GetValue(), int, prefixOfParam="R", OutputUnit = False)
        # R - Measurement Circle Radius (EXC)
        # if hasattr(MainPanel, "lefCircRad"):
        #     iCircRad=_GetFunction("", MainPanel.lefCircRad.edit.GetValue(), float, prefixOfParam="R", OutputUnit = True)          
        # G92
        if hasattr(MainPanel, "lefG92"): 
            dG92X=_GetFunction("", MainPanel.lefG92.llef1.edit.GetValue(), float, OutputUnit = True)# X
            dG92Y=_GetFunction("", MainPanel.lefG92.llef2.edit.GetValue(), float, OutputUnit = True)# Y
                      
    # Build the preview string for NC Code status bar
    if measureObject is not None or measureString is not None or measurePreview is not None:
             
        # G Code for measurement/positioning
        GCode = ''
        
        if MeasureType == "EDG": # Edge Probing / Type 1
            GCode = 'G76'
            strOutput=BuildGString(GCode, dApprX, dApprY, dFastAdvX, dFastAdvY, dTouchAng)
     
        elif MeasureType == "CEN": # Center Hole / Type 2
            GCode = 'G77'
            strOutput=BuildGString(GCode, dApprX, dApprY, dFastAdvX, dFastAdvY, dTouchAng)
            
        elif MeasureType == "CRN": # Corner Edge / Type 3
            GCode = 'G79'
            strOutput=BuildGString(GCode, dApprX, dApprY, dFastAdvX, dFastAdvY, iWorkpInc)
            
        elif MeasureType == "MID": # Groove width center / Type 4
            GCode = 'G80'
            strOutput=BuildGString(GCode, dApprX, dApprY, dFastAdvX, dFastAdvY, dTouchAng)
            
        elif MeasureType == "PLM": # Plate width center / Type 5
            if hasattr(MainPanel, "rbDirXPlus") and hasattr(MainPanel, "rbDirYPlus"):
                if MainPanel.rbDirXPlus.Value == True:
                    GCode = 'G81'
                elif MainPanel.rbDirYPlus.Value == True:
                    GCode = 'G82'
            else:
                if bCycDir == "1":
                    GCode = 'G81'
                else:
                    GCode = 'G82'
            strOutput=BuildGString(GCode, dApprX, dApprY, dFastAdvX, dFastAdvY, dTouchAng)
            
        elif MeasureType == "EXC": # Cylinder (Hole) center / Type 6
            GCode = 'G83'
            if hasattr(MainPanel, "rbCW"): # Coming from python-panel
                if MainPanel.rbCW.Value == True:
                    if MainPanel.cbCylHole.Value == True:
                        CycDir = 'L12' # Clockwise/Hole
                    else:
                        CycDir = 'L02' # Clockwise
                else:
                    if MainPanel.cbCylHole.Value == True:
                        CycDir = 'L13' # Counter Clockwise/Hole
                    else:
                        CycDir = 'L03' # Counter Clockwise                    
            else: # Coming from PP or Main System
                if bCycDir == "1":
                    if bCylHole == "1":
                        CycDir = 'L12' # Clockwise/Hole
                    else:
                        CycDir = 'L02' # Clockwise 
                else:
                    if bCylHole == "1":
                        CycDir = 'L13' # Counter Clockwise/Hole
                    else:
                        CycDir = 'L03' # Counter Clockwise
            strOutput=BuildGString(GCode, CycDir, dEndX, dEndY, dCycCenX, dCycCenY)#, iCircRad)
            
        elif MeasureType == "PAL": # Work piece parallelism / Type 7
            if hasattr(MainPanel, "rbDirXPlus") and hasattr(MainPanel, "rbDirYPlus"):
                if MainPanel.rbDirXPlus.Value == True:
                    GCode = 'G84'
                elif MainPanel.rbDirYPlus.Value == True:
                    GCode = 'G85'
            else:
                if bCycDir == "1":
                    GCode = 'G84'
                else:
                    GCode = 'G85'
            strOutput=BuildGString(GCode, dApprX, dApprY, dFastAdvX, dFastAdvY, iMeasdAng, iMovAmt)
            
    # End here if we only change the preview in Sub-Panels               
    if measurePreview:
        return strOutput
    
    else: # Position probe/wire before measurement and cut/thread wire
        if bCutWire == "1":
            cutwireafter = "M07\n"
        else:
            cutwireafter = ""
            
        if bThreadWire == "1":
            threadwire = "M06\n"
        else:
            threadwire = ""
            
        cutwirebefore="" # @UnusedVariable
        
        # When moving to a defined/caught coordinate
        MOVstring = "G00 X{} Y{} \n".format(dStartX,dStartY)
            
        #G92
        if dG92X != "" and dG92Y != "":
            G92string = "G92 X{} Y{}".format(dG92X,dG92Y)
        elif dG92X != "" and dG92Y == "":
            G92string = "G92 X{}".format(dG92X)
        elif dG92X == "" and dG92Y != "":
            G92string = "G92 Y{}".format(dG92Y)
        else:
            G92string = ""
        # Needed because PEPS automatically puts newline before G92 ... and Opticam doesn't.   
        if inPeps():
            newLine = ""
        else:
            newLine = "\n"
        
        strOutput = MOVstring + threadwire + strOutput + "\n" + cutwireafter + newLine + G92string
        
        return strOutput
    
    
def GetMeasureCycleType(measureString=None):
    """
    This Function is intended for using in peps with a measureString which is holding all information -> here is only the type-string returned
    """
    if not measureString:   # this makes no sense
        logger.error("GetMeasureCycleType: got no measureString!")
        return ""

    s3 = measureString[74:].strip()   # '20401 1 -9.1 -9.1 0 1 0 2 2 1 -99.1 -99.1 -9.1 1 -99.1 -9.1 -9.1 -9.1 -9.1 -9.1 -9.1 -9.2 -9.2 -9.2 -9.2 -9.2 -9.2 -9.2 -9.2 2.82'
    if '\'' in s3 or '\"' in s3:
        P2CMessageBox("Illegal quotes in measure string!")
        return ""
    param = s3.split()[1:]  # get list of params list (2...29)
    
    # NimkeL/23.01.26: 
    # We need this "wrong" assignment in this Version because some Measure Types were switched...
    # Type 5 PLM --> EXN
    # ...and it would break OC serialization and PEPS Strings with already saved files if we change this on a higher level.
    if GetMeasureCycleTypeString(int(param[0])) == "PLM":
        return "EXN"
    else:
        return GetMeasureCycleTypeString(int(param[0]))

def GetMeasureCycleString(measureString=None, reset=False):
    """
    This Function is intended for using in peps with a measureString which is holding all information -> here is only the type-string returned
    """
    return CreateMeasureCycleString(measureString=measureString)
    
   
if __name__ == '__main__':
    StartMeasureCycleSub() # @UndefinedVariable
