# -*- coding: utf-8 -*-
import wx
import os, math, sys
import shutil
from types import MethodType
import p2cpython as opticam  # @UnresolvedImport
from p2cpython import getMessageW, PYTHON_MESSAGES, mm, toMM, BEHAVIOUR  # @UnresolvedImport
from p2cpython import getCurrentDoc  # @UnresolvedImport

from p2c.utils import logger, _DEBUG  # @UnresolvedImport
import p2c.iso as iso  # @UnresolvedImport
from p2c.window import BaseDialog, BasePanel, ScrolledBasePanel, EditField, LabeledEditField, DoubleLabeledEditField, LabeledComboBox, LabeledChoiceBox  # @UnresolvedImport
from p2c.window import LabeledComboBox2, NiceButton, OptiCheckBox, OptiRadioButton  # @UnresolvedImport
from p2c.window import DoubleLabeledComboBox, NormalButton, TextField, OptiRadioBox  # @UnresolvedImport
from p2c.window import SPACER, SMALLBORDER, BORDER, MEDIUMBORDER, BIGBORDER, OptiMultiCheckBox  # @UnresolvedImport
from p2c.window import getText, getToolTip, iconsDir, postPath, getOpticamIcon  # @UnresolvedImport
from p2c.window import BaseGroupPanel, OPEN_FILE_ICON, OPEN_FILE_DISABLED_ICON, StaticBox  # @UnresolvedImport
from p2c.window import ScreenScaleFactor    # @UnresolvedImport
from p2c.utils import GetUnlockedStartholePPs, GetHtmlConvertersList, GetRtfPageSizesListList, GetTechnologyDialogStyle  # @UnresolvedImport
from p2c.utils import get_record_entry_dict  # @UnresolvedImport    # read a record from 'machineoptions.xml' 
from p2c.utils import OpticamVariables # @UnresolvedImports @UnusedImport
from p2c.tdbutils import ChangeDBCommon  # @UnresolvedImport
from p2c.generalsettings import MainOptions, MainAddresses, SubsOptions, SubsAddresses, Models, ModelSettings, AddParamsDepend  # @UnresolvedImport # import only the necessary stuff 
from p2c.generalsettings import COMMON, XmlAddresses, ISOOptions, LastUsedProfiles, StartholePPList, pepsVar, SHPrettyNamesDict   # @UnresolvedImport # import only the necessary stuff 
from p2c.postvar import savePythonDictionaries, updateDictionaries, updateFromCommon    # @UnresolvedImport
from p2c.startholeposts import SetStartholePP # @UnresolvedImport @UnusedImport

TOLERANCE   = opticam.TOLERANCE()       # CAD Geometry resolution (FOR DISTANCES)
SMALL_ANGLE = opticam.SMALL_ANGLE()     # ... (FOR ANGLES)
SMALL_ANGLE_DEG = 0.0005    #math.degrees(SMALL_ANGLE)     # ... (FOR ANGLES IN DEGREES)
MAX_ANGLE_DEG = 60.                     # Restriction for angel imported from PEPS (Jimmy's suggestion 1.2.2011)

postVar = dict()        # A dictionary (c-map) is our container for all data of post-option dialog
                        # this dictionary will initialized in the __init__() of the specific PP's Post (startpost.py)
saveVar = dict()        # A dictionary (c-map) for storing original values of postVar (-> so we are able to store only differences)
postModel = None        # The current model
postProfile = None      # The current Profile
LOADSETTINGS = 0x1
LOADOPTIONS  = 0x2

SPACE = 5


__maintainer__  = [c for c in '$Author: mraks $' if c not in list("$")]
__url__ = 'http://www.camtek.de/'
__version__ = '0.3'
__revision__ = list(filter(str.isdigit, "$Revision: 16497 $"))
__status__ = 'Beta'
__date__ = '2016-1-17'
__updated__ = '2025-01-24'


#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Base Class for
# ...the common options window with all it's gui-components
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class BasePostOptionsDialog(BaseDialog):
    '''Represents the base-main-window for the PostOptions user-dialogs.'''     # can be accessed via __doc__
    def __init__(self, parent=None, title='Please set appropriate Name in the postVar dict', modal=False, hasPages="-1", statusbar=None, tabbed=False):

        # we provide here the default-name "PostOptionsDialog" -> C++ looks for this name to Activate this dialog!!!
        BaseDialog.__init__(self, parent, title, modal, name="PostOptionsDialog", statusbar=statusbar, iconShowSave=True, tabbed=tabbed)

        self.prog = self.doc.program            # current program
        if self.prog is None:
            raise ReferenceError('no program!')
        self.machine = self.doc.GetMachine()    # current machine
        if self.machine is None:
            raise ReferenceError('no machine!')
        self.machineName   = self.machine.Name.getPyString()
        self.machineNumber = self.machine.MachineNumber
        #
        # we have inherited a ...
        #   1. BasePanel - object (self.panel) which will be the parent for all components we will place
        #   2. Vertical BoxSizer (self.vbxV1 - the main sizer)
        #   3. Horizontal BoxSizer (self.vbxH1 - upper row for additional buttons)

        # set or delete variables as needed
        # because we are in the base-class this values exist in all derived classes
        #-----------------------------------------------------------------------------------------------------
        postVar['freezeMaxSize'] = False        # window size will be adapted when pages are opened/closed
        #-----------------------------------------------------------------------------------------------------
        #if postVar.get('ClassName', 'undefined') != self.__class__.__name__:
        if True:
            # the following entries represent a widget/control  (many widgets are only created when they are listed here)
            postVar['OutputUnitsMetric']        = (SubsOptions['outputUnits'] == 'mm') if 'outputUnits' in SubsOptions else None
            postVar['OutputUnitsInch']          = (SubsOptions['outputUnits'] != 'mm') if 'outputUnits' in SubsOptions else None
            postVar['AbsoluteCommandAbsolute']  = (SubsOptions['absolute']['Type'] == 'Absolute') if 'absolute' in SubsOptions else None
            postVar['AbsoluteCommandIncrement'] = (SubsOptions['absolute']['Type'] != 'Absolute') if 'absolute' in SubsOptions else None

            #StartholePP
            postVar['SelectedStartholePP']      = SubsOptions['SelectedStartholePP'] if 'SelectedStartholePP' in SubsOptions else None
#             postVar['SelectedStartholePPLIST']  = GetUnlockedStartholePPs(StartholePPList) #get all unlocked names from StartholePPList Dict : NOW DONE IN CreateControls() 

            # Machine
            postVar['BlockOutPutDoOutPut'] = SubsOptions['blockno'][3] if 'blockno' in SubsOptions else None
            postVar['BlockOutPutStart'] = SubsOptions['blockno'][0] if 'blockno' in SubsOptions else None
            postVar['BlockOutPutStep'] = SubsOptions['blockno'][1] if 'blockno' in SubsOptions else None
            postVar['BlockOutPutMax'] = SubsOptions['blockno'][2] if 'blockno' in SubsOptions else None
            postVar['decimalPoint'] = SubsOptions['decimalPoint'] if 'decimalPoint' in SubsOptions else None
            postVar['DigitsAfter'] = str(SubsOptions['digits']['Trail']) if 'digits' in SubsOptions else None
            postVar['DigitsAfterLIST'] = ['3', '4', '5', '6'] if postVar.get('OutputUnitsMetric') == True else ['4', '5', '6']

            postVar['OpenNCFile']    = SubsOptions['OpenNCFile'] if 'OpenNCFile' in SubsOptions else None
            postVar['ShowInExplorer'] = SubsOptions['ShowInExplorer'] if 'ShowInExplorer' in SubsOptions else None
            postVar['SetupSheet']    = SubsOptions['SetupSheet'] if 'SetupSheet' in SubsOptions else None
            postVar['SetupSheetCompact']    = SubsOptions['SetupSheetCompact'] if 'SetupSheetCompact' in SubsOptions else None
            postVar['SetupSheetExtraCompact'] = SubsOptions['SetupSheetExtraCompact'] if 'SetupSheetExtraCompact' in SubsOptions else False
            postVar['SetupSheet3D'] = SubsOptions['SetupSheet3D'] if 'SetupSheet3D' in SubsOptions else False
            
            postVar['StartHoleFile'] = SubsOptions['StartHoleFile'] if 'StartHoleFile' in SubsOptions else None
            postVar['OpenStartHoleFile'] = SubsOptions['OpenStartHoleFile'] if 'OpenStartHoleFile' in SubsOptions else None

            postVar['OutputComment'] = SubsOptions['OutputComment'] if 'OutputComment' in SubsOptions else False
            if self.hasTechComment():
                postVar['OutputTechComment'] = SubsOptions['OutputTechComment'] if 'OutputTechComment' in SubsOptions else False
            postVar['CommentsInHeader'] = SubsOptions['CommentsInHeader'] if 'CommentsInHeader' in SubsOptions else False
            #postVar['AutomaticThreading'] = True    # should always be set (but the widget is not shown anymore)
            postVar['AutomaticThreading'] = MainOptions['AutomaticThreading'] if 'AutomaticThreading' in MainOptions else None
            postVar['NoThreadingOutput'] = MainOptions['NoThreadingOutput'] if 'NoThreadingOutput' in MainOptions else None

            postVar['UpperNozzleTypeDefault'] = (self.machine.UpperNozzleType == 0)or (self.machine.UpperNozzleType == -1)
            postVar['UpperNozzleTypeSTL'] = (self.machine.UpperNozzleType == 1) 
            postVar['UpperNozzleSTLFile'] = self.machine.UpperNozzleFile.getPyString()
            #if postVar['UpperNozzleTypeDefault']:
            #    postVar['UpperNozzleSTLFile'] = 'DEFAULT'
            postVar['LowerNozzleTypeDefault'] = (self.machine.LowerNozzleType == 0) or (self.machine.LowerNozzleType == -1)
            postVar['LowerNozzleTypeSTL'] = (self.machine.LowerNozzleType == 1)
            postVar['LowerNozzleSTLFile'] = self.machine.LowerNozzleFile.getPyString()
            #if postVar['LowerNozzleTypeDefault']:
            #    postVar['LowerNozzleSTLFile'] = 'DEFAULT'
            if 'MODEL' in MainOptions:
                postVar['MODEL'] = MainOptions['MODEL']
                #Todo switch to c++ method, but this returns the wrong name at the moment always 'classic', propably default value
                #getCurrentDoc().GetCurrentModell().getPyString()                
                
            if 'PROFILE' in MainOptions:
                postVar['PROFILE'] = getCurrentDoc().GetMachine().GetProfileName().getPyString()
                #postVar['PROFILE'] = SubsOptions['PROFILE'] if 'PROFILE' in SubsOptions else 'DEFAULT' 

            postVar['IgnoreAdresses'] = SubsOptions['IgnoreAdresses'] if 'IgnoreAdresses' in SubsOptions else []
            postVar['MinimumMemory'] = SubsOptions['MinimumMemory'] if 'MinimumMemory' in SubsOptions else None
            if 'AdvancedTaper' in SubsOptions: postVar['AdvancedTaper'] = SubsOptions['AdvancedTaper']
            postVar['IsoForEachOrigin'] = SubsOptions['IsoForEachOrigin'] if 'IsoForEachOrigin' in SubsOptions else None
#            postVar['UseRotaryAxis'] = SubsOptions['UseRotaryAxis'] if 'UseRotaryAxis' in SubsOptions else False

            if 'ProgramName' in SubsOptions:
                postVar['ExtChars'] = SubsOptions['ProgramName'].get('ExtChars')
                postVar['ExtChars2'] = SubsOptions['ProgramName'].get('ExtChars2')
            else:
                postVar['ExtChars2'] = postVar['ExtChars'] = 'iso'
            #GroupPage3 Vars (Travellimits)
            postVar['Min_Max_Values'] = SubsOptions['Min_Max_Values'] if 'Min_Max_Values' in SubsOptions else True  # in meeting 17th. of May 2021 B. and M. decided we want the min/max method
            
            #GroupPage5 Vars
            postVar['radioBoxPicture'] = SubsOptions['radioBoxPicture'] if 'radioBoxPicture' in SubsOptions else None
            #postVar['radioBoxPictureLIST'] = [ u"Colour", u"Monochrome", u"No Graphics" ]
            postVar['backgroundColorWhite'] = SubsOptions['backgroundColorWhite'] if 'backgroundColorWhite' in SubsOptions else None
            postVar['choiceFile'] = SubsOptions['choiceFile'] if 'choiceFile' in SubsOptions else None
            #postVar['choiceFileLIST'] = GetHtmlConvertersList() if 'choiceFile' in SubsOptions else []
            postVar['pageSize'] = SubsOptions['pageSize'] if 'pageSize' in SubsOptions else None
            postVar['pageBorderLeftRight'] = SubsOptions['pageBorderLeftRight'] if 'pageBorderLeftRight' in SubsOptions else None
            postVar['PageBorderTopBottom'] = SubsOptions['PageBorderTopBottom'] if 'PageBorderTopBottom' in SubsOptions else None
            #postVar['pageSizeLIST'] = GetRtfPageSizesListList() if 'pageSizeLIST' in SubsOptions else []
            postVar['radioStandardReport'] = SubsOptions['radioStandardReport'] if 'radioStandardReport' in SubsOptions else None
            postVar['radioUserReport'] = SubsOptions['radioUserReport'] if 'radioUserReport' in SubsOptions else None
            postVar['editReportFile'] = SubsOptions['editReportFile'] if 'editReportFile' in SubsOptions else None
            postVar['btnOpenReportFile'] = SubsOptions['btnOpenReportFile'] if 'btnOpenReportFile' in SubsOptions else None
            #postVar['textReportPath'] = SubsOptions['textReportPath'] if 'textReportPath' in SubsOptions else None
            postVar['radioPortraitFormat'] = SubsOptions['radioPortraitFormat'] if 'radioPortraitFormat' in SubsOptions else None
            postVar['radioLandscapeFormat'] = SubsOptions['radioLandscapeFormat'] if 'radioLandscapeFormat' in SubsOptions else None
            postVar['editLogoFile'] = SubsOptions['editLogoFile'] if 'editLogoFile' in SubsOptions else None
            postVar['btnOpenLogoFile'] = SubsOptions['btnOpenLogoFile'] if 'btnOpenLogoFile' in SubsOptions else None
            #postVar['txtDescription'] = SubsOptions['txtDescription'] if 'txtDescription' in SubsOptions else None
            #postVar['txtValue'] = SubsOptions['txtValue'] if 'txtValue' in SubsOptions else None
            postVar['editDesc1'] = SubsOptions['editDesc1'] if 'editDesc1' in SubsOptions else None
            postVar['editVal1'] = SubsOptions['editVal1'] if 'editVal1' in SubsOptions else None
            postVar['editDesc2'] = SubsOptions['editDesc2'] if 'editDesc2' in SubsOptions else None
            postVar['editVal2'] = SubsOptions['editVal2'] if 'editVal2' in SubsOptions else None
            postVar['editDesc3'] = SubsOptions['editDesc3'] if 'editDesc3' in SubsOptions else None
            postVar['editVal3'] = SubsOptions['editVal3'] if 'editVal3' in SubsOptions else None
            postVar['OutputNcFileNameWithPath'] = SubsOptions['OutputNcFileNameWithPath'] if 'OutputNcFileNameWithPath' in SubsOptions else None 
            postVar['OutputNcFileNameWithOutPath'] = SubsOptions['OutputNcFileNameWithOutPath'] if 'OutputNcFileNameWithOutPath' in SubsOptions else None 
            postVar['OutputNcFileNameAndPath'] = SubsOptions['OutputNcFileNameAndPath'] if 'OutputNcFileNameAndPath' in SubsOptions else None 
            postVar['NCExtraFolder'] = SubsOptions['NCExtraFolder'] if 'NCExtraFolder' in SubsOptions else None 
            postVar['NCExtraFolderName'] = SubsOptions['NCExtraFolderName'] if 'NCExtraFolderName' in SubsOptions else None 
            postVar['SetupsheetExtraFolder'] = SubsOptions['SetupsheetExtraFolder'] if 'SetupsheetExtraFolder' in SubsOptions else None 
            postVar['SetupsheetExtraFolderName'] = SubsOptions['SetupsheetExtraFolderName'] if 'SetupsheetExtraFolderName' in SubsOptions else None 
            postVar['HideSolids'] = SubsOptions['HideSolids'] if 'HideSolids' in SubsOptions else None 
            postVar['ShowStartpoint'] = SubsOptions['ShowStartpoint'] if 'ShowStartpoint' in SubsOptions else None 
            postVar['WhiteBackground'] = SubsOptions['WhiteBackground'] if 'WhiteBackground' in SubsOptions else None 
            postVar['PrintAfterPp'] = SubsOptions['PrintAfterPp'] if 'PrintAfterPp' in SubsOptions else None 
            postVar['radioOutModeCut'] = SubsOptions['radioOutModeCut'] if 'radioOutModeCut' in SubsOptions else None
            postVar['radioOutModeFeature'] = SubsOptions['radioOutModeFeature'] if 'radioOutModeFeature' in SubsOptions else None
            postVar['setupSheetDigitsAfter'] = SubsOptions['setupSheetDigitsAfter'] if 'setupSheetDigitsAfter' in SubsOptions else '3'

            postVar['OutputUserDefinedHeader'] = SubsOptions['OutputUserDefinedHeader'] if 'OutputUserDefinedHeader' in SubsOptions else None
            postVar['UserDefinedHeaderField']  = SubsOptions['UserDefinedHeaderField'] if 'UserDefinedHeaderField' in SubsOptions else None
            postVar['OutputUserDefinedFooter'] = SubsOptions['OutputUserDefinedFooter'] if 'OutputUserDefinedFooter' in SubsOptions else None
            postVar['UserDefinedFooterField']  = SubsOptions['UserDefinedFooterField'] if 'UserDefinedFooterField' in SubsOptions else None
            
#             postVar['CanChangeOrigin'] = getCurrentDoc().GetMachine().isPossible_3DFeatureOrigin()      # (2020/11/24)
            #setupsheet template part
            #--------------------------------------------------------------------------
            #postVar['SetupSheetUseTemplate'] = SubsOptions['SetupSheetUseTemplate'] if 'SetupSheetUseTemplate' in SubsOptions else None
            #postVar['editSetupsheetTemplateFile'] = SubsOptions['editSetupsheetTemplateFile'] if 'editSetupsheetTemplateFile' in SubsOptions else ""
            #postVar['SetupSheetCompactUseTemplate'] = SubsOptions['SetupSheetCompactUseTemplate'] if 'SetupSheetCompactUseTemplate' in SubsOptions else None
            #postVar['editSetupsheetCompactTemplateFile'] = SubsOptions['editSetupsheetCompactTemplateFile'] if 'editSetupsheetCompactTemplateFile' in SubsOptions else ""
            
        #-------------------------------------- Server path (2022/01/21) -------------------------------------
        GetServerPath = getattr(opticam.BasePy(), 'GetServerPath', None)
        if GetServerPath and callable(GetServerPath):
            postVar['ServerPath'] = GetServerPath()
        else:
            postVar['ServerPath'] = ''
        #-------------------------------------- Class name ---------------------------------------------------
        # dialog class name
        postVar['ClassName'] = self.__class__.__name__

        #private class attribute 
        self.bIsOutputUnitMetric = False

    def hasTechComment(self):
        """
        Checks if there is a tech comment
        """        
        if get_record_entry_dict("CEVARS", "CE_COMMENT", "show", self.machine) == True:
            return True
        else:
            return False

    def Activate(self):
        #Set the Correct Setting, due to the current selection from C++
        #check the current unit from postVar
        self.bIsOutputUnitMetric = postVar.get('OutputUnitsMetric', True)
        
        curModel = getCurrentDoc().GetMachine().GetModelObject().Name
        #if curModel in ModelSettings and curModel != postVar.get('MODEL'):
        if curModel in ModelSettings:
            postVar['MODEL'] = curModel
            #
            #curProfile = self.machine.GetProfileName().getPyString() #Look for the saved profile name
            curProfile = postVar.get('PROFILE', self.machine.GetProfileName().getPyString())
            if curProfile not in ModelSettings[curModel]:
                curProfile = 'DEFAULT'
            postVar['PROFILELIST'] = list(ModelSettings[curModel].keys())
                 
            self.ProfileChange(curProfile, curModel)

        #super(self.__class__, self).Activate()
        BaseDialog.Activate(self)

    def ProfileChange(self, curProfile, curModel=None):
        if curModel is None:
            curModel = getCurrentDoc().GetMachine().GetModelObject().Name
        
        #Set Model/Profile Name as global variable
        global postModel, postProfile
        
        #Update DB Fields
        try:
            # first update the database info then transfer data to layout
            self.UpdateDatabaseFields(curProfile)
        except Exception:
            pass

        if curModel in ModelSettings:
            postModel = curModel
            if curProfile in ModelSettings[curModel]:
                postVar['PROFILE'] = postProfile = curProfile
                win = self.FindWindowByName('_GRP_PAGE1')
                if win:
                    TransferDataToWindow(win, postVar)   
                    win.enablePage()
                    win.Refresh()          
                win = self.FindWindowByName('_GRP_PAGE2')
                if win:            
                    TransferDataToWindow(win, postVar)   
                    win.enablePage()
                    win.Refresh()          
                    
                # (also update GroupPage 3 with the Travellimits)
                win = self.FindWindowByName('_GRP_PAGE3')
                if win:
                    tmpVar = {}   # a local (temp.) dictionary
                    GetTravelLimits(tmpVar)
                    TransferDataToWindow(win, tmpVar)
                    # win.enablePage()      # here is nothing to enable/disable
                    win.Refresh()
                    del(tmpVar)   
                win = self.FindWindowByName('_GRP_PAGE4')
                if win:
                    pass
                win = self.FindWindowByName('_GRP_PAGE5')
                if win:            
                    TransferDataToWindow(win, postVar)   
                    win.enablePage()
                    win.Refresh()          
                    
        
    def UpdateDatabaseFields(self, ProfileName=None):
        """
        Update the global dictionary postVar, the the function TransferDataToWindows will transfer 
        the value to the widget
        """
        pass

    def OnOK(self, event):
        self.SetWaitCursor()
        
        #Just to be sure, if new Profile was entered, dont discard changes
        GroupPage2Obj = self.FindWindowByName('_GRP_PAGE2')
        if GroupPage2Obj != None:
            GroupPage2Obj.OnButtonAddProfile(event)        

        # Important for the data transfer from the controls to the program:
        TransferDataFromWindow(self)

        # Data correction hook (atm. used by acfanuc, accut to correct the ncextension)
        self.HookForCorrections(postVar)

        # Update Models-Dictionary
        SetTravelLimits(postVar, postModel)

        # IMPORTANT: CALL BASE-CLASS METHOD
        BaseDialog.OnOK(self, event)

        # actualize Opticam C++ (toolpath must be recalculated when the settings are changed)
        #UpdatePostDicts(setModel=False)        
        UpdatePostDicts()               # give model-dependend information (travel-limits) every time to main system
        
        UpdatePostSettings()

        if 'SeperateNCFiles' in postVar:
            self.machine.setSeparateNCFiles(postVar['SeperateNCFiles'])
        else:
            #Just to be sure
            self.machine.setSeparateNCFiles(False)

        #if 'MODEL' in MainOptions:
        #    self.machine.ChangeModel(opticam.String(postVar['MODEL']))
        
        #Save the Profile Name
        ProfileChoiceObj = self.FindWindowByName('PROFILE')
        if ProfileChoiceObj != None:
            doc = getCurrentDoc()
            doc.GetMachine().SetProfileName(opticam.String(ProfileChoiceObj.GetValue()))  
            doc.SetSaveFlag(True) #Something in this doc has changed, please save before closing
            global postProfile
            postProfile = ProfileChoiceObj.GetValue()
            postVar['PROFILE'] = ProfileChoiceObj.GetValue()            

        #We have to switch to the correct Database always (affects Joergs C++ Load Tech dialog). At least to deactivate the demo database.
        try:
            self.ChangeDB()  
        finally:
            self.SetStandardCursor()

    def OnESC(self, event):
        self.SetWaitCursor()

        # IMPORTANT: CALL BASE-CLASS METHOD -> THERE'S THE PROGRAM EXIT
        BaseDialog.OnESC(self, event)

        # now discard all changes...
        global postModel
        postModel = postVar['MODEL']
        
        global postProfile
        postProfile = postVar['PROFILE']
        
        # Important for the data transfer from the controls to the program:
        TransferDataToWindow(self, postVar)

        win = self.FindWindowByName('_GRP_PAGE1')
        if win is not None:
            win.enablePage()
        win = self.FindWindowByName('_GRP_PAGE2')
        if win is not None:
            win.enablePage()
            #win.enableOnce()
        win = self.FindWindowByName('_GRP_PAGE3')
        if win is not None:
            win.enablePage()
        win = self.FindWindowByName('_GRP_PAGE4')
        if win is not None:
            win.enablePage()
        win = self.FindWindowByName('_GRP_PAGE5')
        if win is not None:
            win.enablePage()

        self.SetStandardCursor()

    def HookForCorrections(self, *args, **kwargs):
        """
        Data correction hook (atm. used by acfanuc, accut to correct the ncextension)
        """
        pass

#    def OnTranslate(self, event):
#        # Only call the base
#        BaseDialog.OnTranslate(self, event)

#    def OnDock(self, event):
#        # Only call the base
#        BaseDialog.OnDock(self, event)

#    def OnHelp(self, event):
#        # ...own stuff
#        BaseDialog.OnHelp(self, event)

    def OnSave(self, event):
        self.SetWaitCursor()
        
        #current Model
        global postModel
        postModel = getCurrentDoc().GetMachine().GetModelObject().Name
        
        #Just to be sure, if new Profile was entered, dont discard changes
        GroupPage2Obj = self.FindWindowByName('_GRP_PAGE2')
        if GroupPage2Obj != None:
            GroupPage2Obj.OnButtonAddProfile(event)

        # Important for the data transfer from the controls to the program:
        TransferDataFromWindow(self)

        # Update Models-Dictionary
        SetTravelLimits(postVar, postModel)

        if 'SeperateNCFiles' in postVar:
            self.machine.setSeparateNCFiles(postVar['SeperateNCFiles'])
        else:
            #Just to be sure
            self.machine.setSeparateNCFiles(False)

        #if 'MODEL' in MainOptions:
        #    self.machine.ChangeModel(opticam.String(postVar['MODEL']))
        
        #Save the Profile Name
        ProfileChoiceObj = self.FindWindowByName('PROFILE')
        if ProfileChoiceObj != None:
            doc = getCurrentDoc()
            doc.GetMachine().SetProfileName(opticam.String(ProfileChoiceObj.GetValue())) #set variabl value in document
            doc.SetSaveFlag(True) #Something in this doc has changed, please save before closing
            global postProfile
            postProfile = ProfileChoiceObj.GetValue()
            postVar['PROFILE'] = ProfileChoiceObj.GetValue()
            
            #global postModel  
            
        #We have to switch to the correct Database always (affects Joergs C++ Load Tech dialog). At least to deactivate the demo database.
        try:
            self.ChangeDB()  
        except AttributeError:
            pass
        finally:
            self.SetStandardCursor()

#        saveSettings(<post directory>)     # done in the derived class, because there we know the right path

    def CreateControls(self, child=None):
        logger.info("%s.%s" % ("BasePostOptionsDialog" , "CreateControls"))
        
        # Important for the data transfer mechanism:
        # get sh-licenses
        postVar['SelectedStartholePPLIST']  = GetUnlockedStartholePPs(StartholePPList) #get all unlocked names from StartholePPList Dict
        if postVar['SelectedStartholePP'] not in postVar['SelectedStartholePPLIST']:
            postVar['SelectedStartholePP'] = "standard"
        #
        # TESTING DONGLE REQUEST FOR TECH DIALOG FEATURE (we do this better in main-system)
        # this isn't used atm. but maybe in the future ?
        styleDB = GetTechnologyDialogStyle(self.machineNumber)      #check if machine like dialog-appearance is featured
        postVar['TechnologyDialogStyleDB']  = styleDB[0]
        postVar['TechnologyDialogStyleDB2'] = styleDB[1]

        postVar['choiceFileLIST'] = GetHtmlConvertersList() if 'choiceFile' in SubsOptions else []
        if postVar['choiceFile'] not in postVar['choiceFileLIST']:
            if len(postVar['choiceFileLIST']) > 0:
                postVar['choiceFile'] = postVar['choiceFileLIST'][0]
            else:
                postVar['choiceFile'] = ""

        # For .rtf file format we supply a page size widget
        if postVar['choiceFile'] in ['*.rtf', '.rtf', 'rtf', '*.RTF', '.RTF', 'RTF']:
            postVar['pageSizeLIST'] = GetRtfPageSizesListList() if 'pageSize' in SubsOptions else []
            if postVar['pageSize'] not in postVar['pageSizeLIST']:
                if len(postVar['pageSizeLIST']) > 0:
                    postVar['pageSize'] = postVar['pageSizeLIST'][0]
                else:
                    postVar['pageSize'] = ""

        TransferDataToWindow(self, postVar)

        # Setting the widget enabled/disabled state:
        win = self.FindWindowByName('_GRP_PAGE1')
        if win is not None:
            win.enablePage()
        win = self.FindWindowByName('_GRP_PAGE2')
        if win is not None:
            win.enablePage()
            win.enableOnce()
        win = self.FindWindowByName('_GRP_PAGE3')
        if win is not None:
            win.enablePage()
        win = self.FindWindowByName('_GRP_PAGE4')
        if win is not None:
            win.enablePage()
        win = self.FindWindowByName('_GRP_PAGE5')
        if win is not None:
            win.enablePage()
            win.enableOnce()

        # ...to be continued, if there are more pages one day
        BaseDialog.CreateControls(self, child)


    def ChangeDB(self):
        # NOTE: Zhichao.Wanng 01.07.2016, To better manage the change the database path using a single function to handle this job.
        # thus we can synchronize database info in mainly system (core) and python code. this method code be override,
        # but please keep the ChangeDBCommon in last line 
        techTable=postVar.get('TechTableField', '')
        wireTable = postVar.get('WireTechTableField', '')
        DBPath=postVar.get('DbPathField', '')
        logger.info("Change DB onOK() method of Postoptions dialog tech table : %s" % techTable)
        logger.info("Change DB onOK() method of Postoptions dialog wire table : %s" % wireTable)
        logger.info("Change DB onOK() method of Postoptions dialog DB path : %s" % DBPath)
        ChangeDBCommon(techTable=techTable, wireTable=wireTable, DBPath=DBPath)
        logger.info("After call Change DB onOK() method of Postoptions dialog")

def UpdateModel(newModel):
    """ Transfers the last Settings from the picked Model to the current MainOptions and SubsOptions """
    global postModel
    logger.info("UpdateModel: old Model: %s  new Model: %s" % (postModel, newModel))
    modelChange = False
    #
    if newModel in ModelSettings:
        if newModel != postModel:
            #Set global Variabel
            postModel = newModel
            modelChange = True
            #
            #Get Saved ProfileName
            ProfileName = getCurrentDoc().GetMachine().GetProfileName().getPyString() #ProfileName from Doc when wire.opticam was saved or 'DEFAULT' if new file
            #Check if Profile exits, otherwise use 'DEFAULT'
            if ProfileName not in ModelSettings[postModel]:
                ProfileName = 'DEFAULT'
            #
            SubsOptions['MODEL'] = MainOptions['MODEL'] = postModel
            if ProfileName in ModelSettings[postModel]:
                for entry, value in list(ModelSettings[postModel][ProfileName].items()):
                    if entry in MainOptions:
                        #MainOptions[entry] = ModelSettings[postModel][ProfileName][entry][1]
                        MainOptions[entry] = value[1]
                    else:
                        logger.debug("Error: Updating key %s in MainOptions at Switchting Models from MFC" % (entry))
                    #
                    if entry in SubsOptions:
                        SubsOptions[entry] = value[1]
                    else:
                        logger.debug("Error: Updating key %s in SubsOptions at Switchting Models from MFC" % (entry))
                    #
                    if entry in postVar:
                        if isinstance(value, list):
                            if postVar[entry] != value[1]:
                                postVar[entry] = value[1]
                                logger.debug("...updated from Mainoptions: postVar[%s] to %s " % (entry, value[1]))
                            else:
                                pass
                        elif isinstance(value, str):
                            if postVar[entry] != value:
                                postVar[entry] = value
                                logger.debug("...updated from Mainoptions: postVar[%s] to %s " % (entry, value))
                            else:
                                pass
                        else:
                            pass
                #
                #self.ProfileChange(curProfile, curModel)    # geht nicht wg. self.
        else:
            # When the postoptions.py file does not exist, the parameters will not be passed to postVar 
            # when processing the postsettings.py file in the loadSetting function, so in this case, 
            # some necessary parameters need to be passed from the ModelsSetting dictionary to the postVar dictionary. 
            # At this time, the data source in the ModelsSettings dictionary is the postsettings.py file.
            # It is mainly to solve such problems. For example, when switching from Mitsubishi to Makino, 
            # the postModel and newModel are the same at this time, but the postVar dictionary does not contain database configuration parameters, 
            # when the postoptions.py file does not exist.
            # Get Saved ProfileName 
            ProfileName = getCurrentDoc().GetMachine().GetProfileName().getPyString() #ProfileName from Doc when wire.opticam was saved or 'DEFAULT' if new file
            #Check if Profile exits, otherwise use 'DEFAULT'
            if ProfileName not in ModelSettings[postModel]:
                ProfileName = 'DEFAULT'
            #
            SubsOptions['MODEL'] = MainOptions['MODEL'] = postModel
            if ProfileName in ModelSettings[postModel]:
                for entry, value in list(ModelSettings[postModel][ProfileName].items()):
                    if not entry in  ['TechTableField', 'WireTechTableField', 'TechField4']:
                        continue
                    if entry in postVar:
                        if isinstance(value, list):
                            if postVar[entry] != value[1]:
                                postVar[entry] = value[1]
                                logger.debug("...updated from Mainoptions: postVar[%s] to %s " % (entry, value[1]))
                            else:
                                pass
                        elif isinstance(value, str):
                            if postVar[entry] != value:
                                postVar[entry] = value
                                logger.debug("...updated from Mainoptions: postVar[%s] to %s " % (entry, value))
                            else:
                                pass
                        else:
                            pass
            logger.debug("Updating key Models: NO CHANGE FOR MODEL '%s'" % (postModel))
    else:
        logger.debug("Error: Updating key Models: NO SUCH MODEL '%s'" % (postModel))
    #
    return modelChange

#------------------------- End of class BasePostOptionsDialog ----------------------------

# wxWindow propagation (parent -> children and so on)
# this method walks through all controls of our main-panel and all sub-panels
# and set the values of this controls with the values of the dictionary (if the appropriate key exists)

def TransferDataToWindow(root, postVar):
    #Use PostVar as list for widgets to walk through
    sRootName = root.Name
    # check root name
    if sRootName in postVar:    # widget-name exists as key in postVar
        logger.info("%s\t_transfer to : %s\tValue=%s %s" % (root.__class__.__name__, sRootName, str(postVar[sRootName]), type(postVar[sRootName])))
        # check specific root name
        if sRootName in  ['TechTableField', 'WireTechTableField', 'TechField4']:
            bForceUsePostVar = True
        else:
            bForceUsePostVar = False
        # 
        dMapping = { '1': 'A', '2': 'B', '3': 'C'}
        transTable = str.maketrans(dMapping)
        # Especially GroupPanel2: Checking if widget hast Model-depentent settings in postsettings.py ModelSettings{}, if not, use Values from postVar
        if postModel in ModelSettings:
            if postProfile in ModelSettings[postModel]:
                SetValue = getattr(root, "SetValue", None)
                if callable(SetValue):
                    dProfileModelSetting = ModelSettings[postModel][postProfile]
                    if root.Name in dProfileModelSetting and bForceUsePostVar == False:    # widget properties described in postsettings.ModelSettings
                        # in case of widgets with lists additionally we have to fill this lists:
                        SetItems = getattr(root, "SetItems", None)
                        if callable(SetItems):
                            varName = sRootName + 'LIST'    # Agreement: widgetname + 'LIST'
                            if varName in dProfileModelSetting:
                                if root.__class__ == DoubleLabeledComboBox:
                                    #logger.info("...setting items : %s and %s" % (dProfileModelSetting[varName][1][0],dProfileModelSetting[varName][1][1]) )
                                    SetItems(ModelSettings[postModel][varName][1])
                                else:
                                    #logger.info("...setting items : %s" % dProfileModelSetting[varName][1])
                                    #postVar[varName] = dProfileModelSetting[varName][1]
                                    SetItems(dProfileModelSetting[varName][1])
                            else:
                                if varName in postVar and sRootName == 'UILayoutType': 
                                    ltSetValues = postVar[varName]
                                    ltFixValues = [t.translate(transTable) if t.startswith('Type ') else t for t in ltSetValues]
                                    SetItems(ltFixValues)
                                    postVar[varName] = ltFixValues
                                else:
                                    pass
                        elif root.__class__ in [EditField, LabeledEditField, DoubleLabeledEditField]:
                            #Implement a change of min/max value with setRange function
                            if len(dProfileModelSetting[sRootName]) >= 3:
                                #Check if we have a valid value inside the dict
                                if root.__class__ == DoubleLabeledEditField:
                                    if type(dProfileModelSetting[sRootName][2]) == tuple and len(dProfileModelSetting[sRootName][2]) == 4:
                                        root.SetRange(dProfileModelSetting[sRootName][2][0],dProfileModelSetting[sRootName][2][1],dProfileModelSetting[sRootName][2][2],dProfileModelSetting[sRootName][2][3])
                                else:
                                    if type(dProfileModelSetting[sRootName][2]) == tuple and len(dProfileModelSetting[sRootName][2]) == 2:
                                        root.SetRange(dProfileModelSetting[sRootName][2][0],dProfileModelSetting[sRootName][2][1])
                        # in case of widgets with abilities additionally we have to set new abilities (atm. only OptiMultiCheckBox):
                        SetAbilities = getattr(root, "SetAbilities", None)
                        if callable(SetAbilities):
                            varName = sRootName + 'SKILL'    # Agreement: widgetname + 'SKILL'
                            if varName in dProfileModelSetting:
                                SetAbilities(dProfileModelSetting[varName][1])
                        #Set the control enable or disable
                        enabled = bool( dProfileModelSetting[sRootName][0] )
                        #set value for this control
                        value   = dProfileModelSetting[sRootName][1]
                        if sRootName == 'UILayoutType':
                            value = value.translate(transTable)
                            dProfileModelSetting[sRootName][1] = value
                        root.Enable(enabled)
                        SetValue(value)
                    else:
                        if root.__class__ in [OptiRadioBox]:
                            # For the class OptiRadioBox, we would not check the method "SetItems()". 
                            # Because this method will be used for setting the labels of radio buttons 
                            value = postVar[sRootName]
                            SetValue(value)
                            varName = sRootName + 'LIST'    # Agreement: widgetname + 'LIST'
                            if varName in postVar:    # if the key exists...
                                del postVar[varName]
                        else:
                            #[OptiRadioButton, OptiCheckBox, OptiMultiCheckBox, LabeledEditField, LabeledComboBox, LabeledComboBox2, TextField, EditField, NormalButton]
                            # in case of widgets with lists additionally we have to fill this lists:
                            SetItems = getattr(root, "SetItems", None)
                            if callable(SetItems):
                                logger.info("debug ...setting (list type) widget : %s" % sRootName)
                                varName = sRootName + 'LIST'    # Agreement: widgetname + 'LIST'
                                if varName in postVar:    # if the key exists...
                                    logger.info("...setting items : %s" % postVar[varName])
                                    SetItems(postVar[varName])
                            # in case of widgets with abilities additionally we have to set new abilities (atm. only OptiMultiCheckBox):
                            SetAbilities = getattr(root, "SetAbilities", None)
                            if callable(SetAbilities):
                                varName = sRootName + 'SKILL'    # Agreement: widgetname + 'SKILL'
                                if varName in postVar:
                                    SetAbilities(postVar[varName])
                            value = postVar[sRootName]
                            SetValue(value)
                else:
                    pass # the control has no method like "SetValue"
                    #
    for child in root.GetChildren():
        if not TransferDataToWindow(child, postVar):        # recursive call !!
            return False

    return True

def TransferDataFromWindow(root):
    #Save Settings into postVar
    if root.Name in postVar:    # widget-name exists as key in postVar
        GetValue = getattr(root, "GetValue", None)
        if callable(GetValue):
            postVar[root.Name] = GetValue()
            logger.info("%s\t_transfer from : %s\tValue=%s %s" % (root.__class__.__name__, root.Name, str(postVar[root.Name]), type(postVar[root.Name])))
            if root.__class__ in [OptiRadioBox]:
                # For the class OptiRadioBox, we would not check the method "GetItems()". Because the return values of this method are the labels of Radio buttons and 
                # they are in currently language. If we have saved the labels in postoptions.py. On Loading the label is maybe not in correctly language, 
                # if the user changed language setting before closing. 
                #postVar[root.Name] = GetValue()
                pass
            else:
                # in case of widgets with lists additionally we can get this lists:
                #[OptiRadioButton, OptiCheckBox, OptiMultiCheckBox, LabeledEditField, LabeledComboBox, LabeledComboBox2, TextField, EditField, NormalButton] etc.
                #postVar[root.Name] = GetValue()
                GetItems = getattr(root, "GetItems", None)
                if callable(GetItems):
                    varName = root.Name + 'LIST'    # Agreement: widgetname + 'LIST'
                    postVar[varName] = GetItems()
                    logger.info("...getting items : %s" % str(postVar[varName]))

    for child in root.GetChildren():
        if not TransferDataFromWindow(child):
            return False

    return True


def GetModelSetting():
    if postModel in ModelSettings:
        if postProfile in ModelSettings[postModel]:
            return ModelSettings[postModel][postProfile]
        else:
            return ModelSettings[postModel]
    else:
        return None


def GetTravelLimits(pVar):
    if postModel in Models:
        mSet = Models[postModel]

#        pVar['Serie'] = mSet['Serie'] if 'Serie' in mSet else None
        pVar['TaperMax'] = mSet['TaperMax'] if 'TaperMax' in mSet else None
        pVar['xMin'] = mm(mSet['xMin']) if 'xMin' in mSet else None
        pVar['yMin'] = mm(mSet['yMin']) if 'yMin' in mSet else None
        pVar['zMin'] = mm(mSet['zMin']) if 'zMin' in mSet else 0.0
        pVar['uMin'] = mm(mSet['uMin']) if 'uMin' in mSet else None
        pVar['vMin'] = mm(mSet['vMin']) if 'vMin' in mSet else None
        pVar['xMax'] = mm(mSet['xMax']) if 'xMax' in mSet else None
        pVar['yMax'] = mm(mSet['yMax']) if 'yMax' in mSet else None
        pVar['zMax'] = mm(mSet['zMax']) if 'zMax' in mSet else None
        pVar['uMax'] = mm(mSet['uMax']) if 'uMax' in mSet else None
        pVar['vMax'] = mm(mSet['vMax']) if 'vMax' in mSet else None
        #
        if 'MnemonicsMode' in mSet and mSet['MnemonicsMode'] is not None:
            pVar['MnemonicsMode'] = mSet['MnemonicsMode']
        # if 'SeperateNCFiles' in mSet and mSet['SeperateNCFiles'] is not None:
        #     pVar['SeperateNCFiles'] = mSet['SeperateNCFiles']


def SetTravelLimits(pVar, postModel):
    if postModel in Models:
        mSet = Models[postModel]

#        if 'Serie' in pVar:    mSet['Serie'] = pVar['Serie']
        if 'TaperMax' in pVar: mSet['TaperMax'] = pVar['TaperMax']
        if 'xMin' in pVar and pVar['xMin'] is not None:     mSet['xMin'] = toMM(pVar['xMin'])
        if 'yMin' in pVar and pVar['yMin'] is not None:     mSet['yMin'] = toMM(pVar['yMin'])
        if 'zMin' in pVar and pVar['zMin'] is not None:     mSet['zMin'] = toMM(pVar['zMin'])
        else:                                               mSet['zMin'] = 0.0
        if 'uMin' in pVar and pVar['uMin'] is not None:     mSet['uMin'] = toMM(pVar['uMin'])
        if 'vMin' in pVar and pVar['vMin'] is not None:     mSet['vMin'] = toMM(pVar['vMin'])
        if 'xMax' in pVar and pVar['xMax'] is not None:     mSet['xMax'] = toMM(pVar['xMax'])
        if 'yMax' in pVar and pVar['yMax'] is not None:     mSet['yMax'] = toMM(pVar['yMax'])
        if 'zMax' in pVar and pVar['zMax'] is not None:     mSet['zMax'] = toMM(pVar['zMax'])
        if 'uMax' in pVar and pVar['uMax'] is not None:     mSet['uMax'] = toMM(pVar['uMax'])
        if 'vMax' in pVar and pVar['vMax'] is not None:     mSet['vMax'] = toMM(pVar['vMax'])
        #
        if 'MnemonicsMode' in pVar and pVar['MnemonicsMode'] is not None:         mSet['MnemonicsMode'] = pVar['MnemonicsMode']       # atm. an extension only for onaaf
        # if 'SeperateNCFiles' in pVar and pVar['SeperateNCFiles'] is not None:     mSet['SeperateNCFiles'] = pVar['SeperateNCFiles']


def regtestsettings(testdict={}):
    """
    Functions allows passing various special settings for regression-test mode
    as a dictionary
    """
    global postVar
    
    if len(testdict) > 0:
        for key,val in list(testdict.items()):
            logger.info("RegTestSettings: %s=%s" % (key, val))
            postVar[key] = val
        #
        updatePostDicts()
        
def updatePostDicts():
    """ Update dictionaries used in the postprocessor from postVar."""
    logger.info("%s [%s]" % ("postoptionsdlg.updatePostDicts", ""))

    style = None
    width = None
    #
    if postVar.get('decimalPoint') == True:
        style = iso.STYLE_DOUBLE
        width = 10
    elif postVar.get('decimalPoint') == False:
        if True:    #postVar['ClassName'] == 'RoboFilPostOptionsDialog':        #isinstance(self, RoboFilPostOptionsDialog):
            style = iso.STYLE_IMPLIED_NOLEADZEROS
            #width = 6
            width = 7
            postVar['DigitsAfter'] = u'3'      # important for correct output values
        else:
            style = iso.STYLE_FIXED_NOLEADZEROS
            postVar['DigitsAfter'] = u'3'      # important for correct output values
    #
    nDigits = int(postVar['DigitsAfter']) if 'DigitsAfter' in postVar else None
    #
    d = MainOptions
    mo = {}
    mo = updatePostDictsCall(d, mo)
    MainOptions.update(mo)

    d = MainAddresses
    ma = {}
    for addr in ('X', 'Y', 'I', 'J', 'U', 'V', 'K', 'L', 'RefPlane', 'SecPlane', 'blend', 'Z', 'H', 'F', 'taper'):
        if addr in d and addr not in postVar.get('IgnoreAdresses', []):
            ma[addr] = (d[addr][0],
                        d[addr][1],
                        width   if width   != None else d[addr][2],
                        nDigits if nDigits != None else d[addr][3],
                        style   if style   != None else d[addr][4],
                        d[addr][5],
                        )
            
    MainAddresses.update(ma)
    SubsAddresses.update(ma)

    d = SubsOptions
    so = {}
    so = updatePostDictsCall(d, so)
    SubsOptions.update(so)

    d = ModelSettings
    ms = {}
    for root in list(ModelSettings.keys()):
        ms2 = {}        # second level dict. (one per model)
        ms3 = {}        # third level dict
        for ProfileName in list(ModelSettings[root].keys()):
            if root == postModel:
                if ProfileName == postProfile:
                    for key in list(ModelSettings[root][ProfileName].keys()):
                        if key in  ['TechTableField', 'WireTechTableField', 'TechField4']:
                            # During the entire process of running the program, the settings of the database in the Modellsetting dictionary should be kept unchanged. 
                            # The Modellsetting dictionary should only pass in the new value of the database setting from postVar when the "save" button is clicked.
                            enabled  = d[root][ProfileName][key][0]
                            value    = d[root][ProfileName][key][1]
                            ms3[key] = [enabled, value]
                            continue
                        if key in postVar:
                            enabled  = d[root][ProfileName][key][0]
                            value    = postVar[key]
                            ms3[key] = [enabled, value]
                    #Save the whole dict and add the changes into it
                    ms2 = ModelSettings[root] #save the dict, otherwise we will lose it!
                    ms2[ProfileName] = ms3 #add changes from this Profile
            else:
                ms2[ProfileName] = d[root][ProfileName]
        ms[root] = ms2

    ModelSettings.update(ms)

    # Values for the model-dictionary are already updated, purpose is to write out only values for act. Model
    d = Models
    md = {}
    for root in list(Models.keys()):
        md[root] = d[root]

    return (mo, ma, so, ma, ms, md)

def updatePostDictsCall(d, so):
    if 'BlockOutPutStart' in postVar and 'BlockOutPutStep' in postVar and 'BlockOutPutDoOutPut' in postVar and 'BlockOutPutMax' in postVar:
        so['blockno'] = (postVar['BlockOutPutStart'], postVar['BlockOutPutStep'], postVar['BlockOutPutMax'], postVar['BlockOutPutDoOutPut'])                   # block start, increment and maximum
    if 'DigitsAfter' in postVar: so['digits'] = { 'Trail' : int(postVar['DigitsAfter']) }
    if 'OutputUnitsMetric' in postVar:
        so['outputUnits'] = 'mm' if postVar['OutputUnitsMetric'] == True else 'inch'
        units = 'Metric' if postVar['OutputUnitsMetric'] == True else 'Inch'
        so['units'] = { 'Type' : units , 'Base' : 'gf' }
    if 'AbsoluteCommandAbsolute' in postVar:
        absolute = 'Absolute' if postVar['AbsoluteCommandAbsolute'] == True else 'Increment'
        so['absolute'] = { 'Type' : absolute , 'Base' : 'gf' }
    if 'OpenNCFile' in postVar: so['OpenNCFile'] = postVar['OpenNCFile']
    if 'ShowInExplorer' in postVar: so['ShowInExplorer'] = postVar['ShowInExplorer']
    if 'SetupSheet' in postVar: so['SetupSheet'] = postVar['SetupSheet']
    if 'SetupSheetCompact' in postVar: so['SetupSheetCompact'] = postVar['SetupSheetCompact']
    if 'SetupSheetExtraCompact' in postVar: so['SetupSheetExtraCompact'] = postVar['SetupSheetExtraCompact']
    if 'SetupSheet3D' in postVar: so['SetupSheet3D'] = postVar['SetupSheet3D']
    if 'SelectedStartholePP' in postVar: so['SelectedStartholePP'] = postVar['SelectedStartholePP']
    if 'StartHoleFile' in postVar: so['StartHoleFile'] = postVar['StartHoleFile']
    if 'OpenStartHoleFile' in postVar: so['OpenStartHoleFile'] = postVar['OpenStartHoleFile']
    if 'OutputComment' in postVar: so['OutputComment'] = postVar['OutputComment']
    if 'CommentsInHeader' in postVar: so['CommentsInHeader'] = postVar['CommentsInHeader']
    if 'OutputTechComment' in postVar: so['OutputTechComment'] = postVar['OutputTechComment']
    if 'ConfirmForNewOperations' in postVar: so['ConfirmForNewOperations'] = postVar['ConfirmForNewOperations']
    
    if 'OutputPercSignBeforeMain' in postVar: so['OutputPercSignBeforeMain'] = postVar['OutputPercSignBeforeMain']
    if 'AutomaticThreading' in postVar: so['AutomaticThreading'] = postVar['AutomaticThreading']
    if 'NoThreadingOutput' in postVar: so['NoThreadingOutput'] = postVar['NoThreadingOutput']
    if 'AdvancedTaper' in postVar: so['AdvancedTaper'] = postVar['AdvancedTaper']
    if 'GeneratorOut' in postVar: so['GeneratorOut'] = postVar['GeneratorOut']
    if 'OutputTechnology' in postVar: so['OutputTechnology'] = postVar['OutputTechnology']
    if 'FanucHeader' in postVar: so['FanucHeader'] = postVar['FanucHeader']
    if 'G92AfterThread' in postVar: so['G92AfterThread'] = postVar['G92AfterThread']
    if 'OutputOrigin' in postVar: so['OutputOrigin'] = postVar['OutputOrigin']
    if 'OutputOriginBeforeThread' in postVar: so['OutputOriginBeforeThread'] = postVar['OutputOriginBeforeThread']
    if 'OutputOriginAfterThread' in postVar: so['OutputOriginAfterThread'] = postVar['OutputOriginAfterThread']
    if 'OutputG90AfterG92' in postVar: so['OutputG90AfterG92'] = postVar['OutputG90AfterG92']
    if 'OutputG54P9999' in postVar: so['OutputG54P9999'] = postVar['OutputG54P9999']
    if 'OutputG90G00G40G50' in postVar: so['OutputG90G00G40G50'] = postVar['OutputG90G00G40G50']
    if 'OutputOriginBeforeGeneratorCall' in postVar: so['OutputOriginBeforeGeneratorCall'] = postVar['OutputOriginBeforeGeneratorCall']
    if 'OutputOriginBeforeEachCut' in postVar: so['OutputOriginBeforeEachCut'] = postVar['OutputOriginBeforeEachCut']
    if 'G75Mode' in postVar: so['G75Mode'] = postVar['G75Mode']
    if 'ConicModeM15P' in postVar: so['ConicModeM15P'] = postVar['ConicModeM15P']
    if 'OutputSubRotated' in postVar: so['OutputSubRotated'] = postVar['OutputSubRotated']
    if 'OutputSubScaled' in postVar: so['OutputSubScaled'] = postVar['OutputSubScaled']
    if 'OutputSubMirrored' in postVar: so['OutputSubMirrored'] = postVar['OutputSubMirrored']
    if 'OutputSubInExtraFiles' in postVar: so['OutputSubInExtraFiles'] = postVar['OutputSubInExtraFiles']
    if 'OutputHeightOnTechLine' in postVar: so['OutputHeightOnTechLine'] = postVar['OutputHeightOnTechLine']
    if 'OutputTechnologyISO' in postVar: so['OutputTechnologyISO'] = postVar['OutputTechnologyISO']
    if 'UseKnowledgeBase' in postVar: so['UseKnowledgeBase'] = postVar['UseKnowledgeBase']
    if 'CopyTecToNCFolder' in postVar: so['CopyTecToNCFolder'] = postVar['CopyTecToNCFolder']
    if 'CopyWirToNCFolder' in postVar: so['CopyWirToNCFolder'] = postVar['CopyWirToNCFolder']
    if 'EofChar' in postVar: so['EofChar'] = postVar['EofChar']
    if 'optionalStop' in postVar: so['optionalStop'] = postVar['optionalStop']
    if 'GeometryStrategy' in postVar: so['GeometryStrategy'] = postVar['GeometryStrategy']
    if 'GeometryStrategyM23' in postVar: so['GeometryStrategyM23'] = postVar['GeometryStrategyM23']
    if 'GeometryStrategyM24' in postVar: so['GeometryStrategyM24'] = postVar['GeometryStrategyM24']
    if 'WireStrategy' in postVar: so['WireStrategy'] = postVar['WireStrategy']
    if 'WireStrategyM27' in postVar: so['WireStrategyM27'] = postVar['WireStrategyM27']
    if 'WireStrategyM28' in postVar: so['WireStrategyM28'] = postVar['WireStrategyM28']
    if 'WireStrategyM29' in postVar: so['WireStrategyM29'] = postVar['WireStrategyM29']
    if 'AdditionalOffsetGeometry' in postVar: so['AdditionalOffsetGeometry'] = postVar['AdditionalOffsetGeometry']
    if 'RForEverySegment' in postVar: so['RForEverySegment'] = postVar['RForEverySegment']
    if 'UseSeperateRegistersForOffset' in postVar: so['UseSeperateRegistersForOffset'] = postVar['UseSeperateRegistersForOffset']
    if 'PutOutRegistersForEverySegment' in postVar: so['PutOutRegistersForEverySegment'] = postVar['PutOutRegistersForEverySegment']
    if 'CutWireAtEndOfProgram' in postVar: so['CutWireAtEndOfProgram'] = postVar['CutWireAtEndOfProgram']
    if 'PrepareWorkpieceForTilting' in postVar: so['PrepareWorkpieceForTilting'] = postVar['PrepareWorkpieceForTilting']
    if 'AdditionalOffsetForEachCut' in postVar: so['AdditionalOffsetForEachCut'] = postVar['AdditionalOffsetForEachCut']
    if 'WPROutput' in postVar: so['WPROutput'] = postVar['WPROutput']
    if 'OptionalBlocks' in postVar: so['OptionalBlocks'] = postVar['OptionalBlocks']
    if 'ConicityCompensationM11' in postVar: so['ConicityCompensationM11'] = postVar['ConicityCompensationM11']
    if 'LightOnAtStop' in postVar: so['LightOnAtStop'] = postVar['LightOnAtStop']
    if 'DrawIso' in postVar: so['DrawIso'] = postVar['DrawIso']

    if 'OutputThickness' in postVar: so['OutputThickness'] = postVar['OutputThickness']
    if 'G38Function' in postVar: so['G38Function'] = postVar['G38Function']
    if 'G68Function' in postVar: so['G68Function'] = postVar['G68Function']
    if 'ConicCornerFunction' in postVar: so['ConicCornerFunction'] = postVar['ConicCornerFunction']
    if 'RemoteAlarm' in postVar: so['RemoteAlarm'] = postVar['RemoteAlarm']
    if 'ReThreading' in postVar: so['ReThreading'] = postVar['ReThreading']
    if 'CornerStrategy' in postVar: so['CornerStrategy'] = postVar['CornerStrategy']
    if 'CornerStrategyHeader' in postVar: so['CornerStrategyHeader'] = postVar['CornerStrategyHeader']
    if 'CornerStrategyLeadin' in postVar: so['CornerStrategyLeadin'] = postVar['CornerStrategyLeadin']
    if 'StrategyForRoughcuts' in postVar: so['StrategyForRoughcuts'] = postVar['StrategyForRoughcuts']
    if 'GeneratorSettingSeparate' in postVar: so['GeneratorSettingSeparate'] = postVar['GeneratorSettingSeparate']
    if 'PathCorrectionAfterLeadOn' in postVar: so['PathCorrectionAfterLeadOn'] = postVar['PathCorrectionAfterLeadOn']
    if 'DWell' in postVar: so['DWell'] = postVar['DWell']
    if 'DWellTime' in postVar: so['DWellTime'] = postVar['DWellTime']
    if 'DWellOnAllCuts' in postVar: so['DWellOnAllCuts'] = postVar['DWellOnAllCuts']
    if 'Delay' in postVar: so['Delay'] = postVar['Delay']
    if 'DelayTime' in postVar: so['DelayTime'] = postVar['DelayTime']
    if 'OutputTecFile' in postVar: so['OutputTecFile'] = postVar['OutputTecFile']
    if 'OutputG20G21' in postVar: so['OutputG20G21'] = postVar['OutputG20G21']
    if 'TParameter' in postVar: so['TParameter'] = postVar['TParameter']
    if 'ThreadInGap' in postVar: so['ThreadInGap'] = postVar['ThreadInGap']
    if 'NoThreadingOutput' in postVar: so['NoThreadingOutput'] = postVar['NoThreadingOutput']

    if 'ClearProzessControlDataM74' in postVar: so['ClearProzessControlDataM74'] = postVar['ClearProzessControlDataM74']
    if 'OutputRefSecPlanes' in postVar: so['OutputRefSecPlanes'] = postVar['OutputRefSecPlanes']
    if 'OutputReferenceVar' in postVar: so['OutputReferenceVar'] = postVar['OutputReferenceVar']
    if 'OutputReferenceRegister' in postVar: so['OutputReferenceRegister'] = postVar['OutputReferenceRegister']
    if 'OutputReferenceValue' in postVar: so['OutputReferenceValue'] = postVar['OutputReferenceValue']
    if 'OutputHeightVar' in postVar: so['OutputHeightVar'] = postVar['OutputHeightVar']
    if 'OutputHeightRegister' in postVar: so['OutputHeightRegister'] = postVar['OutputHeightRegister']
    if 'OutputHeightValue' in postVar: so['OutputHeightValue'] = postVar['OutputHeightValue']
    if 'G92_X_Y_I_J' in postVar: so['G92_X_Y_I_J'] = postVar['G92_X_Y_I_J']
    if 'G92_X_Y_Z_I' in postVar: so['G92_X_Y_Z_I'] = postVar['G92_X_Y_Z_I']
    if 'OutputEpackM17' in postVar: so['OutputEpackM17'] = postVar['OutputEpackM17']
    if 'Software' in postVar: so['Software'] = postVar['Software']
    if 'OutputG92' in postVar: so['OutputG92'] = postVar['OutputG92']
    if 'OutputDirectOffset' in postVar: so['OutputDirectOffset'] = postVar['OutputDirectOffset']
    if 'DirectOffsetMicrons' in postVar: so['DirectOffsetMicrons'] = postVar['DirectOffsetMicrons']
    if 'NoOutputOffsetregisterValuesNC' in postVar: so['NoOutputOffsetregisterValuesNC'] = postVar['NoOutputOffsetregisterValuesNC']
    if 'UserCornerControl' in postVar: so['UserCornerControl'] = postVar['UserCornerControl']
    if 'M00insteadM01' in postVar: so['M00insteadM01'] = postVar['M00insteadM01']
    if 'Stop1Mode' in postVar: so['Stop1Mode'] = postVar['Stop1Mode']
    if 'Stop2Mode' in postVar: so['Stop2Mode'] = postVar['Stop2Mode']
    if 'StopAsComment' in postVar: so['StopAsComment'] = postVar['StopAsComment']
    if 'M00insteadM01forStop' in postVar: so['M00insteadM01forStop'] = postVar['M00insteadM01forStop']
    if 'AutoRegisterFix' in postVar: so['AutoRegisterFix'] = postVar['AutoRegisterFix']
    if 'TaperAddressCharA' in postVar: so['TaperAddressCharA'] = postVar['TaperAddressCharA']
    if 'DontSuppressIdenticalRegisterEntries' in postVar: so['DontSuppressIdenticalRegisterEntries'] = postVar['DontSuppressIdenticalRegisterEntries']
    if 'OutputM06RapidMove' in postVar: so['OutputM06RapidMove'] = postVar['OutputM06RapidMove']
    if 'OutputG41G42Offset' in postVar: so['OutputG41G42Offset'] = postVar['OutputG41G42Offset']

    #  for the common header stuff used in all pp's
    if 'OutputUserDefinedHeader' in postVar: so['OutputUserDefinedHeader'] = postVar['OutputUserDefinedHeader']
    if 'UserDefinedHeaderField' in postVar: so['UserDefinedHeaderField'] = postVar['UserDefinedHeaderField']
    if 'OutputUserDefinedFooter' in postVar: so['OutputUserDefinedFooter'] = postVar['OutputUserDefinedFooter']
    if 'UserDefinedFooterField' in postVar: so['UserDefinedFooterField'] = postVar['UserDefinedFooterField']

    # for the special cmd-header stuff used in accutx00, accutexx0, acorange, accutuniquaseq
    if 'OutputHeader' in postVar: so['OutputHeader'] = postVar['OutputHeader']
    if 'editFieldHeader' in postVar: so['editFieldHeader'] = postVar['editFieldHeader']
    if 'OutputFooter' in postVar: so['OutputFooter'] = postVar['OutputFooter']
    if 'editFieldFooter' in postVar: so['editFieldFooter'] = postVar['editFieldFooter']
    if 'editHeader' in postVar: so['editHeader'] = postVar['editHeader']                # special only Joemars (needs to be overworked)

    if 'OutputNoTechnology' in postVar: so['OutputNoTechnology'] = postVar['OutputNoTechnology']
    if 'G11SequenceOutput' in postVar: so['G11SequenceOutput'] = postVar['G11SequenceOutput']
    if 'EmptyTankAtEnd' in postVar: so['EmptyTankAtEnd'] = postVar['EmptyTankAtEnd']

    if 'MnemonicsMode' in postVar: so['MnemonicsMode'] = postVar['MnemonicsMode']
    if 'TechnologyDatabase' in postVar: so['TechnologyDatabase'] = postVar['TechnologyDatabase']
    if 'SelectDbManually' in postVar: so['SelectDbManually'] = postVar['SelectDbManually']
    if 'ChoiceDbSelection' in postVar: so['ChoiceDbSelection'] = postVar['ChoiceDbSelection']
    if 'ChoiceDbSelectionList' in postVar: so['ChoiceDbSelectionList'] = postVar['ChoiceDbSelectionList']
    if 'LoadTechnologyOld' in postVar: so['LoadTechnologyOld'] = postVar['LoadTechnologyOld']
    if 'LoadTechnologyNew' in postVar: so['LoadTechnologyNew'] = postVar['LoadTechnologyNew']
    if 'TechFile' in postVar: so['TechFile'] = postVar['TechFile']

    if 'SecurityPlane' in postVar: so['SecurityPlane'] = postVar['SecurityPlane']
    if 'ReturnPlane' in postVar: so['ReturnPlane'] = postVar['ReturnPlane']
    if 'Variocut' in postVar: so['Variocut'] = postVar['Variocut']
    if 'ThreeDMeasurement' in postVar: so['ThreeDMeasurement'] = postVar['ThreeDMeasurement']
    if 'AgieSoftware02080304' in postVar: so['AgieSoftware02080304'] = postVar['AgieSoftware02080304']
    if 'CreateQualityExtraSection' in postVar: so['CreateQualityExtraSection'] = postVar['CreateQualityExtraSection']
    if 'DatabaseVersionChoice' in postVar: so['DatabaseVersionChoice'] = postVar['DatabaseVersionChoice']
    if 'NumberSeparatedWithUnderscore' in postVar: so['NumberSeparatedWithUnderscore'] = postVar['NumberSeparatedWithUnderscore']
    if 'CharactersForIsoSbl' in postVar: so['CharactersForIsoSbl'] = postVar['CharactersForIsoSbl']
    if 'EnableComScript' in postVar: so['EnableComScript'] = postVar['EnableComScript']
    if 'OverwriteIso' in postVar: so['OverwriteIso'] = postVar['OverwriteIso']
    if 'OverwriteScript' in postVar: so['OverwriteScript'] = postVar['OverwriteScript']
    if 'MachinigsPerScript' in postVar: so['MachinigsPerScript'] = postVar['MachinigsPerScript']
    if 'ImportPathField' in postVar: so['ImportPathField'] = postVar['ImportPathField']
    if 'ImportPathLabel' in postVar: so['ImportPathLabel'] = postVar['ImportPathLabel']
    if 'PartNumberAsIsoSblName' in postVar: so['PartNumberAsIsoSblName'] = postVar['PartNumberAsIsoSblName']
    if 'FigureNameAsWorkName' in postVar: so['FigureNameAsWorkName'] = postVar['FigureNameAsWorkName']
    if 'OperationDescritionAsWorkName' in postVar: so['OperationDescritionAsWorkName'] = postVar['OperationDescritionAsWorkName']
    if 'DontIncrementPriorityCounter' in postVar: so['DontIncrementPriorityCounter'] = postVar['DontIncrementPriorityCounter']
    if 'UpperNozzleSTLFile' in postVar: so['UpperNozzleSTLFile'] = postVar['UpperNozzleSTLFile']
    if 'LowerNozzleSTLFile' in postVar: so['LowerNozzleSTLFile'] = postVar['LowerNozzleSTLFile']
    if 'WindowsControl' in postVar: so['WindowsControl'] = postVar['WindowsControl']

    if 'MachineControl' in postVar: so['MachineControl'] = postVar['MachineControl']
    if 'RadioEvenParity' in postVar: so['RadioEvenParity'] = postVar['RadioEvenParity']
    if 'RadioASCII' in postVar: so['RadioASCII'] = postVar['RadioASCII']
    if 'ProgramName' in d:
        dP = d['ProgramName']
        #d1 = postVar.get('Length', dn['Length'])       # <str>
        #d2 = postVar.get('Allow',  dn['Allow'])         # <str>
        #d3 = postVar.get('ExtLength', dn['ExtLength'])    # <str>
        d4 = postVar.get('ExtChars',   dP['ExtChars'])      # <str>
        #d5 = postVar.get('ExtLength2', dn['ExtLength2'])    # <str>
        d6 = postVar.get('ExtChars2',  dP['ExtChars2'])      # <str>
        so['ExtChars']  = d4.split('.')[-1]
        so['ExtChars2'] = d6.split('.')[-1]
        so['ProgramName'] = {'Length' : dP['Length'], 'Allow' : dP['Allow'], 'ExtLength' : dP['ExtLength'], 'ExtChars' : so['ExtChars'], 'ExtLength2' : dP['ExtLength2'], 'ExtChars2' : so['ExtChars2']}
    if 'StopWithoutSlash' in postVar: so['StopWithoutSlash'] = postVar['StopWithoutSlash']
    if 'M94AtProfileEnd' in postVar: so['M94AtProfileEnd'] = postVar['M94AtProfileEnd']
    if 'BlocksBeforeOutput' in postVar: so['BlocksBeforeOutput'] = postVar['BlocksBeforeOutput']
    if 'BlocksBeforeOutputValue' in postVar: so['BlocksBeforeOutputValue'] = postVar['BlocksBeforeOutputValue']
    if 'TapeOutput' in postVar: so['TapeOutput'] = postVar['TapeOutput']
    if 'NullsInTape' in postVar: so['NullsInTape'] = postVar['NullsInTape']
    if 'M02AfterRoughCut' in postVar: so['M02AfterRoughCut'] = postVar['M02AfterRoughCut']
    if 'OffsetIncrement' in postVar: so['OffsetIncrement'] = postVar['OffsetIncrement']
    if 'OffsetIncrementValue' in postVar: so['OffsetIncrementValue'] = postVar['OffsetIncrementValue']
    if 'OffsetIncrementRev' in postVar: so['OffsetIncrementRev'] = postVar['OffsetIncrementRev']
    if 'OffsetIncrementRevValue' in postVar: so['OffsetIncrementRevValue'] = postVar['OffsetIncrementRevValue']
    if 'GenerateJob' in postVar: so['GenerateJob'] = postVar['GenerateJob']
    if 'AlwaysOverwriteJob' in postVar: so['AlwaysOverwriteJob'] = postVar['AlwaysOverwriteJob']
    if 'NoOfCharBeforeEXEC' in postVar: so['NoOfCharBeforeEXEC'] = postVar['NoOfCharBeforeEXEC']
    if 'NoOfCharForTEC' in postVar: so['NoOfCharForTEC'] = postVar['NoOfCharForTEC']
    if 'OutputProgsDieFaceUp' in postVar: so['OutputProgsDieFaceUp'] = postVar['OutputProgsDieFaceUp']
    if 'OutputProgsDieFaceUp' in postVar: so['OutputProgsDieFaceUp'] = postVar['OutputProgsDieFaceUp']
    if 'WarnOnlyOnceProfiling' in postVar: so['WarnOnlyOnceProfiling'] = postVar['WarnOnlyOnceProfiling']

    #Output Modes
    if 'SingleNCFile' in postVar: so['SingleNCFile'] = postVar['SingleNCFile']
    if 'SeperateNCFiles' in postVar: so['SeperateNCFiles'] = postVar['SeperateNCFiles']
    if 'ScriptFileOutput' in postVar: so['ScriptFileOutput'] = postVar['ScriptFileOutput']
    if 'Subprograms' in postVar: so['Subprograms'] = postVar['Subprograms']
    if 'MainProgramFirst' in postVar: so['MainProgramFirst'] = postVar['MainProgramFirst']
    if 'G54atStart' in postVar: so['G54atStart'] = postVar['G54atStart']

    if 'NoSemicolon' in postVar:
        if 'EncloseNcCodes' in postVar:
            #Special Method for sodick
            so['EncloseNcCodes'] = postVar['EncloseNcCodes']
            so['NoSemicolon'] = postVar['NoSemicolon']
            #for sodick formatting end of block:
            so['eob'] = '\r\n'
            if postVar['EncloseNcCodes'] == True:
                so['eob'] = '"' + so['eob']
            if postVar['NoSemicolon'] == False:
                so['eob'] = ';' + so['eob']
            #for sodick formatting start of block:
            if postVar['EncloseNcCodes'] == True:
                so['sob'] = '" '
            else:
                so['sob'] = ''
        else:
            #Standard Method for No semikolon
            so['NoSemicolon'] = postVar['NoSemicolon']
            if postVar['NoSemicolon'] == True:
                so['eob'] = '\r\n'
            else:
                so['eob'] = ';\r\n'

    if 'RapidModeBeforeDatum' in postVar: so['RapidModeBeforeDatum'] = postVar['RapidModeBeforeDatum']
    if 'OutputReThread' in postVar: so['OutputReThread'] = postVar['OutputReThread']
    if 'UseApproachPath' in postVar: so['UseApproachPath'] = postVar['UseApproachPath']
    if 'OutputWSWTWC' in postVar: so['OutputWSWTWC'] = postVar['OutputWSWTWC']
    if 'OutputStartCodes' in postVar: so['OutputStartCodes'] = postVar['OutputStartCodes']
    if 'OutputRefAndSec' in postVar: so['OutputRefAndSec'] = postVar['OutputRefAndSec']
    if 'OutputG92Z0' in postVar: so['OutputG92Z0'] = postVar['OutputG92Z0']
    if 'CornerStrategy104' in postVar: so['CornerStrategy104'] = postVar['CornerStrategy104']
    if 'DwellTimeCorner' in postVar: so['DwellTimeCorner'] = postVar['DwellTimeCorner']
    if 'DrainTankAtEnd' in postVar: so['DrainTankAtEnd'] = postVar['DrainTankAtEnd']
    if 'Submergemode' in postVar: so['Submergemode'] = postVar['Submergemode']
    if 'PrefixComments' in postVar: so['PrefixComments'] = postVar['PrefixComments']
    if 'IndependentTopBottomUV' in postVar: so['IndependentTopBottomUV'] = postVar['IndependentTopBottomUV']
    if 'IndependentTopBottom' in postVar: so['IndependentTopBottom'] = postVar['IndependentTopBottom']
    if 'UVOption' in postVar: so['UVOption'] = postVar['UVOption']
    if 'ARBITRARY_UD' in postVar: so['ARBITRARY_UD'] = postVar['ARBITRARY_UD']
    if 'ExtendedPowerCoded' in postVar: so['ExtendedPowerCoded'] = postVar['ExtendedPowerCoded']
    if 'OutputDwell' in postVar: so['OutputDwell'] = postVar['OutputDwell']
    if 'DwellOnDies' in postVar: so['DwellOnDies'] = postVar['DwellOnDies']
    if 'DwellOnPunches' in postVar: so['DwellOnPunches'] = postVar['DwellOnPunches']
    if 'LowPressureFlushing' in postVar: so['LowPressureFlushing'] = postVar['LowPressureFlushing']
    if 'EstimatedCycleTime' in postVar: so['EstimatedCycleTime'] = postVar['EstimatedCycleTime']
    if 'SaveActualTime' in postVar: so['SaveActualTime'] = postVar['SaveActualTime']
    if 'CycleTime' in postVar: so['CycleTime'] = postVar['CycleTime']
    if 'TagRemovalC000' in postVar: so['TagRemovalC000'] = postVar['TagRemovalC000']
    if 'LeadWithH000' in postVar: so['LeadWithH000'] = postVar['LeadWithH000']
    if 'AngleDeviation' in postVar: so['AngleDeviation'] = postVar['AngleDeviation']
    if 'ReThreadM03' in postVar: so['ReThreadM03'] = postVar['ReThreadM03']
    if 'PocketingRegister' in postVar: so['PocketingRegister'] = postVar['PocketingRegister']
    if 'TaperRegister' in postVar: so['TaperRegister'] = postVar['TaperRegister']
    if 'TaperOffset' in postVar: so['TaperOffset'] = postVar['TaperOffset']
    if 'RegenerateWireAndMaterial' in postVar: so['RegenerateWireAndMaterial'] = postVar['RegenerateWireAndMaterial']
    if 'TechnologyMatching' in postVar: so['TechnologyMatching'] = postVar['TechnologyMatching']
    if 'ImportFromMachine' in postVar: so['ImportFromMachine'] = postVar['ImportFromMachine']
    if 'DatabasePath' in postVar: so['DatabasePath'] = postVar['DatabasePath']
    if 'DoNotOutputOffsetinNC' in postVar: so['DoNotOutputOffsetinNC'] = postVar['DoNotOutputOffsetinNC']
    if 'DoNotAddHeader' in postVar: so['DoNotAddHeader'] = postVar['DoNotAddHeader']
    if 'EditNCHeader' in postVar: so['EditNCHeader'] = postVar['EditNCHeader']
    if 'ChooseNcHeader' in postVar: so['ChooseNcHeader'] = postVar['ChooseNcHeader']
    if 'CreateNCHeader' in postVar: so['CreateNCHeader'] = postVar['CreateNCHeader']

    if 'FamilyText' in postVar: so['FamilyText'] = postVar['FamilyText']
    if 'OptionsText' in postVar: so['OptionsText'] = postVar['OptionsText']
    if 'MODEL' in postVar: so['MODEL'] = postVar['MODEL']
    if 'PROFILE' in postVar: so['PROFILE'] = postVar['PROFILE']
    if 'VERSION' in postVar: so['VERSION'] = postVar['VERSION']
    if 'MINDBFOLDER' in postVar: so['MINDBFOLDER'] = postVar['MINDBFOLDER']
    if 'PIECENAME' in postVar: so['PIECENAME'] = postVar['PIECENAME']
    if 'AUTHORNAME' in postVar: so['AUTHORNAME'] = postVar['AUTHORNAME']
    if 'ZReferenceAbove' in postVar: so['ZReferenceAbove'] = postVar['ZReferenceAbove']

    if 'MinimumMemory' in postVar: so['MinimumMemory'] = postVar['MinimumMemory']
    if 'AWF_Control' in postVar: so['AWF_Control'] = postVar['AWF_Control']
    if 'CommentSuppressControl' in postVar: so['CommentSuppressControl'] = postVar['CommentSuppressControl']
    if 'G90BeforeG00' in postVar: so['G90BeforeG00'] = postVar['G90BeforeG00']
    if 'RegisterOnSeperateLine' in postVar: so['RegisterOnSeperateLine'] = postVar['RegisterOnSeperateLine']
    if 'OutputG0X0Y0AtBegin' in postVar: so['OutputG0X0Y0AtBegin'] = postVar['OutputG0X0Y0AtBegin']
    if 'OutputG0X0Y0' in postVar: so['OutputG0X0Y0'] = postVar['OutputG0X0Y0']
    if 'PositioningPoint' in postVar: so['PositioningPoint'] = postVar['PositioningPoint']
#    if 'CanChangeOrigin' in postVar: so['CanChangeOrigin'] = postVar['CanChangeOrigin']
    if 'IsoForEachOrigin' in postVar: so['IsoForEachOrigin'] = postVar['IsoForEachOrigin']
#    if 'UseRotaryAxis' in postVar: so['UseRotaryAxis'] = postVar['UseRotaryAxis']
    if 'OutputHeight' in postVar: so['OutputHeight'] = postVar['OutputHeight']
    if 'VariableTaperAs4Axis' in postVar: so['VariableTaperAs4Axis'] = postVar['VariableTaperAs4Axis']
    if 'OutputECode' in postVar: so['OutputECode'] = postVar['OutputECode']
    if 'OutputG10PR' in postVar: so['OutputG10PR'] = postVar['OutputG10PR']
    if 'OutputG10PRInHeader' in postVar: so['OutputG10PRInHeader'] = postVar['OutputG10PRInHeader']
    if 'OutputG10G11' in postVar: so['OutputG10G11'] = postVar['OutputG10G11']
    if 'OutputG10G11InHeader' in postVar: so['OutputG10G11InHeader'] = postVar['OutputG10G11InHeader']
    if 'UseXYROutput' in postVar: so['UseXYROutput'] = postVar['UseXYROutput']
    if 'RegisterOutputFormat' in postVar: so['RegisterOutputFormat'] = postVar['RegisterOutputFormat']
    if 'G00insteadG92' in postVar: so['G00insteadG92'] = postVar['G00insteadG92']
    # mainly mitsubishi (...and robo)
    if 'UseG2G3ROutput' in postVar: so['UseG2G3ROutput'] = postVar['UseG2G3ROutput']
    if postVar.get('ClassName', 'undefined') in ['MitsubishiPostOptionsDialog']:
        if 'UseG2G3ROutput' in postVar: so['arcXY'] = ('radius') if postVar['UseG2G3ROutput'] == True else ('inc')
    if 'FillTank' in postVar: so['FillTank'] = postVar['FillTank']
    if 'LiftTank' in postVar: so['LiftTank'] = postVar['LiftTank']
    if 'OutputFlushing' in postVar: so['OutputFlushing'] = postVar['OutputFlushing']
    if 'AdaptableControl' in postVar: so['AdaptableControl'] = postVar['AdaptableControl']
    if 'LowPressureForRemoval' in postVar: so['LowPressureForRemoval'] = postVar['LowPressureForRemoval']
    if 'PowerMaster' in postVar: so['PowerMaster'] = postVar['PowerMaster']
    if 'EmptyTankAtThreading' in postVar: so['EmptyTankAtThreading'] = postVar['EmptyTankAtThreading']
    if 'MachineOffsetSwitch' in postVar: so['MachineOffsetSwitch'] = postVar['MachineOffsetSwitch']
    if 'RapidmoveAsFeeding' in postVar: so['RapidmoveAsFeeding'] = postVar['RapidmoveAsFeeding']
    if 'RapidmoveAsFeedingValue' in postVar: so['RapidmoveAsFeedingValue'] = postVar['RapidmoveAsFeedingValue']
    if 'OutputZ3AndZ4' in postVar: so['OutputZ3AndZ4'] = postVar['OutputZ3AndZ4']
    if 'HVarZ3' in postVar: so['HVarZ3'] = postVar['HVarZ3']

    # mainly Acorange
    if 'OutputXML' in postVar: so['OutputXML'] = postVar['OutputXML']
    if 'OutputJOB' in postVar: so['OutputJOB'] = postVar['OutputJOB']
    if 'OutputCOMPACTJOB' in postVar: so['OutputCOMPACTJOB'] = postVar['OutputCOMPACTJOB']
    if 'OutputISO' in postVar: so['OutputISO'] = postVar['OutputISO']
    if 'BatchJSON' in postVar: so['BatchJSON'] = postVar['BatchJSON']
    if 'GenerationStrategy' in postVar: so['GenerationStrategy'] = postVar['GenerationStrategy']
    if 'SortPalletByPallet' in postVar: so['SortPalletByPallet'] = postVar['SortPalletByPallet']
    if 'SortPieceByPiece' in postVar: so['SortPieceByPiece'] = postVar['SortPieceByPiece']
    if postVar.get('ClassName', 'undefined') in ['ACCutX00PostOptionsDialog', 'ACCuteXX0PostOptionsDialog']:
        if 'OutputJOB' in postVar: so['CanUseDifferentHeights'] = postVar['OutputJOB']
    if postVar.get('ClassName', 'undefined') in ['RoboFilPostOptionsDialog']:
        if 'CreateCMDFile' in postVar and 'AdvancedOutput' in postVar: so['CanUseDifferentHeights'] = postVar['CreateCMDFile'] and postVar['AdvancedOutput']
    if postVar.get('ClassName', 'undefined') in ['FanucPostOptionsDialog', 'HitachiPostOptionsDialog', 'MakinoPostOptionsDialog']:
        if 'OutputRefSecPlanes' in postVar: so['CanUseDifferentHeights'] = postVar['OutputRefSecPlanes']
    if postVar.get('ClassName', 'undefined') in ['MitsubishiPostOptionsDialog', 'SodickPostOptionsDialog']:
        if 'OutputRefAndSec' in postVar: so['CanUseDifferentHeights'] = postVar['OutputRefAndSec']
    if 'InclinedFeatureAs4Axis' in postVar: so['InclinedFeatureAs4Axis'] = postVar['InclinedFeatureAs4Axis']
    if 'SequenzeByPeps' in postVar: so['SequenzeByPeps'] = postVar['SequenzeByPeps']
    if 'OutputJobmanagement' in postVar: so['OutputJobmanagement'] = postVar['OutputJobmanagement']
    if 'SequenzeByCtExpert' in postVar: so['SequenzeByCtExpert'] = postVar['SequenzeByCtExpert']
    if 'OutputGOP' in postVar: so['OutputGOP'] = postVar['OutputGOP']
    if 'OutputSEP' in postVar: so['OutputSEP'] = postVar['OutputSEP']
    if 'OutputOSP' in postVar: so['OutputOSP'] = postVar['OutputOSP']
    if 'SEPStartNumber' in postVar: so['SEPStartNumber'] = postVar['SEPStartNumber']
    if 'OutputROT' in postVar: so['OutputROT'] = postVar['OutputROT']
    if 'OutputAsIso' in postVar: so['OutputAsIso'] = postVar['OutputAsIso']
    if 'NoPointcoord' in postVar: so['NoPointcoord'] = postVar['NoPointcoord']
    if 'RapidLeadoff' in postVar: so['RapidLeadoff'] = postVar['RapidLeadoff']
    if 'RefreshDatabase' in postVar: so['RefreshDatabase'] = postVar['RefreshDatabase']
    if 'PointReferenceMode' in postVar: so['PointReferenceMode'] = postVar['PointReferenceMode']
    if 'M28M29Strategy' in postVar: so['M28M29Strategy'] = postVar['M28M29Strategy']
    if 'M28Strategy' in postVar: so['M28Strategy'] = postVar['M28Strategy']
    if 'M29Strategy' in postVar: so['M29Strategy'] = postVar['M29Strategy']
    if 'M20M21Generator' in postVar: so['M20M21Generator'] = postVar['M20M21Generator']
    if 'G60Strategy' in postVar: so['G60Strategy'] = postVar['G60Strategy']
    if 'M24Strategy' in postVar: so['M24Strategy'] = postVar['M24Strategy']
    if 'StandardManagement' in postVar: so['StandardManagement'] = postVar['StandardManagement']
    if 'M189Threading' in postVar: so['M189Threading'] = postVar['M189Threading']
    if 'G64OffsetCorrection' in postVar: so['G64OffsetCorrection'] = postVar['G64OffsetCorrection']
    if 'M61Rethread' in postVar: so['M61Rethread'] = postVar['M61Rethread']

    if 'WireThreaded' in postVar: so['WireThreaded'] = postVar['WireThreaded']
    if 'WirecutFormatChoices' in postVar: so['WirecutFormatChoices'] = postVar['WirecutFormatChoices']
    if 'WirecutFormat' in postVar: so['WirecutFormat'] = postVar['WirecutFormat']
    if 'NcAsWNumber' in postVar: so['NcAsWNumber'] = postVar['NcAsWNumber']
    if 'ResetAngle' in postVar: so['ResetAngle'] = postVar['ResetAngle']
    if 'ResetRadius' in postVar: so['ResetRadius'] = postVar['ResetRadius']
    if 'ResetRotation' in postVar: so['ResetRotation'] = postVar['ResetRotation']
    if 'StarttechnoInSteps' in postVar: so['StarttechnoInSteps'] = postVar['StarttechnoInSteps']
    if 'OffsetInH' in postVar: so['OffsetInH'] = postVar['OffsetInH']
    if 'OffsetAsT' in postVar: so['OffsetAsT'] = postVar['OffsetAsT']
    if 'UseG41G42R0' in postVar: so['UseG41G42R0'] = postVar['UseG41G42R0']
    if 'BlendedCornersG88' in postVar: so['BlendedCornersG88'] = postVar['BlendedCornersG88']
    if 'BlendWithOffset' in postVar: so['BlendWithOffset'] = postVar['BlendWithOffset']
    if 'RegisterOnG92' in postVar: so['RegisterOnG92'] = postVar['RegisterOnG92']
    if 'AngleLikeSeibu' in postVar: so['AngleLikeSeibu'] = postVar['AngleLikeSeibu']
    if 'UseCornerControl' in postVar: so['UseCornerControl'] = postVar['UseCornerControl']
    if 'Use4Condition' in postVar: so['Use4Condition'] = postVar['Use4Condition']
    if 'UseKnowedgeBase' in postVar: so['UseKnowedgeBase'] = postVar['UseKnowedgeBase']
    if 'LoadTechnology' in postVar: so['LoadTechnology'] = postVar['LoadTechnology']

    if 'OutputM89' in postVar: so['OutputM89'] = postVar['OutputM89']
    if 'ThicknessM162M161' in postVar: so['ThicknessM162M161'] = postVar['ThicknessM162M161']

    if 'ChooseDatabase' in postVar: so['ChooseDatabase'] = postVar['ChooseDatabase']
    if 'ExtraStopAsEventStop' in postVar: so['ExtraStopAsEventStop'] = postVar['ExtraStopAsEventStop']

    # Mainly ona
    if 'UseOffsets' in postVar: so['UseOffsets'] = postVar['UseOffsets']
    if 'OffsetsFile' in postVar: so['OffsetsFile'] = postVar['OffsetsFile']
    if 'OffsetNumber' in postVar: so['OffsetNumber'] = postVar['OffsetNumber']
    if 'G69Output' in postVar: so['G69Output'] = postVar['G69Output']
    if 'SubmergedErosion' in postVar: so['SubmergedErosion'] = postVar['SubmergedErosion']
    if 'M32Output' in postVar: so['M32Output'] = postVar['M32Output']
    if 'M44Output' in postVar: so['M44Output'] = postVar['M44Output']
    if 'OutputCornerTypes' in postVar: so['OutputCornerTypes'] = postVar['OutputCornerTypes']

    #Tec Fields
    if 'ManageTechnology' in postVar: so['ManageTechnology'] = postVar['ManageTechnology']
    if 'staticDbPath' in postVar: so['staticDbPath'] = postVar['staticDbPath']
    if 'TechTableField' in postVar: so['TechTableField'] = postVar['TechTableField']
    if 'WireTechTableField' in postVar: so['WireTechTableField'] = postVar['WireTechTableField']
    if 'TechField4' in postVar: so['TechField4'] = postVar['TechField4']
    #Mainly sodick
    if 'OutputTtTbCsp' in postVar: so['OutputTtTbCsp'] = postVar['OutputTtTbCsp']
    if 'CorrectionForSodickBug' in postVar: so['CorrectionForSodickBug'] = postVar['CorrectionForSodickBug']
    
    # Grouppage 4 stuff
    if 'CreateCMDFile' in postVar: so['CreateCMDFile'] = postVar['CreateCMDFile']
    if 'OverwriteCMD' in postVar: so['OverwriteCMD'] = postVar['OverwriteCMD']
    if 'BasicOutput' in postVar: so['BasicOutput'] = postVar['BasicOutput']
    if 'AdvancedOutput' in postVar: so['AdvancedOutput'] = postVar['AdvancedOutput']
    if 'OutputWireFile' in postVar: so['OutputWireFile'] = postVar['OutputWireFile']
    if 'MovCommand' in postVar: so['MovCommand'] = postVar['MovCommand']
    if 'CreateHeader' in postVar: so['CreateHeader'] = postVar['CreateHeader']
    if 'Select Header' in postVar: so['Select Header'] = postVar['Select Header']
    if 'Edit Header' in postVar: so['Edit Header'] = postVar['Edit Header']
    if 'Import Header' in postVar: so['Import Header'] = postVar['Import Header']
    if 'CreateFooter' in postVar: so['CreateFooter'] = postVar['CreateFooter']
    if 'OutputCMDEditField1' in postVar: so['OutputCMDEditField1'] = postVar['OutputCMDEditField1']
    if 'OutputCMDEditField2' in postVar: so['OutputCMDEditField2'] = postVar['OutputCMDEditField2']
    if 'Select Footer' in postVar: so['Select Footer'] = postVar['Select Footer']
    if 'Edit Footer' in postVar: so['Edit Footer'] = postVar['Edit Footer']
    if 'Import Footer' in postVar: so['Import Footer'] = postVar['Import Footer']
    if 'InsertHeaderFooterInCMD' in postVar: so['InsertHeaderFooterInCMD'] = postVar['InsertHeaderFooterInCMD']
    if 'CallHeaderFooterWithCCF' in postVar: so['CallHeaderFooterWithCCF'] = postVar['CallHeaderFooterWithCCF']
    if 'ZCoordinateAsVarCB' in postVar: so['ZCoordinateAsVarCB'] = postVar['ZCoordinateAsVarCB']
    if 'ZCoordinateAsVar' in postVar: so['ZCoordinateAsVar'] = postVar['ZCoordinateAsVar']
    if 'SecurityHeight' in postVar: so['SecurityHeight'] = postVar['SecurityHeight']
    if 'GopCommandAbsolute' in postVar: so['GopCommandAbsolute'] = postVar['GopCommandAbsolute']
    if 'GopCommandMachine' in postVar: so['GopCommandMachine'] = postVar['GopCommandMachine']
    if 'GopCommandPart' in postVar: so['GopCommandPart'] = postVar['GopCommandPart']
    if 'GopMaxPoints' in postVar: so['GopMaxPoints'] = postVar['GopMaxPoints']
    if 'NoSEPOut' in postVar: so['NoSEPOut'] = postVar['NoSEPOut']
    if 'SEPOutAfterISO' in postVar: so['SEPOutAfterISO'] = postVar['SEPOutAfterISO']
    if 'CurrentDrive' in postVar: so['CurrentDrive'] = postVar['CurrentDrive']
    if 'Drive_A' in postVar: so['Drive_A'] = postVar['Drive_A']
    if 'Drive_B' in postVar: so['Drive_B'] = postVar['Drive_B']
    if 'Drive_DD0' in postVar: so['Drive_DD0'] = postVar['Drive_DD0']
    if 'Drive_DD1' in postVar: so['Drive_DD1'] = postVar['Drive_DD1']
    if 'Drive_DNC' in postVar: so['Drive_DNC'] = postVar['Drive_DNC']
    if 'CopyDataToMemory' in postVar: so['CopyDataToMemory'] = postVar['CopyDataToMemory']
    if 'DeleteDataFromCMD' in postVar: so['DeleteDataFromCMD'] = postVar['DeleteDataFromCMD']

    #joemars
    if 'SetCoordiateSystem' in postVar: so['SetCoordiateSystem'] = postVar['SetCoordiateSystem']
    if 'AutoDWell' in postVar: so['AutoDWell'] = postVar['AutoDWell']

    # mainly ACUniqua
    if 'WPMaterial' in postVar: so['WPMaterial'] = postVar['WPMaterial']            # TO DO : check if it's nonsense
    if 'WireMaterial' in postVar: so['WireMaterial'] = postVar['WireMaterial']      # TO DO : ...
    if 'OutputOPComment' in postVar: so['OutputOPComment'] = postVar['OutputOPComment']     # deactivatetable for schaeffler
    if 'AutomaticTargetName' in postVar: so['AutomaticTargetName'] = postVar['AutomaticTargetName']     # wish schaeffler
    if 'UseUserTechnology' in postVar: so['UseUserTechnology'] = postVar['UseUserTechnology']
    if 'RotaryAxisA' in postVar: so['RotaryAxisA'] = postVar['RotaryAxisA']
    if 'RotaryAxisB' in postVar: so['RotaryAxisB'] = postVar['RotaryAxisB']
    if 'RotaryAxisAOUTPUT' in postVar: so['RotaryAxisAOUTPUT'] = postVar['RotaryAxisAOUTPUT']
    if 'RotaryAxisBOUTPUT' in postVar: so['RotaryAxisBOUTPUT'] = postVar['RotaryAxisBOUTPUT']

    if 'RotaryAxisPositiveAngles' in postVar: so['RotaryAxisPositiveAngles'] = postVar['RotaryAxisPositiveAngles']
    #---------------------------Grouppage 5 ----------------------------
    if 'radioBoxPicture' in postVar: so['radioBoxPicture'] = postVar['radioBoxPicture']
    if 'backgroundColorWhite' in postVar: so['backgroundColorWhite'] = postVar['backgroundColorWhite']
    if 'choiceFile' in postVar: so['choiceFile'] = postVar['choiceFile']
    if 'pageSize' in postVar: so['pageSize'] = postVar['pageSize']
    if 'radioStandardReport' in postVar: so['radioStandardReport'] = postVar['radioStandardReport']
    if 'radioUserReport' in postVar: so['radioUserReport'] = postVar['radioUserReport']
    if 'editReportFile' in postVar: so['editReportFile'] = postVar['editReportFile']
    if 'btnOpenReportFile' in postVar: so['btnOpenReportFile'] = postVar['btnOpenReportFile']
    if 'textReportPath' in postVar: so['textReportPath'] = postVar['textReportPath']
    if 'radioPortraitFormat' in postVar: so['radioPortraitFormat'] = postVar['radioPortraitFormat']
    if 'radioLandscapeFormat' in postVar: so['radioLandscapeFormat'] = postVar['radioLandscapeFormat']
    if 'editLogoFile' in postVar: so['editLogoFile'] = postVar['editLogoFile']
    if 'btnOpenLogoFile' in postVar: so['btnOpenLogoFile'] = postVar['btnOpenLogoFile']
    if 'txtDescription' in postVar: so['txtDescription'] = postVar['txtDescription']
    if 'txtValue' in postVar: so['txtValue'] = postVar['txtValue']
    if 'editDesc1' in postVar: so['editDesc1'] = postVar['editDesc1']
    if 'editVal1' in postVar: so['editVal1'] = postVar['editVal1']
    if 'editDesc2' in postVar: so['editDesc2'] = postVar['editDesc2']
    if 'editVal2' in postVar: so['editVal2'] = postVar['editVal2']
    if 'editDesc3' in postVar: so['editDesc3'] = postVar['editDesc3']
    if 'editVal3' in postVar: so['editVal3'] = postVar['editVal3']
    if 'OutputNcFileNameWithPath' in postVar: so['OutputNcFileNameWithPath'] = postVar['OutputNcFileNameWithPath']
    if 'OutputNcFileNameWithOutPath' in postVar: so['OutputNcFileNameWithOutPath'] = postVar['OutputNcFileNameWithOutPath']
    if 'OutputNcFileNameAndPath' in postVar: so['OutputNcFileNameAndPath'] = postVar['OutputNcFileNameAndPath']
    if 'NCExtraFolder' in postVar: so['NCExtraFolder'] = postVar['NCExtraFolder']
    if 'NCExtraFolderName' in postVar: so['NCExtraFolderName'] = postVar['NCExtraFolderName']
    if 'SetupsheetExtraFolder' in postVar: so['SetupsheetExtraFolder'] = postVar['SetupsheetExtraFolder']
    if 'SetupsheetExtraFolderName' in postVar: so['SetupsheetExtraFolderName'] = postVar['SetupsheetExtraFolderName']
    if 'HideSolids' in postVar: so['HideSolids'] = postVar['HideSolids']
    if 'ShowStartpoint' in postVar: so['ShowStartpoint'] = postVar['ShowStartpoint']
    if 'WhiteBackground' in postVar: so['WhiteBackground'] = postVar['WhiteBackground']
    if 'PrintAfterPp' in postVar: so['PrintAfterPp'] = postVar['PrintAfterPp']
    if 'radioOutModeCut' in postVar: so['radioOutModeCut'] = postVar['radioOutModeCut']
    if 'radioOutModeFeature' in postVar: so['radioOutModeFeature'] = postVar['radioOutModeFeature']
    if 'setupSheetDigitsAfter' in postVar: so['setupSheetDigitsAfter'] = postVar['setupSheetDigitsAfter']

    #---------------------------Grouppage 6 ----------------------------
    if 'editFilename' in postVar: so['editFilename'] = postVar['editFilename']
    if 'editNcDir' in postVar: so['editNcDir'] = postVar['editNcDir']
    if 'btnChooseNcDir' in postVar: so['btnChooseNcDir'] = postVar['btnChooseNcDir']
    if 'editSuffix' in postVar: so['editSuffix'] = postVar['editSuffix']
    if 'checkBlockNo' in postVar: so['checkBlockNo'] = postVar['checkBlockNo']
    if 'editStartNumber' in postVar: so['editStartNumber'] = postVar['editStartNumber']
    if 'editIncrement' in postVar: so['editIncrement'] = postVar['editIncrement']
    if 'txtcrtlHeader' in postVar: so['txtcrtlHeader'] = postVar['txtcrtlHeader']
    if 'txtctrlData' in postVar: so['txtctrlData'] = postVar['txtctrlData']
    if 'txtctrlFooter' in postVar: so['txtctrlFooter'] = postVar['txtctrlFooter']
    if 'choiceVarHeaderChoices' in postVar: so['choiceVarHeaderChoices'] = postVar['choiceVarHeaderChoices']
    if 'choiceVarHeader' in postVar: so['choiceVarHeader'] = postVar['choiceVarHeader']
    if 'choiceVarDataChoices' in postVar: so['choiceVarDataChoices'] = postVar['choiceVarDataChoices']
    if 'choiceVarData' in postVar: so['choiceVarData'] = postVar['choiceVarData']
    if 'choiceVarFooterChoices' in postVar: so['choiceVarFooterChoices'] = postVar['choiceVarFooterChoices']
    if 'choiceVarFooter' in postVar: so['choiceVarFooter'] = postVar['choiceVarFooter']
    if 'editLeadDigit' in postVar: so['editLeadDigit'] = postVar['editLeadDigit']
    if 'editTrailDigit' in postVar: so['editTrailDigit'] = postVar['editTrailDigit']
    if 'choiceDecSep' in postVar: so['choiceDecSep'] = postVar['choiceDecSep']
    if 'radioLeadZero' in postVar: so['radioLeadZero'] = postVar['radioLeadZero']
    if 'radioTrailZero' in postVar: so['radioTrailZero'] = postVar['radioTrailZero']
    if 'radioAlgeSign' in postVar: so['radioAlgeSign'] = postVar['radioAlgeSign']
    #
    return(so)

def saveSettings(modDir, scalings={}):
    logger.info("%s [%s]" % ("postoptionsdlg.saveSettings", modDir))

    (mo, ma, so, sa, ms, md) = updatePostDicts()       # update the dicts used from the postprocessor

    # create the postoptions.py - File
    modName = 'postoptions'
    modPath = modDir + os.sep + modName + '.py'      # abs. path name
    savePythonDictionaries(modPath, logger, sort=True, scalings=scalings, MainOptions=mo, MainAddresses=ma, SubsOptions=so, SubsAddresses=sa, postVar=postVar, ModelSettings=ms, Models=md)
    

def loadSettings(modDir, mode=0x3):
    # ...a little experimental yet; mode: bit 1 is 'postsettings', bit 2 is 'postoptions'
    logger.info("%s [%s]" % ("postoptionsdlg.loadSettings", modDir))

#    from p2c.postvar import loadXML
#    load from xml file
#    postVar = loadXML(modDir, postVar)
#    return

    #---------------------------------------------------------------------------------------------------
    # Import and update the (_modified) dictionaries from postsettings.py and postoptions.py
    ret1 = ret2 = 0
    if mode & LOADSETTINGS:
        modName = 'postsettings'    # modName is the filename without the .py/.pyc extention
        modPath = modDir + os.sep + modName + '.py'      # abs. path name
        ret1 = updateDictionaries(modName, modPath, logger, MainOptions=MainOptions, MainAddresses=MainAddresses, SubsOptions=SubsOptions, SubsAddresses=SubsAddresses, Models=Models, ModelSettings=ModelSettings, AddParamsDepend=AddParamsDepend, COMMON=COMMON, XmlAddresses=XmlAddresses, ISOOptions=ISOOptions, LastUsedProfiles=LastUsedProfiles)
        updateFromCommon(ModelSettings, COMMON, 'GENERAL') #Update the ModelSettings with the Common['GENERAL'] Settings (if defined)
    if mode & LOADOPTIONS:
        global postVar, postModel, postProfile
        postVar['LoadOptions'] = False
        SubsOptions['LoadOptions'] = False
        modName = 'postoptions'
        modPath = modDir + os.sep + modName + '.py'      # abs. path name
        # DEACTIVATED (since 2021/06/11 because getting problems by reading the (possibly) old states of MainAddresses, SubsAddresses
        #ret2 = updateDictionaries(modName, modPath, logger, MainOptions=MainOptions, MainAddresses=MainAddresses, SubsOptions=SubsOptions, SubsAddresses=SubsAddresses, Models=Models, postVar=postVar, ModelSettings=ModelSettings, AddParamsDepend=AddParamsDepend, XmlAddresses=XmlAddresses)
        machine   = getCurrentDoc().GetMachine()    # current machine
        # test to deactivate much more
        pp_name = machine.Name.getPyString()
        if pp_name in ["acvision"]:
            ret2 = updateDictionaries(modName, modPath, logger, Models=Models, postVar=postVar, ModelSettings=ModelSettings, AddParamsDepend=AddParamsDepend, XmlAddresses=XmlAddresses)
        else:
            ret2 = updateDictionaries(modName, modPath, logger, postVar=postVar, ModelSettings=ModelSettings, AddParamsDepend=AddParamsDepend, XmlAddresses=XmlAddresses)
        if ret2:
            SubsOptions['LoadOptions'] = True
            postVar['LoadOptions'] = True
        
        postModel = postVar['MODEL'] = machine.GetModelObject().Name
        postProfile = machine.GetProfileName().getPyString()    # it seems there comes never the selected profile name, even not it was is explicitely stored
        #postProfile = postVar.get('PROFILE', machine.GetProfileName().getPyString())
        '''# Not needed anymore, we dont have a model selection anymore
        postVar['MODELLIST'] = ModelSettings.keys()
        if len(postVar['MODELLIST']) > 0:
            postVar['MODELLIST'].sort()     # an alphabetical order later in the combobox looks nicer
            # if there is no selected Model -> take simply the first one
            if 'MODEL' not in postVar:
                postVar['MODEL'] = postVar['MODELLIST'][0]
            elif postVar['MODEL'] not in postVar['MODELLIST']:
                postVar['MODEL'] = postVar['MODELLIST'][0]
        postModel = postVar['MODEL']
        '''
        #
        # For ACCutX00 and ACCutexx0 look for models set in the registry (not sure if this must be done for accutuniqua also)
        # -> in this case the edm software of the manufactorer has to be installed
        #
        if machine.Name.getPyString() in ('accutx00', 'accutexx0'):     # PROBABLY NOT 'accutuniqua'  : TO CHECK IF THIS IS CORRECT
            # read models from registry (e.g. 'HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\AgieCharmilles\EDMExpert\TCT' )
            nModels = machine.GetModelSize()
            if nModels > 0:
                modellist_from_registry = []
                for m in range(nModels):            # 4
                    mName = machine.GetModelObjectAt(m).Name       # 'Cut 350', 'Cut C600', 'Cut E350'
                    modellist_from_registry.append(mName)
                    if mName not in list(Models.keys()):          # if this model is not already in the postsettings models dict -> add it
                        logger.info("Adding model %s got from main-module!" % mName)
                        last_entry = list(Models.keys())[-1]
                        Models[mName] = dict( Models[last_entry] )          # ...and take initial values from the last model in list (problem to solve: the name inside this sub-dict doesn't fit)
                    if mName not in list(ModelSettings.keys()):   # probably it's not there too!
                        last_entry = list(ModelSettings.keys())[-1]
                        ModelSettings[mName] = dict( ModelSettings[last_entry] )
                # delete models from the postsettings models dict if they are not in the list (got from main-module)
                keyList = list(Models.keys())
                for key in keyList:
                    if key not in modellist_from_registry:
                        logger.info("Deleting model %s (not in list from main-module!" % key)
                        del Models[key]
                        del ModelSettings[key]
                del keyList

        GetTravelLimits(postVar)
    #---------------------------------------------------------------------------------------------------
    return (ret1, ret2)

def UpdatePostSettings():
    """
    Invoked to pass the current PostSettings to Opticam-C++.
    1. Is called on UpdatePostEx Postprocessor called from main system.
    """
    taperMax = None
    if len(pepsVar) > 0:
        logger.info("READING %d VARIABLES FROM PEPS" % len(pepsVar))
        for key,value in list(pepsVar.items()):
            logger.info('........%s = %s' % (key,value))

        # take the peps values
        if '$_machine_model'  in pepsVar and pepsVar['$_machine_model'] != "" and pepsVar['$_machine_model'] in Models:
            MainOptions['MODEL'] = pepsVar['$_machine_model']
            #del (pepsVar['$_machine_model'])

        if 'w_MAXWIREANGLEMC' in pepsVar:
            if pepsVar['w_MAXWIREANGLEMC'] < SMALL_ANGLE_DEG or pepsVar['w_MAXWIREANGLEMC'] > MAX_ANGLE_DEG:
                logger.info("MAXWIREANGLE %.3f out of range [%.3f-%.3f]" % (pepsVar['w_MAXWIREANGLEMC'], SMALL_ANGLE_DEG, MAX_ANGLE_DEG))
            else:
                taperMax = pepsVar['w_MAXWIREANGLEMC']    
    #
    if taperMax is not None:
        logger.info("MAXWIREANGLE %.3f actualized for Postmodel %s" % (taperMax, postModel))
        postVar['TaperMax'] = taperMax
        Models[postModel]['TaperMax'] = taperMax

    updatePostDicts()
    
    # 2.BlendFunction:
    if 'UseXYROutput' in postVar:
        # Blend for accut, accutex, fanuc, joemars, mseibu, sodick, onaaf, acmillennium is controllable in PP-Options ('UseXYROutput')
        if postVar['UseXYROutput'] == True:
            MainOptions['BlendFunction'] = MainOptions.get('BlendAbilityy', 1)     # if posssible, reset to original value
        else:
            MainOptions['BlendFunction'] = 0
    # 3.Fouraxis mode:
    if 'IndependentTopBottom' in postVar:
        if postVar['IndependentTopBottom'] == True:
            SubsOptions['UVOption'] = MainOptions['UVOption'] = postVar['UVOption']
            if 'DoubleBlock' in MainOptions:
                MainOptions['DoubleBlock'] = (True, MainOptions['DoubleBlock'][1])
        else:
            SubsOptions['UVOption'] = MainOptions['UVOption'] = 1     # Line/Line (vectorized)
            if 'DoubleBlock' in MainOptions:
                MainOptions['DoubleBlock'] = (False, MainOptions['DoubleBlock'][1])
    
    if "SetupSheetUseTemplate" in postVar:
        MainOptions['SetupSheetUseTemplate'] = postVar['SetupSheetUseTemplate']
    
    if "editSetupsheetTemplateFile" in postVar:
        MainOptions['editSetupsheetTemplateFile'] = postVar['editSetupsheetTemplateFile']
    
    if "SetupSheetCompactUseTemplate" in postVar:
        MainOptions['SetupSheetCompactUseTemplate'] = postVar['SetupSheetCompactUseTemplate']
        
    if "editSetupsheetTemplateFile" in postVar:
        MainOptions['editSetupsheetCompactTemplateFile'] = postVar['editSetupsheetCompactTemplateFile']

    # build string for displaying the 'Workplanes Default'
    (key, number) = MainOptions.get('From', ('G', 92))
    prep = MainAddresses.get(key, ( 0, 'G'))[1]
    MainOptions['WorkplaneDefault'] = prep + (str(number) if number > 0 else '')
    # Get machine
    mac = getCurrentDoc().GetMachine()
    if mac is not None:
        mac.SetPPSettings( MainOptions )

def UpdatePostDicts(setModel=True):
    """
    Invoked to pass the updated dicts to Opticam-C++.
    1. Is called on Init Postprocessor (for passing postprocessor-settings to Opticam)
    2. Is called when leaving PP-OptionsDlg with OK (passes possibly changed settings to Opticam)
    """
    # Check if we have dict entries exported from peps
    #machine = None
    taperMax = None
    if len(pepsVar) > 0:
        logger.info("READING %d VARIABLES FROM PEPS" % len(pepsVar))
        for key,value in list(pepsVar.items()):
            logger.info('........%s = %s' % (key,value))

        # take the peps values
        if '$_machine_model'  in pepsVar and pepsVar['$_machine_model'] != "" and pepsVar['$_machine_model'] in Models:
            MainOptions['MODEL'] = pepsVar['$_machine_model']
            #del (pepsVar['$_machine_model'])

        if 'w_MAXWIREANGLEMC' in pepsVar:
            if pepsVar['w_MAXWIREANGLEMC'] < SMALL_ANGLE_DEG or pepsVar['w_MAXWIREANGLEMC'] > MAX_ANGLE_DEG:
                logger.info("MAXWIREANGLE %.3f out of range [%.3f-%.3f]" % (pepsVar['w_MAXWIREANGLEMC'], SMALL_ANGLE_DEG, MAX_ANGLE_DEG))
            else:
                taperMax = pepsVar['w_MAXWIREANGLEMC']    
    #
    if taperMax is not None:
        logger.info("MAXWIREANGLE %.3f actualized for Postmodel %s" % (taperMax, postModel))
        postVar['TaperMax'] = taperMax
        Models[postModel]['TaperMax'] = taperMax

    # Actualize some important settings for toolpath-calculation
    # 1.Read act. settings from pp-options-settings
    updatePostDicts()
    
    # 2.BlendFunction:
    if 'UseXYROutput' in postVar:
        # Blend for accut, accutex, fanuc, joemars, mseibu, sodick, onaaf, acmillennium is controllable in PP-Options ('UseXYROutput')
        if postVar['UseXYROutput'] == True:
            MainOptions['BlendFunction'] = MainOptions.get('BlendAbilityy', 1)     # if posssible, reset to original value
        else:
            MainOptions['BlendFunction'] = 0
    # 3.Fouraxis mode:
    if 'IndependentTopBottom' in postVar:
        if postVar['IndependentTopBottom'] == True:
            SubsOptions['UVOption'] = MainOptions['UVOption'] = postVar['UVOption']
            if 'DoubleBlock' in MainOptions:
                MainOptions['DoubleBlock'] = (True, MainOptions['DoubleBlock'][1])
        else:
            SubsOptions['UVOption'] = MainOptions['UVOption'] = 1     # Line/Line (vectorized)
            if 'DoubleBlock' in MainOptions:
                MainOptions['DoubleBlock'] = (False, MainOptions['DoubleBlock'][1])
    
    if "SetupSheetUseTemplate" in postVar:
        MainOptions['SetupSheetUseTemplate'] = postVar['SetupSheetUseTemplate']
    
    if "editSetupsheetTemplateFile" in postVar:
        MainOptions['editSetupsheetTemplateFile'] = postVar['editSetupsheetTemplateFile']
    
    if "SetupSheetCompactUseTemplate" in postVar:
        MainOptions['SetupSheetCompactUseTemplate'] = postVar['SetupSheetCompactUseTemplate']
    
    if "editSetupsheetTemplateFile" in postVar:
        MainOptions['editSetupsheetCompactTemplateFile'] = postVar['editSetupsheetCompactTemplateFile']

    # Update C++ from Python
    
    # build string for displaying the 'Workplanes Default'
    (key, number) = MainOptions.get('From', ('G', 92))
    prep = MainAddresses.get(key, ( 0, 'G'))[1]
    MainOptions['WorkplaneDefault'] = prep + (str(number) if number > 0 else '')
    
    getCurrentDoc().ReadDict('MainOptions', MainOptions)
    getCurrentDoc().ReadDict('SubOptions',  SubsOptions)
    #
    if setModel == True:
        getCurrentDoc().ReadDict('Models',      Models)
        UpdateModel( getCurrentDoc().GetMachine().GetModelObject().Name )
        
    if MainOptions.get('DocFullName', "") == "":
        SubsOptions['DocFullName'] = MainOptions['DocFullName'] = getCurrentDoc().GetDocFullNameW()    

    # Starthole options
    #Starthole_Options['editFilename']       # this have to be actualized
    #Starthole_Options['editSuffix']
    #getCurrentDoc().ReadDict('Starthole_Options', Starthole_Options)
    
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

# the FoldPanel Stuff (GroupPanel)

class BaseGroupPanel(BaseGroupPanel):
    '''Represents a sub-window with several pages.'''     # can be accessed via __doc__

    def createGroup1(self):
        # Generell
        itemSizer = wx.BoxSizer( wx.VERTICAL )
        c = self.IsCollapsed("1")
        item = self.AddFoldPanel("General", collapsed=c, foldIcons=self.Images, itemname="_FPL_ITEM1", captionname="CPT_BAR1")
        item.SetSizer(itemSizer)
        itemSizer.Add(item._captionBar, 0, wx.EXPAND)
        page = GroupPage1(item, wx.ID_ANY)
        itemSizer.Add(page, 0, wx.EXPAND)
        if c:
            self.collapsedPagesSize.append(itemSizer.CalcMin())
        else:
            self.openPagesSize.append(itemSizer.CalcMin())
        itemSizer.Show(page, show=not c, recursive=False)
        self.AddFoldPanelWindow(item, page)
        self._foldPanel.GetSizer().Add(item, 0, wx.EXPAND)

    def createGroup2(self):
        # NC-Ausgabe Optionen
        itemSizer = wx.BoxSizer( wx.VERTICAL )
        c = self.IsCollapsed("2")
        item = self.AddFoldPanel("NC output", collapsed=c, foldIcons=self.Images, itemname="_FPL_ITEM2", captionname="CPT_BAR2")
        item.SetSizer(itemSizer)
        itemSizer.Add(item._captionBar, 0, wx.EXPAND)
        page = GroupPage2(item, wx.ID_ANY)
        itemSizer.Add(page, 0, wx.EXPAND)
        if c:
            self.collapsedPagesSize.append(itemSizer.CalcMin())
        else:
            self.openPagesSize.append(itemSizer.CalcMin())
        itemSizer.Show(page, show=not c, recursive=False)
        self.AddFoldPanelWindow(item, page)
        self._foldPanel.GetSizer().Add(item, 0, wx.EXPAND)

    def createGroup3(self):
        # Simulation
        itemSizer = wx.BoxSizer( wx.VERTICAL )
        c = self.IsCollapsed("3")
        item = self.AddFoldPanel("Simulation", collapsed=c, foldIcons=self.Images, itemname="_FPL_ITEM3", captionname="CPT_BAR3")
        item.SetSizer(itemSizer)
        itemSizer.Add(item._captionBar, 0, wx.EXPAND)
        page = GroupPage3(item, wx.ID_ANY)
        itemSizer.Add(page, 0, wx.EXPAND)
        if c:
            self.collapsedPagesSize.append(itemSizer.CalcMin())
        else:
            self.openPagesSize.append(itemSizer.CalcMin())
        itemSizer.Show(page, show=not c, recursive=False)
        self.AddFoldPanelWindow(item, page)
        self._foldPanel.GetSizer().Add(item, 0, wx.EXPAND)

    def createGroup4(self):
        # implement additional pages in the derived classes
        # -> create a new one or overwrite there
#         itemSizer = wx.BoxSizer( wx.VERTICAL )
#         c = self.IsCollapsed("4")
#         item = self.AddFoldPanel("MyWidget", collapsed=c, foldIcons=self.Images, itemname="_FPL_ITEM4", captionname="CPT_BAR4")
#         item.SetSizer(itemSizer)
#         itemSizer.Add(item._captionBar, 0, wx.EXPAND)
#         page = GroupPage4(item, wx.ID_ANY)
#         itemSizer.Add(page, 0, wx.EXPAND)
#         minsize = itemSizer.CalcMin()
#         itemSizer.Show(page, show=not c, recursive=False)
#         self.AddFoldPanelWindow(item, page)
#         self._foldPanel.GetSizer().Add(item, 0, wx.EXPAND)
#         return minsize
        pass

    def createGroup5(self):
        # Setupsheet
        itemSizer = wx.BoxSizer( wx.VERTICAL )
        c = self.IsCollapsed("5")
        item = self.AddFoldPanel("Setupsheet", collapsed=c, foldIcons=self.Images, itemname="_FPL_ITEM5", captionname="CPT_BAR5")
        item.SetSizer(itemSizer)
        itemSizer.Add(item._captionBar, 0, wx.EXPAND)
        page = GroupPage5(item, wx.ID_ANY)
        itemSizer.Add(page, 0, wx.EXPAND)
        if c:
            self.collapsedPagesSize.append(itemSizer.CalcMin())
        else:
            self.openPagesSize.append(itemSizer.CalcMin())
        itemSizer.Show(page, show=not c, recursive=False)
        self.AddFoldPanelWindow(item, page)
        self._foldPanel.GetSizer().Add(item, 0, wx.EXPAND)

        
class BaseGroupPage(BasePanel):
    '''
    Baseclass of a page of the GroupPanel.
    We are derived from a BasePanel -> so we have all properties of a panel
    '''     # can be accessed via __doc__
    def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize,  # @ReservedAssignment
                 style=wx.NO_BORDER | wx.TAB_TRAVERSAL, name=wx.PanelNameStr):
        BasePanel.__init__(self, parent, id, pos, size, style, name)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)

        self.doc = getCurrentDoc()
        self.mac = self.doc.GetMachine()

#        self.Fit() -> must be done in the derived class (at the end, when all placement was done e.g. -> CreateControls)

    def listControls(self, parent):
        """ Lists all widgets of the parent-panel."""
        for child in parent.GetChildren():
            if not self.listControls(child):
                return False
        if parent.Name in postVar or True:    # show us all
            pass
            #txt = "(enabled)" if parent.IsEnabled() == True else "(disabled)"
            # print self.__class__.__name__, "\t-->\t", parent.__class__.__name__ + "\t : " + parent.Name + "\tId ", parent.GetId(), "\t", txt
        return True
    
    def setPanelMaster(self, Item, panelMasterList=[], subMasterList=[], excludeList=[]): 
        '''
        This function sets masters for the given wx.Panel, so that all panel widgets can be enabled/disabled by them.
        Input:
        [Item] --> BaseGroupPanel (or different wx.Item) where the masters and slaves are contained.
        [panelMasterList] --> List of predefined masters for this Panel.
        [subMasterList] --> List of predefined sub-masters for this Panel which are independent of the panel masters.
        [excludeList] --> List of additional widgets that shall be excluded.
        Output: 
        [WDGNameList] --> An Item-List of the Group Page Widgets excluding the given Panel-Master and the slaves of the sub-masters.
        [WDGItemList] --> A Name-List of the Group Page Widgets excluding the given Panel-Master and the slaves of the sub-masters.
        '''       
        STBList = list() #Variable not returned currently
        WDGNameList = list()
        WDGItemList = list()
        slaveList_nest = list()
        slaveList_flat = list()
        
        #Get all Children of the given wx.Item
        children = Item.Children
        
        for child in children:
            #Get 'name' of the child item
            name = child.Name           
            #Check if child item is a widget (Button, Check Box, etc.) or ...
            if child.ClassName != 'wxStaticBox':
                #Check if is in the given sub-master list
                if name in subMasterList:
                    #List slaves of the given sub-masters
                    slaveList_nest.append(self.FindWindowByName(name).slaveList)
                    slaveList_flat = sum(slaveList_nest, [])  
                #Check if widget is contained in panel-masters, sub-master slaves or optional exclude list and exclude them from the widget list    
                if name not in set().union(panelMasterList, slaveList_flat, excludeList):
                    WDGNameList.append(name)
                    WDGItemList.append(child)
            # ... a sizer (StaticBox, ...)
            else:
                STBList.append(name) #Variable not returned currently
                pass   

        return WDGNameList, WDGItemList
    
    def getCBStatus(self, cbList=[]):
        '''
        This function returns a list of the status of the given Check Boxes (True or False)
        Input:
        [cbList] --> List of Check boxes to be checked for status    
        Output: 
        [cbStsList] --> A status list of the given Check Boxes
        '''
        cbStsList = []
        #Get the Status of each defined master widget                        
        for cb in cbList:
            
            cbStsList.append(self.FindWindowByName(cb).IsChecked())
            
        return cbStsList

    def getControlsId(self):
        cl = list()  # new list
        for child in self.GetChildren():
            cl.append(child.GetId())
        return cl

    def enablePage(self):
        pass        # if needed, implement method in derived class

    def enableWidget(self, wdgName, masterNameList, modelSet=None, invert=False, invertDisable=False):
        """ Enables/disables a widget depending on the model selected and the value of masterWidgets."""
        widget = self.FindWindowByName(wdgName)     # search for the widget to enable/disable

        if widget is not None:
            enabled = True
            if modelSet is not None:
                if wdgName in modelSet:
                    enabled = bool( modelSet[wdgName][0] )
#                   value   = modelSet[wdgName][1]      # not used in this function
            if enabled == True and masterNameList is not None:  # if we have widgets on which we depend (in a list)
                for masterName in masterNameList:
                    wdg = self.FindWindowByName(masterName)
                    if wdg is not None:
                        enabled = invert ^ bool( wdg.GetValue() )
                        if enabled == False:
                            break
            widget.Enable(enabled)
            # if we disable a checkbox than it's nicer if we also uncheck it 
            # if enabled == False and isinstance(widget, wx.CheckBox):
            #     if invertDisable==False:
            #         widget.SetValue(False)
            #     else:
            #         widget.SetValue(True)
            #

            # if we disable a text field than it's nicer if we also clear its content 
            # if enabled == False and isinstance(widget, wx.TextCtrl):
            #     if invertDisable==False:
            #         widget.SetValue('')
            #     else:
            #         pass

    def enableControls(self, idList, enable):
        """ Enables or disables the child-widgets of this panel which are in the ID-list. """
        for child in self.GetChildren():    # all widgets of this panel
            cid = child.GetId()
            if cid in idList:    # is this one in the list?
                child.Enable(enable)        # ... then set it's state (enabled/disabled)
            elif -cid in idList:   # if widget is with neg. index in the list -> toggle it
                child.Enable(not enable)
#       some more ways to identify a widget
#        for id in list:
#            widget = self.FindWindowById(id)
#            widget = self.FindWindowByLabel(label)
#            widget = self.FindWindowByName(name)

    def OnMODELChanged(self, event):
        pass
    
    def UpdateDatabaseFields(self, ProfileName=None):
        #Dummy function, overwrite this in optionsdlg
        pass    

    def SelectUserDefinedHeader(self, event):
        self.SelectUserDefinedStuff(event, self.FindWindowByName('UserDefinedHeaderField'), 'User_NC_header.txt')

    def SelectUserDefinedFooter(self, event):
        self.SelectUserDefinedStuff(event, self.FindWindowByName('UserDefinedFooterField'), 'User_NC_footer.txt')

    def SelectUserDefinedStuff(self, event, headerField, defaultFile):
        if headerField is None:
            return

        s1 = self.mac.Name
        if headerField.GetValue():
            defaultDir  = os.path.dirname( headerField.GetValue() )
            defaultFile = os.path.basename( headerField.GetValue() )
            if os.path.isdir(defaultDir) == False:
                defaultDir = opticam.getPath('Post') +'\\' + s1.getPyString() + '\\data'
                if os.path.isdir(defaultDir) == False:
                    os.makedirs(defaultDir)
        else:
            defaultDir = opticam.getPath('Post') +'\\' + s1.getPyString() + '\\data'
            if os.path.isdir(defaultDir) == False:
                os.makedirs(defaultDir)

        evtObjName  = event.GetEventObject().GetName()
        wildcard = "(*.txt)|*.txt|" \
            "All files (*.*)|*.*"
        dlg = wx.FileDialog(self, message=evtObjName + " File",
                            defaultDir=defaultDir,
                            #defaultFile=postVar['UserDefinedHeaderField']
                            #defaultFile=wx.EmptyString,
                            defaultFile=defaultFile,
                            wildcard=wildcard,
                            style=wx.FD_OPEN
                            )
        # Show the dialog and retrieve the user response. If it is the OK response, process the data.
        #
        if dlg.ShowModal() == wx.ID_OK:
            HeaderField = dlg.GetPath()
            headerField.SetValue(HeaderField)

            if _DEBUG:
                local_dir  = dlg.GetDirectory()
                file_name = dlg.GetFilename()   
                if logger: logger.info("You selected directory: %s" %  local_dir )
                if logger: logger.info("You selected file: %s" %  file_name )
                if logger: logger.info("You selected path: %s" %  dlg.GetPath() )   
        else:
            HeaderField = headerField.GetValue()
            return


        if HeaderField:
            if os.path.isfile(HeaderField) == False:
                with open(HeaderField, 'w') as HeaderFile:
                    opticamVars = iso.opticamVars
                    if not opticamVars:
                        opticamVars = OpticamVariables(options=MainOptions)  # @UndefinedVariable
                    HeaderFile.write("""'**********************************************************************************
'***Lines beginning like this are comments and will not be written in nc file.
'***To inhibit line numbering on the header, prefix each line with a < symbol.
'***List of variables:\n""")
                    for key,val in list(opticamVars.items()):
                        keyItem = "%s%s%s" % ("%", key, "%")
                        HeaderFile.write("""'***%-25s(%s)\n""" % (keyItem, val))
                    HeaderFile.write("""'**********************************************************************************\n""")
            try:
                os.system("Start Notepad " + HeaderField)
            except:
                pass

    def ImportTechnology(self, event):  # @UnusedVariable
        if _DEBUG:
            logger.info("%s%s" % (self.__class__.__name__ , ".OnImportTechnologyButton"))
        ret = getCurrentDoc().GetMachine().DBImportStart()
        if _DEBUG:
            logger.info("%s%s" % ("...Import Module Return Value: " , ret))
        #

    def enableOnce(self):
        pass
    
    def OnAutomaticThreadingChanged(self, event):  # @UnusedVariable
        self.enablePage(clearStatusBar=False)

    def AutomaticThreadingChanged(self, clearStatusBar=False):
#        wdg = event.GetEventObject()
#        postVar['AutomaticThreading'] = wdg.GetValue()
        topWin = self.GetTopLevelParent()      # find most top window (here we expect the statusbar)
        if topWin and hasattr(topWin, "SetStatusBarText"):  
            if clearStatusBar:
                topWin.HideStatusbar()
                return           
            v1 = self.AutomaticThreading.GetValue()
            v2 = self.NoThreadingOutput.GetValue()
            logger.info("AutomaticThreadingChanged (enabled=%s)" % v1)
            if v1 == False and v2 == True:
                msg1 = getMessageW("Warning", PYTHON_MESSAGES, 495)
                msg2 = getMessageW("This Settings deactivates Output of Wire-Thread/Cut completely!", PYTHON_MESSAGES, 496)
                #Warning Dialog
                wnd1 = wx.Window.FindFocus()
                opticam.P2CMessageBoxW(msg1 + " !!\n" + msg2)      # this widget stealth the focus
                if wnd1 and hasattr(wnd1, "SetFocus"):
                    wnd2 = wx.Window.FindFocus()
                    if wnd1 != wnd2:
                        wnd1.SetFocus()                             # put focus back
                #
                topWin.ShowStatusbar()
                #stb.Show()
                topWin.SetStatusBarText([msg1, msg2], ["red"])
            else:
                #topWin.SetStatusBarText()
                topWin.HideStatusbar()
            #
    def AdvancedTaperMode(self, parentSizer=None):
        if postVar.get('AdvancedTaper') is not None:
            subSizer = wx.StaticBoxSizer( StaticBox( self, wx.ID_ANY, "Advanced taper mode", name='STB_ADVANCED_TAPER_MODE' ), wx.VERTICAL )
            if parentSizer:
                parentSizer.Add( subSizer, 0, wx.EXPAND, SMALLBORDER )
            
            labelList = ["Variable taper ability"]
            toolTipList = ["Variable taper ability - If disabled, we get four axis-output"]
            mcb1 = OptiMultiCheckBox( self, wx.ID_ANY, labelList, toolTipList, name='AdvancedTaper' )
            subSizer.Add( mcb1, 0, wx.ALL, SMALLBORDER )
            return subSizer

    def StopModes(self, parentSizer=None):
        if 'Stop1Mode' in postVar or 'Stop2Mode' in postVar or 'StopAsComment' in postVar:
            subSizer = wx.StaticBoxSizer( StaticBox( self, wx.ID_ANY, "Stop modes", name='STB_STOP_MODES' ), wx.VERTICAL )
            if parentSizer:
                parentSizer.Add( subSizer, 0, wx.EXPAND, SMALLBORDER )
            
            if 'Stop1Mode' in postVar:
                self.Stop1Mode = LabeledComboBox(self, wx.ID_ANY, label='First stop', name='Stop1Mode', toolTipString="", propChoice=1)
                self.Stop1Mode.SetToolTipString("")
                subSizer.Add(self.Stop1Mode, 0, wx.ALL, SMALLBORDER)
            if 'Stop2Mode' in postVar:
                self.Stop2Mode = LabeledComboBox(self, wx.ID_ANY, label='Second stop', name='Stop2Mode', toolTipString="", propChoice=1)
                self.Stop2Mode.SetToolTipString("")
                subSizer.Add(self.Stop2Mode, 0, wx.ALL, SMALLBORDER)
            if 'StopAsComment' in postVar:
                self.StopAsComment = OptiCheckBox(self, wx.ID_ANY, label='Stop as comment', name='StopAsComment')
                self.StopAsComment.SetToolTipString("")
                subSizer.Add(self.StopAsComment, 0, wx.ALL, SMALLBORDER)
            return subSizer

    def OriginChange(self, parentSizer=None, enabled=True):
        if 'IsoForEachOrigin' in postVar and False:     ### Meeting 2021/06/16 we decided that this goes away -> Instead we implement a new CheckBox in first PP-Options page like : 'Use rotary axis'
            #subSizer = wx.StaticBoxSizer( StaticBox( self, wx.ID_ANY, "Origin operation mode", name='STB_ORIGIN_MOD' ), wx.VERTICAL )
#             stBox = StaticBox( self, wx.ID_ANY, "Origin operation mode", name='STB_ORIGIN_MOD' )
#             stBox.Enable(enabled)
#             subSizer = wx.StaticBoxSizer( stBox, wx.VERTICAL )
#             if parentSizer:
#                 parentSizer.Add( subSizer, 0, wx.EXPAND, SMALLBORDER )
#             subSizerH = wx.BoxSizer( wx.HORIZONTAL )
#             
#             self.OriChangeAbilityLabel = TextField( self, wx.ID_ANY, "Machine can rotate axis:", wx.DefaultPosition, wx.DefaultSize, 0, name="MACHINE_AXIS_ABILITY_LBL" )
#             subSizerH.Add( self.OriChangeAbilityLabel, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )
#             self.OriChangeAbilityLabel.Enable(enabled)
# 
#             self.OriChangeAbility = TextField( self, 200, label="--MACHINE AXIS ABILITY--", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.ALIGN_LEFT,  name='CanChangeOrigin')
#             self.OriChangeAbility.SetToolTipString('Ability of machine to rotate axis')
#             self.OriChangeAbility.Enable(enabled)
#             subSizerH.Add( self.OriChangeAbility, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )
#             subSizerH.AddSpacer(MEDIUMBORDER+MEDIUMBORDER+SMALLBORDER+SMALLBORDER+SMALLBORDER+SMALLBORDER+SMALLBORDER)    
#             subSizer.Add(subSizerH)

            self.IsoForEachOrigin = OptiCheckBox( self, wx.ID_ANY, label="Create new ISO if origin changes", name='IsoForEachOrigin' )
            self.IsoForEachOrigin.SetToolTipString("Create for each origin change a new ISO")
            self.IsoForEachOrigin.Enable(enabled)
            if parentSizer:
                parentSizer.Add( self.IsoForEachOrigin, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)       
#             subSizer.Add( self.IsoForEachOrigin, 0, wx.ALL, SMALLBORDER )                
#             return subSizer

    # def RotaryAxis(self, parentSizer=None, enabled=True):
    #     if 'UseRotaryAxis' in postVar:
    #         self.UseRotaryAxis = OptiCheckBox( self, wx.ID_ANY, label="Use rotary axis", name='UseRotaryAxis' )
    #         self.UseRotaryAxis.SetToolTipString("Use rotary axis")
    #         self.UseRotaryAxis.Enable(enabled)
    #         if parentSizer:
    #             parentSizer.Add( self.UseRotaryAxis, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)       
            

    def RuledSurfaceOutput(self, parentSizer=None):
        if postVar.get('IndependentTopBottom') is not None: 
            subSizer = wx.StaticBoxSizer( StaticBox( self, wx.ID_ANY, "Ruled surface output", name='STB_RULED_SURFACE_OUTPUT' ), wx.VERTICAL )
            if parentSizer:
                parentSizer.Add( subSizer, 0, wx.EXPAND, SMALLBORDER )
            
            rb1 = OptiRadioButton(self, wx.ID_ANY, label="U/V output", style=wx.RB_GROUP, name='IndependentTopBottomUV')
            rb1.SetToolTipString("Split lines and arcs")
            rb1.Bind(wx.EVT_RADIOBUTTON, self.OnRuledSurfaceRadioButtonClicked)
            subSizer.Add(rb1, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            
            if postVar.get('ARBITRARY_UD') is not None: 
                cb1 = OptiCheckBox( self, wx.ID_ANY, label="Arbitrary mode", name='ARBITRARY_UD' )
                cb1.SetToolTipString("Set ARBITRARY mode (on=Mitsubishi | off=Fanuc vectorized)")
                subSizer.Add(cb1, 0, wx.LEFT, SMALLBORDER+20)        

            rb2 = OptiRadioButton(self, wx.ID_ANY, label="Two independent geometries", name='IndependentTopBottom')
            rb2.SetToolTipString("Double block output (lower- and upper geometry in same block)")
            rb2.Bind(wx.EVT_RADIOBUTTON, self.OnRuledSurfaceRadioButtonClicked)
            subSizer.Add(rb2, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            labelList = ["Line-Line", 
                         "Arc-Arc",
                         "Arc-Arc (same direction)",
                         "Arc-Line"]
            toolTipList = ["Line-Line Ability",
                           "Arc-Arc Ability",
                           "Arc-Arc (same Direction) Ability",
                           "Arc-Line Ability"]
            mcb1 = OptiMultiCheckBox( self, wx.ID_ANY, labelList, toolTipList, name='UVOption' )
            subSizer.Add( mcb1, 1, wx.EXPAND|wx.ALL, SMALLBORDER )
            return subSizer
        
    def OnRuledSurfaceRadioButtonClicked(self, event):  # @UnusedVariable
        modelSet = GetModelSetting()
        self.enableWidget('ARBITRARY_UD', ['IndependentTopBottomUV'], modelSet)
        self.enableWidget('UVOption',     ['IndependentTopBottom'], modelSet)

    def G92Output(self, parentSizer=None):
        if postVar.get('OutputOrigin') is not None: 
            #subSizer = wx.StaticBoxSizer( StaticBox( self, wx.ID_ANY, "Ruled surface output", name='STB_RULED_SURFACE_OUTPUT' ), wx.VERTICAL )
            subSizer = wx.BoxSizer( wx.VERTICAL )
            if parentSizer:
                parentSizer.Add( subSizer, 0, wx.EXPAND, SMALLBORDER )
            
            cb = OptiCheckBox( self, wx.ID_ANY, label="Output G92", name='OutputOrigin' )
            cb.SetToolTipString("Output G92")
            #cb.setSlaves(['OutputOriginAfterThread', 'OutputOriginBeforeEachCut'])
            subSizer.Add(cb, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            
            pnl = BasePanel(self)

            size = wx.Size(int(300 * ScreenScaleFactor), int(15 * ScreenScaleFactor))
            xStart = MEDIUMBORDER
            yStart = 0
            xInc   = 0
            yInc   = MEDIUMBORDER            

            if postVar.get('OutputOriginBeforeThread') is not None:
                rb1 = OptiRadioButton(pnl, wx.ID_ANY, label=u"G92 before wire threading", style = wx.RB_GROUP, pos=(xStart, yStart), size=size, name='OutputOriginBeforeThread')
                rb1.SetToolTipString("?")
                cb.addSlave(rb1.Name)
                xStart += xInc
                yStart += yInc

    
            if postVar.get('OutputOriginAfterThread') is not None:
                rb2 = OptiRadioButton(pnl, wx.ID_ANY, label=u"G92 after wire threading", pos=(xStart, yStart), size=size, name='OutputOriginAfterThread')
                rb2.SetToolTipString("?")
                cb.addSlave(rb2.Name)
                xStart += xInc
                yStart += yInc
    
            if postVar.get('OutputOriginBeforeGeneratorCall') is not None:
                rb3 = OptiRadioButton(pnl, wx.ID_ANY, label="G92 before generator output", pos=(xStart, yStart), size=size, name='OutputOriginBeforeGeneratorCall')
                rb3.SetToolTipString("?")
                cb.addSlave(rb3.Name)
                xStart += xInc
                yStart += yInc

            if postVar.get('OutputOriginBeforeEachCut') is not None:
                rb4 = OptiRadioButton(pnl, wx.ID_ANY, label="G92 before each cut", pos=(xStart, yStart), size=size, name='OutputOriginBeforeEachCut')
                rb4.SetToolTipString("?")
                cb.addSlave(rb4.Name)
                xStart += xInc
                yStart += yInc

            if postVar.get('OutputG90AfterG92') is not None:
                cb9 = OptiCheckBox(pnl, wx.ID_ANY, label="G92 and G90", pos=(xStart, yStart), size=size, name='OutputG90AfterG92')
                cb9.SetToolTipString("?")
                cb.addSlave(cb9.Name)
                xStart += xInc
                yStart += yInc

            subSizer.Add( pnl, 1, wx.EXPAND|wx.ALL, SMALLBORDER )

            return subSizer
        else:
            if postVar.get('OutputOriginBeforeThread') is not None:
                #rb11 = OptiRadioButton(self, wx.ID_ANY, label=u"G92 before wire threading", style = wx.RB_GROUP, name='OutputOriginBeforeThread')
                rb11 = OptiCheckBox(self, wx.ID_ANY, label="G92 before wire threading", name='OutputOriginBeforeThread')
                rb11.SetToolTipString("?")
                parentSizer.Add(rb11, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            
            if postVar.get('OutputOriginAfterThread') is not None:
                #rb10 = OptiRadioButton(self, wx.ID_ANY, label=u"G92 after wire threading", name='OutputOriginAfterThread')
                rb10 = OptiCheckBox(self, wx.ID_ANY, label="G92 after wire threading", name='OutputOriginAfterThread')
                rb10.SetToolTipString("?")
                parentSizer.Add(rb10, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            
            if postVar.get('OutputOriginBeforeGeneratorCall') is not None:
                cb12 = OptiCheckBox(self, wx.ID_ANY, label="G92 before generator output", name='OutputOriginBeforeGeneratorCall')
                cb12.SetToolTipString("?")
                parentSizer.Add(cb12, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
        
    def SubprogramOutput(self, parentSizer=None):
        if 'SingleNCFile' in postVar or 'SeperateNCFiles' in postVar or 'Subprograms' in postVar:
            subSizer = wx.StaticBoxSizer( StaticBox( self, wx.ID_ANY, "Output Mode", name="STB_OUTMODE") , wx.VERTICAL )
            if parentSizer:
                parentSizer.Add( subSizer, 0, wx.EXPAND, SMALLBORDER )

            if 'SingleNCFile' in postVar:
                self.SingleNCFile = OptiRadioButton(self, wx.ID_ANY, label="Single NC file", style=wx.RB_GROUP, name='SingleNCFile')
                self.SingleNCFile.SetToolTipString("Single NC file")
                subSizer.Add(self.SingleNCFile, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
                self.SingleNCFile.Bind(wx.EVT_RADIOBUTTON, self.OnSubProgramOutChanged)

            if 'SeperateNCFiles' in postVar:
                self.SeperateNCFiles = OptiRadioButton(self, wx.ID_ANY, label="Seperate NC files", name='SeperateNCFiles')
                self.SeperateNCFiles.SetToolTipString("Seperate NC files")
                subSizer.Add(self.SeperateNCFiles, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
                self.SeperateNCFiles.Bind(wx.EVT_RADIOBUTTON, self.OnSubProgramOutChanged)

            if 'Subprograms' in postVar:
                self.cb15 = OptiRadioButton(self, wx.ID_ANY, label="Subprogram output", name='Subprograms')
                self.cb15.SetToolTipString("?")
                subSizer.Add(self.cb15, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
                self.cb15.Bind(wx.EVT_RADIOBUTTON, self.OnSubProgramOutChanged)

                if 'OutputSubRotated' in postVar:
                    subSizer.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
                    self.cb16 = OptiCheckBox(self, wx.ID_ANY, label="Output rotated subprograms", name='OutputSubRotated')
                    self.cb16.SetToolTipString("?")
                    subSizer.Add(self.cb16, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)
                    subSizer.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
                if 'OutputSubScaled' in postVar:
                    subSizer.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
                    self.cb17 = OptiCheckBox(self, wx.ID_ANY, label="Output scaled subprograms", name='OutputSubScaled')
                    self.cb17.SetToolTipString("?")
                    subSizer.Add(self.cb17, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)
                    subSizer.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
                if 'OutputSubMirrored' in postVar:
                    subSizer.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
                    self.cb18 = OptiCheckBox(self, wx.ID_ANY, label="Output mirrored subprograms", name='OutputSubMirrored')
                    self.cb18.SetToolTipString("?")
                    subSizer.Add(self.cb18, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)
                    subSizer.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
                if 'OutputSubInExtraFiles' in postVar:
                    subSizer.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
                    self.cb50 = OptiCheckBox(self, wx.ID_ANY, label="Output in separate files", name='OutputSubInExtraFiles')
                    self.cb50.SetToolTipString("?")
                    subSizer.Add(self.cb50, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)
                    subSizer.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)

            if 'ExtChars' in postVar:
                self.ExtChars = LabeledEditField( self, wx.ID_ANY, "NC filename extension", pos=wx.DefaultPosition, editSize=(50,-1), behaviour=BEHAVIOUR.ALPHANUMERIC, name='ExtChars' )
                #self.ExtChars.Wrap( -1 )
                subSizer.Add( self.ExtChars, 0, wx.EXPAND, SMALLBORDER )

            return subSizer
        
    def SelectNCfileExtension(self, parentSizer=None):
        if 'ExtChars' in postVar:
            subSizer = wx.StaticBoxSizer( StaticBox( self, wx.ID_ANY, "Output Mode", name="STB_OUTMODE") , wx.VERTICAL )
            if parentSizer:
                parentSizer.Add( subSizer, 0, wx.EXPAND, SMALLBORDER )

            self.ExtChars = LabeledEditField( self, wx.ID_ANY, "NC filename extension", pos=wx.DefaultPosition, editSize=(50,-1), behaviour=BEHAVIOUR.ALPHANUMERIC, name='ExtChars' )
            #self.ExtChars.Wrap( -1 )
            subSizer.Add( self.ExtChars, 0, wx.EXPAND, SMALLBORDER )

    def OnSubProgramOutChanged(self, event):  # @UnusedVariable
        postVar['SingleNCFile']    = self.SingleNCFile.GetValue()
        postVar['SeperateNCFiles'] = self.SeperateNCFiles.GetValue()
        postVar['Subprograms']     = self.cb15.GetValue()
        self.enablePage()

    def OnParseFileButton(self, event):
        # evtObjClass = event.GetEventObject().__class__.__name__
        evtObjName  = event.GetEventObject().GetName()
        # evtObjId    = event.GetEventObject().GetId()
        #
        doc = getCurrentDoc()
        #ncDir = doc.GetMachine().GetNCPath()
        #jku 2022/04/06
        ncDir = doc.GetMachine().GetCurrentOutputPath().getPyString()
        ncExt = doc.GetMachine().GetOutputExtension().getPyString().split(os.extsep)[-1].__str__()  # @UnusedVariable
        #
        defaultDir  = os.path.dirname( postVar.get('parseFileButton', ncDir) )
        defaultFile = os.path.basename( postVar.get('parseFileButton', wx.EmptyString) )

        # This is how you pre-establish a file filter so that the dialog
        # only shows the extension(s) you want it to.
#         wildcard = "(*.iso)|*.iso|" \
#             "All files (*.*)|*.*"
        wildcard = "All files (*.*)|*.*"

        dlg = wx.FileDialog(self, message=getMessageW("Choose file for ",PYTHON_MESSAGES,11) + evtObjName,
                            defaultDir=defaultDir,
                            defaultFile=defaultFile,
                            wildcard=wildcard,
                            style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST
                            )
        # Show the dialog and retrieve the user response. If it is the OK response, process the data.
        #
        if dlg.ShowModal() == wx.ID_OK:
            if evtObjName == 'parseFileButton':
                postVar['parseFileButton'] = dlg.GetPath()
                self.importNCFile(dlg.GetPath())
            else:
                postVar['parseFileButton'] = wx.EmptyString

            if _DEBUG:
                if logger: logger.info("You selected directory: %s" %  dlg.GetDirectory())
                if logger: logger.info("You selected file: %s" %  dlg.GetFilename())
                if logger: logger.info("You selected path: %s" %  dlg.GetPath())

    def importNCFile(self, filePath):
        """
        virtual method
        has to be implemented in derived (public postprocessor) classes
        """
        pass        

    def ModelStuff(self, parentSizer=None):
        if 'MODEL' in postVar:
            subSizer = wx.BoxSizer( wx.HORIZONTAL )
            if parentSizer: 
                parentSizer.Add( subSizer, 0, wx.EXPAND )  
            self.STT_MACHINE = TextField( self, wx.ID_ANY, "Machine Model:", wx.DefaultPosition, wx.DefaultSize, 0, name="MACHINE_MODEL" )
            # 09/03/2024 jorgk
            # wxSizer::Add() now does checks for flags, that make sense!
            # 09/03/2024 jorgk
            # hFlags = wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALL
            # hFlags = wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.SHAPED
            hFlags = wx.EXPAND|wx.ALL
            subSizer.Add( self.STT_MACHINE, 1, hFlags, SMALLBORDER )
            
            self.MODEL = TextField( self, 200, label="--MODEL NAME--", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.ALIGN_LEFT,  name='MODEL')
            self.MODEL.SetToolTipString('Name of current Model')
            #self.MODEL.SetBackgroundColour("LIGHT GREY")
            # hFlags = wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALL
            subSizer.Add( self.MODEL, 1, hFlags, SMALLBORDER )
            return subSizer

    def VersionStuff(self, parentSizer=None):
        if 'VERSION' in postVar:
            from p2c.jsonbase import UNIQUA_CHANGELOG  # @UnresolvedImport

            return  LabeledChoiceBox(self, wx.ID_ANY, label='Version', name='VERSION', toolTipString=UNIQUA_CHANGELOG, propChoice=1.0)

    # Uniquas
    def MinDBVersionStuff(self, parentSizer=None, callbck=None):
        if 'MINDBFOLDER' in postVar:
            toolTipString = 'Version of current minDB xml-file'
            lcb = LabeledChoiceBox(self, wx.ID_ANY, label='MinimalDb folder', name='MINDBFOLDER', toolTipString=toolTipString, propChoice=1.0)
            if len(postVar.get('MINDBFOLDERLIST', [])) == 0:
                lcb.Enable(False)
            elif callbck is not None:
                lcb.Bind( wx.EVT_CHOICE, callbck )
            return lcb

    # Uniquas, Cutexx0
    def PointReferenceStuff(self, parentSizer=None, callbck=None):
        if 'PointReferenceMode' in postVar:
            toolTipString = 'Coordinates reference mode for defined points'
            lcb = LabeledChoiceBox(self, wx.ID_ANY, label='Point reference mode', name='PointReferenceMode', toolTipString=toolTipString, propChoice=0.7)
            if len(postVar.get('PointReferenceModeLIST', [])) == 0:
                lcb.Enable(False)
            elif callbck is not None:
                lcb.Bind( wx.EVT_CHOICE, callbck )
            return lcb

    def ProfileStuff(self, parentSizer=None):
        if 'PROFILE' in postVar:
            subSizer = wx.BoxSizer( wx.HORIZONTAL )
            if parentSizer: 
                parentSizer.Add( subSizer, 0, wx.EXPAND )  
            self.ProfileText = TextField( self, wx.ID_ANY, "Profile:", size=( MEDIUMBORDER,MEDIUMBORDER ), name="PROFILE_TEXT")
            self.ProfileText.Wrap( -1 )
            subSizer.Add( self.ProfileText, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )
            self.PROFILE = LabeledComboBox2( self, wx.ID_ANY, label="", size=( MEDIUMBORDER,MEDIUMBORDER ), name='PROFILE', propChoice=1 )
            self.PROFILE.SetSelection( 0 )
            subSizer.Add( self.PROFILE, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )    
            subSizer.AddSpacer(SMALLBORDER)    
            self.AddProfile = NormalButton( self, wx.ID_ANY, "+", size=( MEDIUMBORDER,MEDIUMBORDER ), name='AddProfile')
            subSizer.Add( self.AddProfile, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )    
            self.DelProfile = NormalButton( self, wx.ID_ANY, "-", size=( MEDIUMBORDER,MEDIUMBORDER ), name='DelProfile')
            subSizer.Add( self.DelProfile, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )   
            
            self.AddProfile.Bind( wx.EVT_BUTTON, self.OnButtonAddProfile )
            self.DelProfile.Bind( wx.EVT_BUTTON, self.OnButtonDelProfile )    
            self.PROFILE.Bind(wx.EVT_COMBOBOX, self.OnPROFILEChanged)  
            return subSizer

    def OnButtonAddProfile(self, event):
        #Overwrite this in Grouppage 2 if you need a something different
        value=self.PROFILE.GetValue()
    
        #Check if String already exists
        if self.PROFILE.FindString(value) < 0:
            self.PROFILE.Append(value)
            
            #Add a Dict with this name
            #curModelName = self.FindWindowByName('MODEL').GetValue() # Todo maybe switch to exported curModel name
            doc = getCurrentDoc()
            curModelName = doc.GetMachine().GetModelObject().Name
            ModelSettings[curModelName][value]={}
            copydict = ModelSettings[curModelName]['DEFAULT'] #copy the default dict
            ModelSettings[curModelName][value].update(copydict)
            
            #Do this only if we dont already come from OnSave / OnOK event
            CallerName = event.EventObject.GetName()
            if not (CallerName == 'BTN_SAVESETTINGS' or CallerName == 'BTN_OK'):
                self.Parent.Parent.Parent.Parent.OnSave(event)
            
    def OnButtonDelProfile(self, event):
        #Overwrite this in Grouppage 2 if you need a something different
        #Dont Delete the Selection 0 (Default)
        if self.PROFILE.GetSelection() != 0:
            string = self.PROFILE.GetStringSelection()
            self.PROFILE.Delete(self.PROFILE.GetSelection())
            self.PROFILE.SetSelection(0)
            
            #Delete the Dict with this name
            #curModelName = self.FindWindowByName('MODEL').GetValue() # Todo maybe switch to exported curModel name
            doc = getCurrentDoc()
            curModelName = doc.GetMachine().GetModelObject().Name
            if string in ModelSettings[curModelName]:
                del(ModelSettings[curModelName][string])
                
            newstring = self.PROFILE.GetStringSelection()
            #try this
            self.Parent.Parent.Parent.Parent.ProfileChange(newstring)    
            #try this
            self.Parent.Parent.Parent.Parent.OnSave(event)    

    def OnPROFILEChanged(self, event = None):
        wdg = event.GetEventObject()

        if wdg:
            ProfileName = wdg.GetStringSelection()
            #try this
            self.Parent.Parent.Parent.Parent.ProfileChange(ProfileName)    

    def CmdHeaderStuff(self, parentSizer=None):
        #  Header / Footer (used by accutexx0, accutuniquaseq, accutx00, acorange)
        if postVar.get('OutputHeader') is not None and postVar.get('OutputFooter') is not None:

            def OnSelectCmdHeader(event):
                OnSelectCmdHeaderFooter(event, self.FindWindowByName('editFieldHeader'), 'header.cmd')
                
            def OnSelectCmdFooter(event):
                OnSelectCmdHeaderFooter(event, self.FindWindowByName('editFieldFooter'), 'footer.cmd')

            def OnSelectCmdHeaderFooter( event, headerField, defaultFile ):
                if headerField is None:
                    return
        
                s1 = self.mac.Name
                if headerField.GetValue():
                    defaultDir  = os.path.dirname( headerField.GetValue() )
                    defaultFile = os.path.basename( headerField.GetValue() )
                    if os.path.isdir(defaultDir) == False:
                        defaultDir = opticam.getPath('Post') +'\\' + s1.getPyString() # + '\\data'
                        if os.path.isdir(defaultDir) == False:
                            os.makedirs(defaultDir)
                else:
                    defaultDir = opticam.getPath('Post') +'\\' + s1.getPyString() # + '\\data'
                    if os.path.isdir(defaultDir) == False:
                        os.makedirs(defaultDir)
        
                evtObjName  = event.GetEventObject().GetName()
                wildcard = "(*.cmd)|*.cmd|" \
                         "All files (*.*)|*.*"
        
                dlg = wx.FileDialog(self, message=evtObjName + " File",
                                    defaultDir=defaultDir,
                                    defaultFile=defaultFile,
                                    wildcard=wildcard,
                                    style=wx.FD_OPEN
                    )
                # Show the dialog and retrieve the user response. If it is the OK response, process the data.
                #
                if dlg.ShowModal() == wx.ID_OK:
                    headerField.SetValue(dlg.GetPath())
                    EditHeaderFooterClicked(evtObjName, headerField)
        
            def EditHeaderFooterClicked(evtObjName, headerField):
                # Open Notepad for editing a file
                if headerField:
                    filepath = headerField.GetValue()
                else:
                    filepath = ''
                
                if os.path.exists(filepath):
                    os.system("Start Notepad " + filepath)
                else:
                    dlg = wx.MessageDialog(self, "Error: File not Found", evtObjName, wx.OK | wx.ICON_EXCLAMATION)
                    result = dlg.ShowModal()  # @UnusedVariable
                    dlg.Destroy()

            subSizer = wx.StaticBoxSizer( StaticBox( self, wx.ID_ANY, "Output Header Footer Data", name='STB_HEADERFOOTER') , wx.VERTICAL )
            if parentSizer: 
                parentSizer.Add( subSizer, 0, wx.EXPAND )  

            OutputHeader = OptiCheckBox(self, wx.ID_ANY, label="Load user defined header", name='OutputHeader')
            OutputHeader.SetToolTipString("?")
            subSizer.Add(OutputHeader, 1, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            OutputHeader.setSlaves(['editFieldHeader', 'chooseHeader'])
            
            hbox1 = wx.BoxSizer(wx.HORIZONTAL)
            subSizer.Add(hbox1, 0, wx.EXPAND)
            editFieldHeader = EditField(self, wx.ID_ANY, toolTipString="", name='editFieldHeader', style=wx.TE_READONLY)
            hbox1.Add(editFieldHeader, 1, wx.ALIGN_CENTER|wx.LEFT|wx.RIGHT, 0)

            chooseHeader = NiceButton(self, wx.ID_ANY, OPEN_FILE_ICON,  disabledButtonICO=OPEN_FILE_DISABLED_ICON, name='chooseHeader')
            chooseHeader.SetToolTipString("Browse for user defined header file")
            chooseHeader.Bind(wx.EVT_BUTTON, OnSelectCmdHeader)
            hbox1.Add(chooseHeader, 0, wx.ALIGN_CENTER|wx.RIGHT, SMALLBORDER)

            OutputFooter = OptiCheckBox(self, wx.ID_ANY, label="Load user defined footer", name='OutputFooter')
            OutputFooter.SetToolTipString("?")
            subSizer.Add(OutputFooter, 1, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            OutputFooter.setSlaves(['editFieldFooter', 'chooseFooter'])

            hbox2 = wx.BoxSizer(wx.HORIZONTAL)
            subSizer.Add(hbox2, 0, wx.EXPAND)
            editFieldFooter = EditField(self, wx.ID_ANY, toolTipString="", name='editFieldFooter', style=wx.TE_READONLY)
            hbox2.Add(editFieldFooter, 1, wx.ALIGN_CENTER|wx.LEFT|wx.RIGHT, 0)

            chooseFooter = NiceButton(self, wx.ID_ANY, OPEN_FILE_ICON, disabledButtonICO=OPEN_FILE_DISABLED_ICON, name='chooseFooter')
            chooseFooter.SetToolTipString("Browse for user defined footer file")
            chooseFooter.Bind(wx.EVT_BUTTON, OnSelectCmdFooter)
            hbox2.Add(chooseFooter, 0, wx.ALIGN_CENTER|wx.RIGHT, SMALLBORDER)

            return subSizer

class GroupPage1(BaseGroupPage):
    """ we are a BasePanel. """
    #GENERALSETTINGS PAGE
    def __init__(self, parent, id, name="_GRP_PAGE1"):  # @ReservedAssignment
        BaseGroupPage.__init__(self, parent, id, name=name)

        self.createPage()

        # now we have to call this function after the TransferDataToWindow
        # because the state of some widgets depends of some other widgets which have to be set before
        # ...in BasePostOptionsDialog.Activate()
        # self.enablePage()

    def createPage(self):      # First Side (Allgemein)
        #Sizer for whole page       
        pageSubsizer = wx.BoxSizer(wx.HORIZONTAL)
        self.sizer.Add(pageSubsizer, 0, wx.EXPAND)
        #Subsizers for left and right side of the page 
        leftSideSubsizer = wx.StaticBoxSizer( StaticBox( self, wx.ID_ANY, wx.EmptyString, name="_STB_L" ), wx.VERTICAL)
        rightSideSubsizer = wx.StaticBoxSizer( StaticBox( self, wx.ID_ANY, wx.EmptyString, name="_STB_R" ), wx.VERTICAL)
        pageSubsizer.Add(leftSideSubsizer, 1, wx.EXPAND)
        pageSubsizer.Add(rightSideSubsizer, 1, wx.EXPAND)
        
        # the Logo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#        logo = iconsDir + postVar['winLogo']
        sub1_1 = wx.StaticBoxSizer(StaticBox(self, 110, "Output units", "STB_OUTUNITS"), wx.HORIZONTAL)
        leftSideSubsizer.Add(sub1_1, 0, wx.EXPAND)
#        if not fileExist(logo):
#            bmp = wx.ArtProvider.GetBitmap(wx.ART_MISSING_IMAGE, wx.ART_OTHER, (48, 48))
#            logger.error("""can't load Image: %s""" % logo)
#        else:
#            img = wx.Image(logo, wx.BITMAP_TYPE_ANY)
#            logger.error("""loading Image: %s %s""" % (logo, str(img.GetSize())))
#            img = img.Scale(100, 100)
#            bmp = wx.BitmapFromImage(img)

        if _DEBUG > 0x1:
            self.imgButton = NiceButton(self, wx.ID_ANY, postVar['winLogo'], name="_BTN_DIALOGLOGO")
            self.imgButton.SetToolTipString("Machine Manufacturers Logo (click to select new one)")
            self.imgButton.Bind(wx.EVT_LEFT_DCLICK, self.OnImageBrowse)

            sub1_1.Add(self.imgButton, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        else:
            bmp = getOpticamIcon(postVar['winLogo'], (48,48))
            bmp = wx.StaticBitmap(self, wx.ID_ANY, bmp)
            sub1_1.Add(bmp, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        # 1st group of Radio-Buttons:
        sub2 = wx.BoxSizer(wx.VERTICAL)
        sub1_1.Add(sub2, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        if 'OutputUnitsMetric' in postVar:
            metricButton = OptiRadioButton(self, wx.ID_ANY, "Metric", style = wx.RB_GROUP, name="OutputUnitsMetric")  # starts first group
            metricButton.SetToolTipString("Output in metrical units")
            metricButton.Bind(wx.EVT_RADIOBUTTON, self.OnUnitsButton)
            sub2.Add(metricButton, 1, wx.ALIGN_LEFT|wx.EXPAND|wx.TOP|wx.BOTTOM, SMALLBORDER)
        else:
            sub2.Add(SPACER, 1, wx.ALIGN_LEFT|wx.EXPAND|wx.TOP|wx.BOTTOM, SMALLBORDER)

        if 'OutputUnitsInch' in postVar:
            if not 'OutputUnitsMetric' in postVar:
                inchButton = OptiRadioButton(self, wx.ID_ANY, label="Inch", style = wx.RB_GROUP, name="OutputUnitsInch")
            else:
                inchButton = OptiRadioButton(self, wx.ID_ANY, label="Inch", name="OutputUnitsInch")
            inchButton.SetToolTipString("Output in inches units")
            inchButton.Bind(wx.EVT_RADIOBUTTON, self.OnUnitsButton)
            sub2.Add(inchButton, 1, wx.ALIGN_LEFT | wx.EXPAND|wx.TOP|wx.BOTTOM, SMALLBORDER)
        else:
            sub2.Add(SPACER, 1, wx.ALIGN_LEFT | wx.EXPAND|wx.TOP|wx.BOTTOM, SMALLBORDER)

        # 2nd group of controls:
        if 'AbsoluteCommandAbsolute' in postVar:
            rb3 = OptiRadioButton(self, wx.ID_ANY, label="Absolute", style = wx.RB_GROUP, name='AbsoluteCommandAbsolute')   # starts second group
            rb3.SetToolTipString("Absolute units")
            sub2.Add(rb3, 1, wx.ALIGN_LEFT | wx.EXPAND|wx.TOP|wx.BOTTOM, SMALLBORDER)
        else:
            sub2.Add(SPACER, 1, wx.ALIGN_LEFT | wx.EXPAND|wx.TOP|wx.BOTTOM, SMALLBORDER)
        if 'AbsoluteCommandIncrement' in postVar:
            if not 'AbsoluteCommandAbsolute' in postVar:
                rb4 = OptiRadioButton(self, wx.ID_ANY, label="Incremental", style = wx.RB_GROUP, name='AbsoluteCommandIncrement')
            else:
                rb4 = OptiRadioButton(self, wx.ID_ANY, label="Incremental", name='AbsoluteCommandIncrement')
            rb4.SetToolTipString("Incremental units")
            sub2.Add(rb4, 1, wx.ALIGN_LEFT | wx.EXPAND|wx.TOP|wx.BOTTOM, SMALLBORDER)
        else:
            sub2.Add(SPACER, 1, wx.ALIGN_LEFT | wx.EXPAND|wx.TOP|wx.BOTTOM, SMALLBORDER)

        # Satz Nummerierung
        if 'BlockOutPutDoOutPut' in postVar:
            sub3 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Block Numbers out", "STB_BLOCKNUMBERS"), wx.VERTICAL)
            rightSideSubsizer.Add(sub3, 0, wx.EXPAND)
            cb1 = OptiCheckBox(self, wx.ID_ANY, label="Active", name='BlockOutPutDoOutPut')
            cb1.SetToolTipString("?")
            sub3.Add(cb1, 1, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            cb1.setSlaves(['BlockOutPutStep', 'BlockOutPutStart'])

            ef1 = LabeledEditField(self, wx.ID_ANY, "Start Number", min=0, max=1000000, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.INTEGER, name='BlockOutPutStart')
            ef1.SetToolTipString("Start numbering with this value")
            sub3.Add(ef1, 0, wx.EXPAND)
            if postVar.get('ClassName', 'undefined') in ['MakinoPostOptionsDialog']:                
                ef2 = LabeledEditField(self, wx.ID_ANY, "Increment",    min=-1000000, max=1000000, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.INTEGER, name='BlockOutPutStep')
            else:
                ef2 = LabeledEditField(self, wx.ID_ANY, "Increment",    min=1, max=1000000, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.INTEGER, name='BlockOutPutStep')
            ef2.SetToolTipString("Use an increment with this value")
            sub3.Add(ef2, 0, wx.EXPAND)
        else:
            #rightSideSubsizer.Add(SPACER, 1, wx.EXPAND)
            pass

        # Ausgabe Parameter !! Not for AGIE123
        #leftSideSubsizer = wx.BoxSizer(wx.HORIZONTAL)
        #self.sizer.Add(leftSideSubsizer, 0, wx.EXPAND)
        if postVar.get('decimalPoint') != None:
            # leftSideSubsizer = wx.BoxSizer(wx.HORIZONTAL)
            # self.sizer.Add(leftSideSubsizer, 0, wx.EXPAND)
            #
            sub4 = wx.StaticBoxSizer(StaticBox(self, 118, "Output format", name='STB_OUTPARAMS'), wx.VERTICAL)
            leftSideSubsizer.Add(sub4, 0, wx.EXPAND)

            cb2 = OptiCheckBox(self, 114, label="Use decimal point output", name='decimalPoint')
            cb2.SetToolTipString("Decimalpoint Output")
            if postVar.get('ClassName', 'undefined') in ['ACMillenniumPostOptionsDialog', 'ACVisionPostOptionsDialog']:
                cb2.Enable(False)
            else:
                cb2.setSlaves(['DigitsAfter'])          # test a new method for dependencies between widgets
            sub4.Add(cb2, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

            self.cb2_10 = LabeledComboBox(self, 135, "Digits after decimal point", name='DigitsAfter', propChoice=0.5)
            self.cb2_10.SetToolTipString("Number of digits after decimal point")
            self.cb2_10.Enable(postVar['decimalPoint'])
            sub4.Add(self.cb2_10, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
            #leftSideSubsizer.Add(SPACER, 1, wx.EXPAND)
        else:
            #leftSideSubsizer.Add(SPACER, 1, wx.EXPAND)
            pass
            
        # if postVar.get('UseRotaryAxis') != None and False:        ### DEACTIVATED -> MAINSYSTEM TOOK CONTROL
        #     sub41 = wx.StaticBoxSizer(StaticBox(self, 118, "Rotary axis", name='STB_ROTARYAXIS'), wx.VERTICAL)
        #     leftSideSubsizer.Add(sub41, 1, wx.EXPAND)
        #
        #     self.RotaryAxis(sub41)
        #     leftSideSubsizer.Add(SPACER, 1, wx.EXPAND)

        #----------Experimental-------------------
        """
        from wx import gizmos

        sub5 = wx.BoxSizer(wx.VERTICAL)
        leftSideSubsizer.Add(sub5, 1, wx.EXPAND)
        sub5.Add(SPACER, 1, wx.EXPAND)
        led = gizmos.LEDNumberCtrl(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, gizmos.LED_ALIGN_CENTER)
        led.SetValue("123456.789")
        led.SetMinSize((120,30))
        sub5.Add(led, 1, wx.EXPAND|wx.ALL, SMALLBORDER)
        """
        """
        The widget probably doesn't have a DoGetBestSize defined so it is
        falling back to a simple default. You can override that by setting its
        min size to whatever you want, which the sizer will then use instead of
        the best size. (from Robin Dunn)
        """
        #-----------------------------------------
        #subsizer3 = wx.BoxSizer(wx.HORIZONTAL)
        #self.sizer.Add(subsizer3, 0, wx.EXPAND)

        # Einrichteblatt / Startlochdatei
        sub3_2 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, wx.EmptyString, name='STB_NCSETUP'), wx.VERTICAL)
        leftSideSubsizer.Add(sub3_2, 0, wx.EXPAND)

        if 'OpenNCFile' in postVar:
            cb3 = OptiCheckBox(self, wx.ID_ANY, label="Open NC file in editor", name='OpenNCFile')
            cb3.SetToolTipString("Opens the new created file automatically in an editor.")
            sub3_2.Add(cb3, 1, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if postVar.get('ShowInExplorer') == True:
            cb4 = OptiCheckBox(self, wx.ID_ANY, label="Show nc-file in explorer", name='ShowInExplorer')
            cb4.SetToolTipString("Shows the new created file automatically in windows explorer.")
            sub3_2.Add(cb4, 1, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'NCExtraFolder' in postVar:
            hbox = wx.BoxSizer(wx.HORIZONTAL)
            sub3_2.Add(hbox, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, SMALLBORDER)
            self.NCExtraFolder = OptiCheckBox(self, wx.ID_ANY, label="Store nc-file in subfolder", name='NCExtraFolder')
            self.NCExtraFolder.SetToolTipString("Store nc-data in separate folder!")
            # Only vertical allignement in horizontal possible!
            # wx.ALIGN_LEFT
            # flags = wx.ALIGN_LEFT|wx.ALIGN_CENTRE_VERTICAL|wx.EXPAND
            # 10240
            # flagsI = wx.ALIGN_RIGHT|wx.ALIGN_CENTRE_VERTICAL|wx.EXPAND
            # 09/03/2024 jorgk
            # wxSizer::Add() now does checks for flags, that make sense!
            # 09/03/2024 jorgk
            hbox.Add(self.NCExtraFolder, 1, wx.ALIGN_CENTER_VERTICAL)
            self.NCExtraFolderName = EditField(self, wx.ID_ANY, size=(150,-1), behaviour=BEHAVIOUR.ALPHANUMERIC, name='NCExtraFolderName')
            self.NCExtraFolderName.SetToolTipString("NC subfolder name")
            # hbox.Add(self.NCExtraFolderName, 1, wx.ALIGN_RIGHT|wx.ALIGN_CENTER)
            hbox.Add(self.NCExtraFolderName, 1, wx.ALIGN_CENTER)

        sub3_3 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "", name='STB_STARTHOLE'), wx.VERTICAL)
        rightSideSubsizer.Add(sub3_3, 0, wx.EXPAND)
        cb109 = OptiCheckBox(self, 109, label="Create starthole file", name='StartHoleFile')
        cb109.SetToolTipString("Output a coordinate file for a starthole drilling machine")
        sub3_3.Add(cb109, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        
        self.OpenStartHoleFile = OptiCheckBox(self, wx.ID_ANY, label="Open starthole file in editor", name='OpenStartHoleFile')
        self.OpenStartHoleFile.SetToolTipString("Open the file after PP run in editor")
        sub3_3.Add(self.OpenStartHoleFile, 1, wx.EXPAND | wx.ALL, SMALLBORDER)

        self.SelectedStartholePP = LabeledComboBox(self, wx.ID_ANY, label='Current starthole PP', name='SelectedStartholePP', toolTipString="", propChoice=1, prettyNamesDict=SHPrettyNamesDict)
        self.SelectedStartholePP.SetToolTipString("")
        sub3_3.Add(self.SelectedStartholePP, 1, wx.EXPAND | wx.ALL, SMALLBORDER)

        self.ShowShPPDlg = NormalButton(self, wx.ID_ANY, label='Show starthole PP dialog', name='ShowShPPDlg')
        self.ShowShPPDlg.SetToolTipString("")
        self.ShowShPPDlg.Bind(wx.EVT_BUTTON, self.OnShowShPPDialogClicked)
        sub3_3.Add(self.ShowShPPDlg, 1, wx.EXPAND | wx.ALL, SMALLBORDER)

        #-----------------------------------------
        #subsizer4 = wx.BoxSizer(wx.HORIZONTAL)
        #self.sizer.Add(subsizer4, 0, wx.EXPAND)
        
        #  KommentarAusgabe / MaschinentypAuswahl
        if 'OutputComment' in postVar:
            sub4_2 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "", name='STB_COMMENT'), wx.VERTICAL)
            leftSideSubsizer.Add(sub4_2, 0, wx.EXPAND)
            cb117 = OptiCheckBox(self, 117, label="Add comment for each cut", name='OutputComment')
#            cb117.SetToolTipString(u"Three options available: Do not confirm / Confirm for new operations / Confirm on new and edited operations.")
            cb117.SetToolTipString("Inserts a description as a comment in the NC-file.")
            sub4_2.Add(cb117, 1, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

            #if postVar['ClassName'] == 'RoboFilPostOptionsDialog':
            if 'OutputTechComment' in postVar:
                cb118 = OptiCheckBox(self, 117, label="Add techn. comment for each cut", name='OutputTechComment')
                cb118.SetToolTipString("Inserts a cuts-editor description as a comment in the NC-file.")
                sub4_2.Add(cb118, 1, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

            if 'ConfirmForNewOperations' in postVar:
                sub4_2.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
                cb124 = OptiCheckBox(self, 124, label="Confirm upon a new machining operation only", name='ConfirmForNewOperations')
                cb124.SetToolTipString("Three options available: Do not confirm / confirm for new operartions / confirm on new and edited operations.")
                sub4_2.Add(cb124, 1, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)
                sub4_2.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
                cb117.setSlaves(['ConfirmForNewOperations'])

        #  Header / Footer
        if postVar.get('OutputUserDefinedHeader') is not None and postVar.get('OutputUserDefinedFooter') is not None:
            sub4_3 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "", name='STB_HEADER'), wx.VERTICAL)
            rightSideSubsizer.Add(sub4_3, 0, wx.EXPAND)

            cb240 = OptiCheckBox(self, wx.ID_ANY, label="Load user defined header", name='OutputUserDefinedHeader')
            cb240.SetToolTipString("?")
            sub4_3.Add(cb240, 1, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            cb240.setSlaves(['UserDefinedHeaderField', 'UserDefinedHeaderButton'])
            
            hbox1 = wx.BoxSizer(wx.HORIZONTAL)
            sub4_3.Add(hbox1, 0, wx.EXPAND)
            ef342 = EditField(self, wx.ID_ANY, toolTipString="", name='UserDefinedHeaderField', style=wx.TE_READONLY)
            hbox1.Add(ef342, 1, wx.ALIGN_CENTER|wx.LEFT|wx.RIGHT, 0)

            btn408 = NiceButton(self, wx.ID_ANY, OPEN_FILE_ICON, name='UserDefinedHeaderButton')
            btn408.SetToolTipString("Browse for user defined header file")
            btn408.Bind(wx.EVT_BUTTON, self.OnSelectUserDefinedHeader)
            hbox1.Add(btn408, 0, wx.ALIGN_CENTER|wx.RIGHT, SMALLBORDER)

            cb241 = OptiCheckBox(self, wx.ID_ANY, label="Load user defined footer", name='OutputUserDefinedFooter')
            cb241.SetToolTipString("?")
            sub4_3.Add(cb241, 1, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            cb241.setSlaves(['UserDefinedFooterField', 'UserDefinedFooterButton'])

            hbox2 = wx.BoxSizer(wx.HORIZONTAL)
            sub4_3.Add(hbox2, 0, wx.EXPAND)
            ef343 = EditField(self, wx.ID_ANY, toolTipString="", name='UserDefinedFooterField', style=wx.TE_READONLY)
            hbox2.Add(ef343, 1, wx.ALIGN_CENTER|wx.LEFT|wx.RIGHT, 0)

            btn409 = NiceButton(self, wx.ID_ANY, OPEN_FILE_ICON, name='UserDefinedFooterButton')
            btn409.SetToolTipString("Browse for user defined footer file")
            btn409.Bind(wx.EVT_BUTTON, self.OnSelectUserDefinedFooter)
            hbox2.Add(btn409, 0, wx.ALIGN_CENTER|wx.RIGHT, SMALLBORDER)

        # a testwise button intended to read in and parse nc-files
        # parsing takes place in the derived classes (postprocessor dependend)
        if os.environ.get('NCFileImport', '').upper() == 'TRUE':
            self.parseFileButton = NormalButton( self, wx.ID_ANY, "Import NC file", wx.DefaultPosition, wx.DefaultSize, 0, name='parseFileButton' )
            self.parseFileButton.SetToolTipString("Load and parse NC file")
            self.parseFileButton.SetBackgroundColour("AQUAMARINE")
            self.parseFileButton.Bind(wx.EVT_BUTTON, self.OnParseFileButton)
            self.sizer.Add(self.parseFileButton, 0, wx.EXPAND)

        # another testwise button intended to start gears dialog
        if os.environ.get('STARTGEARSDIALOG', '').upper() == 'TRUE':
            self.startGearsDialog = NormalButton( self, wx.ID_ANY, "Start gears dialog", wx.DefaultPosition, wx.DefaultSize, 0, name='startGearsDialog' )
            self.startGearsDialog.SetToolTipString("Load and parse NC file")
            self.startGearsDialog.SetBackgroundColour("AQUAMARINE")
            self.startGearsDialog.Bind(wx.EVT_BUTTON, self.OnStartGearsDialogClicked)
            self.sizer.Add(self.startGearsDialog, 0, wx.EXPAND)
            
            
            
        '''Bind wx-Events to Widgets'''
        self.NCExtraFolder.Bind( wx.EVT_CHECKBOX, self.OnNCExtraFolderBox )
        

    def enablePage(self):
        """ Enables/disables the widgets of this page."""

        ENABLED = True
        DISABLED = False
        self.enableWidget('OpenNCFile',              None, {'OpenNCFile': [ENABLED, False]})
        self.enableWidget('NCExtraFolderName',       ['NCExtraFolder',], {'NCExtraFolderName': [ENABLED, False]})
        self.enableWidget('ShowInExplorer',          None, {'ShowInExplorer': [ENABLED, False]})
        self.enableWidget('SetupSheet',              None, {'SetupSheet': [ENABLED, False]})
        #self.enableWidget('StartHoleFile',           None, {'StartHoleFile': [DISABLED, False]})
        self.enableWidget('OutputComment',           None, {'OutputComment': [ENABLED, False]})
        self.enableWidget('OutputTechComment',       None, {'OutputTechComment': [ENABLED, False]})

        modelSet = GetModelSetting()

        # self.enableWidget('OutputUserDefinedHeader', None, modelSet)
        # self.enableWidget('UserDefinedHeaderField',  ['OutputUserDefinedHeader'], modelSet)
        # self.enableWidget('OutputUserDefinedFooter', None, modelSet)
        # self.enableWidget('UserDefinedFooterField',  ['OutputUserDefinedFooter'], modelSet)

    def OnImageBrowse(self, event):  # @UnusedVariable
        ret = ImageBrowser(self)
        if ret is not None:
            postVar['winLogo'] = ret[1]
            self.imgButton.setButtonUpICO(postVar['winLogo'])

    def OnUnitsButton(self, event):
        isHasAttribute = False
        wdg = event.GetEventObject()
        # wdg.GetTopLevelParent().bIsOutputUnitMetric. PostOption Dilog
        objPPDialog = wdg.GetTopLevelParent()
        if hasattr(objPPDialog, 'bIsOutputUnitMetric'):
            isHasAttribute = True
        else:
            isHasAttribute = False
        if wdg.GetName() == "OutputUnitsMetric":
            self.setDigitsList(True)
            if isHasAttribute: objPPDialog.bIsOutputUnitMetric = True
        if wdg.GetName() == "OutputUnitsInch":
            self.setDigitsList(False)
            if isHasAttribute: objPPDialog.bIsOutputUnitMetric = False
        if _DEBUG:
            logger.info("%s%s" % (wdg.__class__.__name__, wdg.GetValue()))
            
    def OnNCExtraFolderBox( self, event ):
        if event.IsChecked():
            #enable widgets as soon as SetupsheetExtraFolder check box is checked
            self.NCExtraFolderName.Enable()

        else:
            #disable widgets if SetupsheetExtraFolder is unchecked
            self.NCExtraFolderName.SetValue('')
            self.NCExtraFolderName.Disable()
            
    def setDigitsList(self, isMetric):
        digits = self.cb2_10.GetValue()     # act. value
        if isMetric:
            digitsList = ['3', '4', '5', '6']
        else:
            digitsList = ['4', '5', '6']

        # if act. value is not in the new itemslist -> take the first value from the itemlist
        if digits not in digitsList:
            digits = digitsList[0]
        self.cb2_10.SetItems(digitsList)
        self.cb2_10.SetValue(digits)

    def OnShowShPPDialogClicked(self, event):  # @UnusedVariable
        shppname = self.SelectedStartholePP.GetStringSelection()
        startholemachine = SetStartholePP(shppname)  # @UndefinedVariable
        startholemachine.InitPost(show=False, parent=self.TopLevelParent)
        """ to show modeless dialogs from within python: """
        pyobj = getCurrentDoc().GetPyObj()
        # Now show the dialog:
        pyobj.ShowModlessListObjectDlg("StartholeOptionsDialog")        # Use here the NAME of the dialog (not class name)

    def OnStartGearsDialogClicked(self, event):  # @UnusedVariable
        from gears.gears_main import MainGearsDialog  # @UnresolvedImport
        parent = getCurrentDoc().DocumentWindow()
        gearDlg = MainGearsDialog(parent, title='Envolute Gear Wheel - /1' + 'External / DIN', modal=True)     # Dialog with no blocking
        # Resize MainGearsDialog
        gearDlg.CreateControls()
        gearDlg.Activate()

    def OnSelectUserDefinedHeader(self, event):
        BaseGroupPage.SelectUserDefinedHeader(self, event)
        
    def OnSelectUserDefinedFooter(self, event):
        BaseGroupPage.SelectUserDefinedFooter(self, event)

class GroupPage2(BaseGroupPage):
    #NC-OUTPUT PAGE
    def __init__(self, parent, id, name="_GRP_PAGE2"):  # @ReservedAssignment
        BaseGroupPage.__init__(self, parent, id, name=name)

        self.createPage()

        # should always be configurable
        if 'autoConfigOff' in postVar:
            self.autoConfigOff(postVar['autoConfigOff'])

        # now we have to call this function after the TransferDataToWindow
        # because the state of some widgets depends of some other widgets which have to be set before
        # ...in BasePostOptionsDialog.Activate()
        # self.enablePage()

    def createPage(self):      # Second Side (Optionen)
        subsizer1 = wx.BoxSizer(wx.HORIZONTAL)
        self.sizer.Add(subsizer1, 0, wx.EXPAND)

        # Maschinen Modell     # Linke Seite
        sub1_1 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "", name="STB_MACHINEMODEL"), wx.VERTICAL)
        subsizer1.Add(sub1_1, 1, wx.EXPAND)
        
        if 'MODEL' in postVar:
            sub1_1.Add( self.ModelStuff(), 0, wx.EXPAND | wx.ALL, SMALLBORDER)

        self.ProfileStuff(parentSizer=sub1_1)        

        self.SubprogramOutput(parentSizer=sub1_1)

#         self.SelectNCfileExtension(parentSizer=sub1_1)    # now integrated in previous 'SubprogramOutput' method

        if 'OutputPercSignBeforeMain' in postVar:
            cb111 = OptiCheckBox(self, wx.ID_ANY, label="Output % before main program", name='OutputPercSignBeforeMain')
            cb111.SetToolTipString("?")
            sub1_1.Add(cb111, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
        
        if 'AutomaticThreading' in postVar:     # this is now set constantly to True (without presenting the wdg)

            self.AutomaticThreading = OptiCheckBox(self, 202, label="Wire Thread by Machine", name='AutomaticThreading')
            self.AutomaticThreading.SetToolTipString("Output automatical Wirethread and Wirecut")       # robo
            sub1_1.Add(self.AutomaticThreading, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            self.AutomaticThreading.Bind(wx.EVT_CHECKBOX, self.OnAutomaticThreadingChanged)


            if 'TParameter' in postVar:
                #We add some String, because a empty choice (only with one entry '') causes a to huge combobox
                if len(postVar['TParameterLIST']) == 0:
                    postVar['TParameterLIST'].append('Empty')
                elif len(postVar['TParameterLIST']) == 1:
                    if postVar['TParameterLIST'][0] == '':
                        postVar['TParameterLIST'][0] = 'Empty'
#                cobo227 = LabeledComboBox(self, wx.ID_ANY, u"Threading Type", choices=postVar['TParameterLIST'], name='TParameter')
                cobo227 = LabeledComboBox(self, wx.ID_ANY, "Threading Type", name='TParameter')
                cobo227.SetMinSize((230,35))
                cobo227.SetToolTipString("Threading Type M06T01 to T03; available only for the Machines CT 1020 and CT 1030")
                sub1_1.Add(cobo227, 0, wx.EXPAND)

            if 'ThreadInGap' in postVar:
                cb211 = OptiCheckBox(self, wx.ID_ANY, label="Thread in the gap (G50/G52)", name='ThreadInGap')
                cb211.SetToolTipString("Thread in the Gap; available only for the Machine CT 1030")
                sub1_1.Add(cb211, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

            if 'NoThreadingOutput' in postVar:
                self.NoThreadingOutput = OptiCheckBox(self, wx.ID_ANY, label="Don't Output Stop with comment", name='NoThreadingOutput')
                self.NoThreadingOutput.SetToolTipString("Suppress stopping the machine and showing a comment")
                sub1_1.Add(self.NoThreadingOutput, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)
                sub1_1.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
                self.NoThreadingOutput.Bind(wx.EVT_CHECKBOX, self.OnAutomaticThreadingChanged)

        if 'OutputRefSecPlanes' in postVar:
            cb3 = OptiCheckBox(self, wx.ID_ANY, label="Output ref. and sec. plane", name='OutputRefSecPlanes')
            cb3.SetToolTipString("?")
            sub1_1.Add(cb3, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'GeneratorOut' in postVar:
            self.cb223 = OptiCheckBox(self, 223, label="Output Generator (M20/M21)", name='GeneratorOut')
            self.cb223.SetToolTipString("Output 'Generator on'; M20 and 'Generator off'; M21")
            sub1_1.Add(self.cb223, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            self.cb223.Bind(wx.EVT_CHECKBOX, self.OngeneratorOutChanged)

            if 'CutWireAtStop' in postVar:
                sub1_1.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
                cb204 = OptiCheckBox(self, wx.ID_ANY, label="Wire cut at Stop", name='CutWireAtStop')
                cb204.SetToolTipString("Nur bei Anbindungsoption: Stop - Anbindungen mit dem ersten Schnitt entfernen")
                sub1_1.Add(cb204, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)

                sub1_1.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)

        if 'GeneratorOnOffBeforeChange' in postVar:
            cb5 = OptiCheckBox(self, 205, label="Generator on off before gen. change", name='GeneratorOnOffBeforeChange')
            cb5.SetToolTipString("i.E. M21 E7 M20")
            sub1_1.Add(cb5, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'OutputCornerStrategy' in postVar:
            cb6 = OptiCheckBox(self, wx.ID_ANY, label="Output edge strategy", name='OutputCornerStrategy')
            cb6.SetToolTipString("?")
            sub1_1.Add(cb6, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'GeneratorOnOffByFigur' in postVar:
            cb7 = OptiCheckBox(self, 237, label="Gen off/on with 'Cut between Profiles'", name='GeneratorOnOffByFigur')
            cb7.SetToolTipString("Generator off/on (M21/M20) before the rough cut E501 when using 'Cut between Profiles'")
            sub1_1.Add(cb7, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'GeneratorOffByArcLeadOff' in postVar:
            cb8 = OptiCheckBox(self, 210, label="Gen. off with arc.type lead-off (M21)", name='GeneratorOffByArcLeadOff')
            cb8.SetToolTipString("Switches off Generator before leading off with a Circle; only available with leading off in Rapid Mode")
            sub1_1.Add(cb8, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        self.G92Output(sub1_1)

        if 'G75Mode' in postVar:
            cb40 = OptiCheckBox(self, wx.ID_ANY, label="Use G75 for first position", name='G75Mode')
            cb40.SetToolTipString("?")
            sub1_1.Add(cb40, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'GeneratorSettingSeparate' in postVar:
            self.cb206 = OptiCheckBox(self, 206, label="Generator stage in a separate NC-Line", name='GeneratorSettingSeparate')
            self.cb206.SetToolTipString("Output of the E-Pack in a separate NC Line")
            sub1_1.Add(self.cb206, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            self.cb206.Bind(wx.EVT_CHECKBOX, self.OnGeneratorSettingSeparateChanged)

            if 'DWell' in postVar:
                hbox5 = wx.BoxSizer(wx.HORIZONTAL)
                #hbox5.AddSpacer( ( 20, 0), 0, wx.EXPAND, SMALLBORDER )
                hbox5.AddSpacer( SPACE )
                sub1_1.Add(hbox5, 1, wx.EXPAND)
                cb221 = OptiCheckBox(self, wx.ID_ANY, label="Dwell time", name='DWell')
                cb221.SetToolTipString("Generatorchange with Dwelltime in Milliseconds; i.E.: G04 F5.0")
                hbox5.Add(cb221, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, SMALLBORDER)
                cb221.Bind(wx.EVT_CHECKBOX, self.OndWellChanged)

                hbox5.AddSpacer( SPACE )

                ef224 = EditField(self, wx.ID_ANY, min=0, max=1000000, behaviour=BEHAVIOUR.NUMERIC, name='DWellTime', size=(50,-1))
                ef224.SetToolTipString("A typical value for this would be 5ms")
                hbox5.Add(ef224, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, SMALLBORDER)
        else:
            if 'DWell' in postVar:
                hbox5 = wx.BoxSizer(wx.HORIZONTAL)
                sub1_1.Add(hbox5, 0, wx.EXPAND, SMALLBORDER)
                cb221 = OptiCheckBox(self, wx.ID_ANY, label="Dwell time", name='DWell')
                cb221.SetToolTipString("Dwelltime in Milliseconds; i.E.: G04 F5.0")
                hbox5.Add(cb221, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, SMALLBORDER)
                cb221.Bind(wx.EVT_CHECKBOX, self.OndWellChanged)

                hbox5.AddSpacer(  SPACE )

                ef224 = EditField(self, wx.ID_ANY, size=(50,-1), min=0, max=1000000, behaviour=BEHAVIOUR.NUMERIC, name='DWellTime', style=wx.TE_RIGHT)
                ef224.SetToolTipString("A typical value for this would be 5ms")
                hbox5.Add(ef224, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, SMALLBORDER)
                
        if 'PathCorrectionAfterLeadOn' in postVar:
            self.cb207 = OptiCheckBox(self, 207, label="Path Correction After Lead On", name='PathCorrectionAfterLeadOn')
            self.cb207.SetToolTipString("Path Correction After Lead On")
            sub1_1.Add(self.cb207, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            self.cb207.Bind(wx.EVT_CHECKBOX, self.PathCorrectionAfterLeadOnChanged)

        if 'ConicModeM15P' in postVar:
            cb13 = OptiCheckBox(self, wx.ID_ANY, label="Conic mode M15P", name='ConicModeM15P')
            cb13.SetToolTipString("?")
            sub1_1.Add(cb13, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'IndependentTopBottom' in postVar:
            cb14 = OptiCheckBox(self, wx.ID_ANY, label="Ruled surface not in Taper Expert Mode", name='IndependentTopBottom')
            cb14.SetToolTipString("?")
            sub1_1.Add(cb14, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if postVar.get('InclinedFeatureAs4Axis') is not None:
            cb41 = OptiCheckBox(self, wx.ID_ANY, label="Inclined feature as four-axis feature", name='InclinedFeatureAs4Axis')
            cb41.SetToolTipString("Can be used to prevent the G32 command (Robo)")
            sub1_1.Add(cb41, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'OutputHeightOnTechLine' in postVar:
            cb19 = OptiCheckBox(self, wx.ID_ANY, label="Output height to cut on tech line", name='OutputHeightOnTechLine')
            cb19.SetToolTipString("Output of the material height to cut on the technology line")
            sub1_1.Add(cb19, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)


        #outdated, now moved to "Output Mode" radio buttons
        #if 'SeperateNCFiles' in postVar:
        #    cb36 = OptiCheckBox(self, wx.ID_ANY, label=u"Output Seperate NC Files", name='SeperateNCFiles')
        #    cb36.SetToolTipString(u"Output Seperate NC Files for Rough, Finish and Bridgecut")
        #    sub1_1.Add(cb36, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'UseKnowledgeBase' in postVar and postVar.get('ClassName', 'undefined') == 'ACMillenniumPostOptionsDialog':
            cb251 = OptiCheckBox(self, wx.ID_ANY, label="Use knowledge base", name='UseKnowledgeBase')
            cb251.SetToolTipString("Enables the use of Ct expert databases")
            sub1_1.Add(cb251, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            cb251.Bind(wx.EVT_CHECKBOX, self.OnUseKnowledgeBaseChanged)

            if 'CopyTecToNCFolder' in postVar:
                sub1_1.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
                self.cb212 = OptiCheckBox(self, wx.ID_ANY, label="Copy .tec files to NC folder", name='CopyTecToNCFolder')
                self.cb212.SetToolTipString("?")
                sub1_1.Add(self.cb212, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)
                sub1_1.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)

            if 'CopyWirToNCFolder' in postVar:
                sub1_1.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
                self.cb213 = OptiCheckBox(self, wx.ID_ANY, label="Copy .wir Files to NC folder", name='CopyWirToNCFolder')
                self.cb213.SetToolTipString("?")
                sub1_1.Add(self.cb213, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)
                sub1_1.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)

        if 'autoConfigOff' in postVar:
            line = wx.StaticLine(self, wx.ID_ANY)       # SEEMS NOT TO WORK ---> CHECK !!!
            sub1_1.Add(line, 0, wx.EXPAND | wx.ALL, SMALLBORDER)

            self.cb250 = OptiCheckBox(self, 250, label="Turn off automatic configuration", name='autoConfigOff')
            self.cb250.SetToolTipString("?")
            sub1_1.Add(self.cb250, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            self.cb250.Bind(wx.EVT_CHECKBOX, self.OnautoConfigOff)

        if 'AWF_Control' in postVar:
            cb249 = OptiCheckBox(self, 249, label="AWF control (M61)", name='AWF_Control')
            cb249.SetToolTipString("Automatic wire feed")
            sub1_1.Add(cb249, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'TaperMode' in postVar:
            cb35 = OptiCheckBox(self, wx.ID_ANY, label="Conic mode M15P", name='TaperMode')
            cb35.SetToolTipString("?")
            sub1_1.Add(cb35, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'EmptyTankAtEnd' in postVar:
            self.EmptyTankAtEnd = OptiCheckBox(self, wx.ID_ANY, label="M35 empty tank at end of program", name='EmptyTankAtEnd')
            self.EmptyTankAtEnd.SetToolTipString("?")
            sub1_1.Add(self.EmptyTankAtEnd, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'G11SequenceOutput' in postVar:
            self.G11SequenceOutput = OptiCheckBox(self, wx.ID_ANY, label="G11 sequence output", name='G11SequenceOutput')
            self.G11SequenceOutput.SetToolTipString("?")
            sub1_1.Add(self.G11SequenceOutput, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'OutputNoTechnology' in postVar:
            self.OutputNoTechnology = OptiCheckBox(self, wx.ID_ANY, label="Output no technology", name='OutputNoTechnology')
            self.OutputNoTechnology.SetToolTipString("?")
            sub1_1.Add(self.OutputNoTechnology, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        # Techn. Import Button available for all??? or for spec. Machines???
        # Obsolete -> No longer supported at this place (email mely 12.12.2017)
#         if postVar['ClassName'] == 'ACMillenniumPostOptionsDialog' or postVar['ClassName'] == 'ACFanucPostOptionsDialog' or postVar['ClassName'] == 'RoboFilPostOptionsDialog':
#             self.btn210 = NiceButton(self, wx.ID_ANY, "Technology_Import.ico", name="BTN_TECH_IMPORT")
#             self.btn210.SetToolTipString(u"Start Technology-Database Import")
#             sub1_1.Add(self.btn210, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, SMALLBORDER)
#             self.btn210.Bind(wx.EVT_BUTTON, self.OnImportTechnologyButton)

        self.AdvancedTaperMode(sub1_1)
        #
        self.OriginChange(sub1_1)

        # Dateiende Zeichen und folgende (Rechte Hälfte)
        sub1_2 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "", name="STB_ENDOFFILE"), wx.VERTICAL)
        subsizer1.Add(sub1_2, 1, wx.EXPAND)

        if 'EofChar' in postVar:
#            cb20 = LabeledComboBox(self, wx.ID_ANY, u"End of File Character", choices=postVar['EofCharLIST'], name='EofChar')
            cb20 = LabeledComboBox(self, wx.ID_ANY, "End of file character", name='EofChar')
            cb20.SetToolTipString("?")
            sub1_2.Add(cb20, 0, wx.EXPAND)

        if 'optionalStop' in postVar:
#            cb21 = LabeledComboBox(self, wx.ID_ANY, u"Optional Stop", choices=postVar['optionalStopLIST'], name='optionalStop')
            cb21 = LabeledComboBox(self, wx.ID_ANY, "Optional stop", name='optionalStop')
            cb21.SetToolTipString("?")
            sub1_2.Add(cb21, 0, wx.EXPAND)

        if 'RegisterOutputFormat' in postVar:
#            cb29 = LabeledComboBox(self, wx.ID_ANY, u"Register Output Format", choices=postVar['RegOutFormatLIST'], name='RegisterOutputFormat')
            cb29 = LabeledComboBox(self, wx.ID_ANY, "Register output format", name='RegisterOutputFormat')
            cb29.SetToolTipString("?")
            sub1_2.Add(cb29, 0, wx.EXPAND)

        if 'G38Function' in postVar:
            cb220 = OptiCheckBox(self, 220, label="G38 function", name='G38Function')
            cb220.SetToolTipString("")
            sub1_2.Add(cb220, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'G68Function' in postVar:
            cb22 = OptiCheckBox(self, 220, label="G68 function", name='G68Function')
            cb22.SetToolTipString("Supports sharp corners with conics between two arcs; machines CT1000 or CT1020 only with console 2!")
            sub1_2.Add(cb22, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'OutputThickness' in postVar:
            cb23 = OptiCheckBox(self, 219, label="Output height for technology", name='OutputThickness')
            cb23.SetToolTipString("Output the height for technology at the startposition G92  H..")
            sub1_2.Add(cb23, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'OutputHeightOnTechLine' in postVar and postVar.get('ClassName', 'undefined') == 'StandardPostOptionsDialog':
            cb32 = OptiCheckBox(self, 233, label="Output workpiece height per cut", name='OutputHeightOnTechLine')
            cb32.SetToolTipString("Output of the material height to cut on the technology line")
            sub1_2.Add(cb32, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'OutputG20G21' in postVar:
            cb33 = OptiCheckBox(self, 234, label="Output G20/21", name='OutputG20G21')
            cb33.SetToolTipString("Output G20 = inches / G21 = metric")
            sub1_2.Add(cb33, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'UseXYROutput' in postVar:
            cb34 = OptiCheckBox(self, 235, label="Use X Y R output where possible", name='UseXYROutput')
            cb34.SetToolTipString("Use X Y R output where possible")
            sub1_2.Add(cb34, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'VariableTaperWithUV' in postVar:
            cb24 = OptiCheckBox(self, wx.ID_ANY, label="Variable taper with U/V output", name='VariableTaperWithUV')
            cb24.SetToolTipString("Variable taper with U/V output")
            sub1_2.Add(cb24, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'ConicCornerFunction' in postVar:
            cb26 = OptiCheckBox(self, 207, label="Offset correction for conic (G64)", name='ConicCornerFunction')
            cb26.SetToolTipString("Calculates 3D-Offset with conical Programs")
            sub1_2.Add(cb26, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'ReThreading' in postVar:
            cb27 = OptiCheckBox(self, 217, label="Repeated wire threading (M61)", name='ReThreading')
            cb27.SetToolTipString("Position of Rethreading M61")
            sub1_2.Add(cb27, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'RemoteAlarm' in postVar:
            cb28 = OptiCheckBox(self, 218, label="Remote alarm before stop (M93/M94)", name='RemoteAlarm')
            cb28.SetToolTipString("Remote Alarm Function")
            sub1_2.Add(cb28, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'OutputFlushing' in postVar:
            cb38 = OptiCheckBox(self, 238, label="Output flushing (M07/M08)", name='OutputFlushing')
            cb38.SetToolTipString("")
            sub1_2.Add(cb38, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'CornerStrategy' in postVar:
            self.cb222 = OptiCheckBox(self, 222, label="Corner strategy (G60)", name='CornerStrategy')
            self.cb222.SetToolTipString("Calls the strategy for corners or small radii")
            sub1_2.Add(self.cb222, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            self.cb222.Bind(wx.EVT_CHECKBOX, self.OnCornerStrategyChanged)

            """
            itemstrings = [ "Prg. Header", "After Leadin Line" ]
            cb30 = LabeledComboBox(self, wx.ID_ANY, u" ", choices=itemstrings, name='CornerStrategyMode')
            cb30.SetToolTipString(u"?")
            sub1_2.Add(cb30, 0, wx.EXPAND)
            cb30.Enable(postVar['CornerStrategy'])
            """

            sub1_2.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
            rb225 = OptiRadioButton(self, wx.ID_ANY, label="Prg. header", style = wx.RB_GROUP, name="CornerStrategyHeader")
            rb225.SetToolTipString("Output of G60 once in the header")
            sub1_2.Add(rb225, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)

            sub1_2.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
            rb226 = OptiRadioButton(self, wx.ID_ANY, label="After leadin line", name="CornerStrategyLeadin")
            rb226.SetToolTipString("Output of G60 before each leadon and G61 after each leadoff")
            sub1_2.Add(rb226, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)

            sub1_2.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)

        if 'StrategyForRoughcuts' in postVar:
            cb31 = OptiCheckBox(self, 208, label="Protection strategy for rough cut", name='StrategyForRoughcuts')
            cb31.SetToolTipString("Enables straight leadon to an arc in conical programs for machines CT100 and CT1000 (M29)")
            sub1_2.Add(cb31, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'OutputTechnologyISO' in postVar:
            cb32 = OptiCheckBox(self, 214, label="Output technology in ISO-file", name='OutputTechnologyISO')
            cb32.SetToolTipString("Output TEC name in ISO File when CMD output is not active")
            sub1_2.Add(cb32, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'UseKnowledgeBase' in postVar and postVar.get('ClassName', 'undefined') == 'StandardPostOptionsDialog':
            cb251 = OptiCheckBox(self, wx.ID_ANY, label="Technology database", name='UseKnowledgeBase')
            cb251.SetToolTipString("Enables the use of Ct expert databases")
            sub1_2.Add(cb251, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            cb251.Bind(wx.EVT_CHECKBOX, self.OnUseKnowledgeBaseChanged)

            if 'CopyTecToNCFolder' in postVar:
                sub1_2.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
                self.cb212 = OptiCheckBox(self, 212, label="Copy TEC file to NC folder", name='CopyTecToNCFolder')
                self.cb212.SetToolTipString("?")
                sub1_2.Add(self.cb212, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)
                sub1_2.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)

        if 'GeometryStrategy' in postVar:
            self.cb231 = OptiCheckBox(self, wx.ID_ANY, label="Geometry strategy", name='GeometryStrategy')
            self.cb231.SetToolTipString("?")
            sub1_2.Add(self.cb231, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            self.cb231.Bind(wx.EVT_CHECKBOX, self.OnGeometryStrategyChanged)

            sub1_2.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
            self.rb232 = OptiRadioButton(self, wx.ID_ANY, "M23", style = wx.RB_GROUP, name="GeometryStrategyM23")
            self.rb232.SetToolTipString("M23")
            sub1_2.Add(self.rb232, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)

            sub1_2.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
            self.rb233 = OptiRadioButton(self, wx.ID_ANY, label="M24", name="GeometryStrategyM24")
            self.rb233.SetToolTipString("?")
            sub1_2.Add(self.rb233, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)

            sub1_2.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)

        if 'WireStrategy' in postVar:
            self.cb235 = OptiCheckBox(self, wx.ID_ANY, label="Wire strategy", name='WireStrategy')
            self.cb235.SetToolTipString("?")
            sub1_2.Add(self.cb235, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            self.cb235.Bind(wx.EVT_CHECKBOX, self.OnWireStrategyChanged)

            sub1_2.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
            self.rb236 = OptiRadioButton(self, wx.ID_ANY, "M27", style = wx.RB_GROUP, name="WireStrategyM27")
            self.rb236.SetToolTipString("?")
            sub1_2.Add(self.rb236, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)

            sub1_2.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
            self.rb237 = OptiRadioButton(self, wx.ID_ANY, label="M28 (step 1)", name="WireStrategyM28")
            self.rb237.SetToolTipString("?")
            sub1_2.Add(self.rb237, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)

            sub1_2.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
            self.rb238 = OptiRadioButton(self, wx.ID_ANY, label="M29 (step 2)", name="WireStrategyM29")
            self.rb238.SetToolTipString("?")
            sub1_2.Add(self.rb238, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)

            sub1_2.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)

        if 'AdditionalOffsetGeometry' in postVar:
            self.cb345 = OptiCheckBox(self, wx.ID_ANY, label="Additional Offset in Geometry", name='AdditionalOffsetGeometry')
            self.cb345.SetToolTipString("?")
            sub1_2.Add(self.cb345, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            
        if 'CutWireAtEndOfProgram' in postVar:
            self.cb348 = OptiCheckBox(self, wx.ID_ANY, label="Cut Wire At End Of Program", name='CutWireAtEndOfProgram')
            self.cb348.SetToolTipString("?")
            sub1_2.Add(self.cb348, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'NoSemicolon' in postVar:
            self.NoSemicolon = OptiCheckBox( self, wx.ID_ANY, label="No EOB character (;)", name='NoSemicolon' )
            self.NoSemicolon.SetToolTipString("Not output semicolon at end of line")
            sub1_2.Add( self.NoSemicolon, 0, wx.ALL, SMALLBORDER )

        if 'ConicityCompensationM11' in postVar:
            self.ConicityCompensationM11 = OptiCheckBox(self, wx.ID_ANY, label="Conicity compensation with M11", name='ConicityCompensationM11')
            self.ConicityCompensationM11.SetToolTipString("?")
            sub1_2.Add(self.ConicityCompensationM11, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)
            
        if 'LightOnAtStop' in postVar:  # and postVar['ClassName'] == 'RoboFilPostOptionsDialog':
            self.cb346 = OptiCheckBox(self, wx.ID_ANY, label="Light on at stop", name='LightOnAtStop')
            self.cb346.SetToolTipString("?")
            sub1_2.Add(self.cb346, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)

        if 'DrawIso' in postVar:        # and postVar['ClassName'] == 'RoboFilPostOptionsDialog':
            self.cb347 = OptiCheckBox(self, wx.ID_ANY, label="Draw ISO", name='DrawIso')
            self.cb347.SetToolTipString("?")
            sub1_2.Add(self.cb347, 0, wx.ALIGN_LEFT | wx.ALL, SMALLBORDER)


        #Database Stuff
        ##
        vboxDB = wx.StaticBoxSizer( StaticBox( self, wx.ID_ANY, "Technology database", name='STB_TECHDB') , wx.VERTICAL )
        
        self.staticDbPath = TextField( self, wx.ID_ANY, u"Database path:", wx.DefaultPosition, wx.DefaultSize, 0, name='staticDbPath')
        self.staticDbPath.Wrap( -1 )
        vboxDB.Add( self.staticDbPath, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 1)
        
        hDBPath = wx.BoxSizer(wx.HORIZONTAL)
        self.DbPathField = EditField( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, style=wx.TE_READONLY, behaviour=BEHAVIOUR.ALPHANUMERIC , name='DbPathField' )
#         def NewGetTool(self):
#             return self.GetValue()
        self.DbPathField.SetToolTipString("Database Path")
        self.DbPathField.Enable(False)
#         self.DbPathField.GetToolTipString = MethodType(NewGetTool, self.DbPathField)
        hDBPath.Add(self.DbPathField, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 1)

#         self.btnOpenDbPathField = NiceButton( self, wx.ID_ANY, OPEN_FILE_ICON, disabledButtonICO=OPEN_FILE_DISABLED_ICON, name='btnOpenDbPathField', toolTipString="Select the database")
#         hDBPath.Add(self.btnOpenDbPathField,  0, wx.ALL, 0)
#         if hasattr(self, "OnOpenDbPathFieldClicked"):
#             self.btnOpenDbPathField.Bind( wx.EVT_BUTTON, self.OnOpenDbPathFieldClicked)
        
        vboxDB.Add(hDBPath, 0, wx.ALL|wx.EXPAND, 1)
        
        self.ManageTechnology = NormalButton( self, wx.ID_ANY, "Manage technology", pos=wx.DefaultPosition, size=wx.DefaultSize, name='ManageTechnology' )
        vboxDB.Add( self.ManageTechnology, 0, wx.ALL, 1)
        self.ManageTechnology.Bind( wx.EVT_BUTTON, self.OnManageTechnologyClicked )
        
        self.staticTechTable = TextField( self, wx.ID_ANY, "Technology table", wx.DefaultPosition, wx.DefaultSize, 0, name='staticTechTable' )
        self.staticTechTable.Wrap( -1 )
        vboxDB.Add( self.staticTechTable, 0, wx.ALL, 2)
        self.TechTableField = EditField( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, style=wx.TE_READONLY, behaviour=BEHAVIOUR.ALPHANUMERIC , name='TechTableField' )
        vboxDB.Add( self.TechTableField, 0, wx.ALL|wx.EXPAND, 3)
        
        self.staticWireTable = TextField( self, wx.ID_ANY, "Wire table", wx.DefaultPosition, wx.DefaultSize, 0, name='staticWireTable' )
        self.staticWireTable.Wrap( -1 )
        vboxDB.Add( self.staticWireTable, 0, wx.ALL, 2)
        self.WireTechTableField = EditField( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, style=wx.TE_READONLY, behaviour=BEHAVIOUR.ALPHANUMERIC , name='WireTechTableField' )
        vboxDB.Add( self.WireTechTableField, 0, wx.ALL|wx.EXPAND, 3)
        
        #self.staticTechField4 = TextField( self, wx.ID_ANY, u"MyLabel", wx.DefaultPosition, wx.DefaultSize, 0, name='staticTechField4' )
        #self.staticTechField4.Wrap( -1 )
        #vboxDB.Add( self.staticTechField4, 0, wx.ALL, SMALLBORDER )
        #self.TechField4 = EditField( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, style=wx.TE_READONLY, behaviour=BEHAVIOUR.ALPHANUMERIC , name='TechField4' )
        #vboxDB.Add( self.TechField4, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.EXPAND, SMALLBORDER )
        
        sub1_2.Add( vboxDB, 0, wx.EXPAND, SMALLBORDER )                   

        self.Layout()       

    def enablePage(self, clearStatusBar=True):
        """ Enables/disables the widgets of this page depending on the model selected."""

        self.AutomaticThreadingChanged(clearStatusBar=clearStatusBar)

        # take the settings from the choosen model (Sub-Dictionary in ModelSettings)
        modelSet = GetModelSetting()
        
        self.enableWidget('OutputPercSignBeforeMain',   None, modelSet)
        self.enableWidget('AutomaticThreading',   None, modelSet)
        self.enableWidget('TParameter',           ['AutomaticThreading'],       modelSet)
        self.enableWidget('ThreadInGap',          ['AutomaticThreading'],       modelSet)
        self.enableWidget('NoThreadingOutput',    ['AutomaticThreading'],       modelSet, invert=True)
        self.enableWidget('GeneratorOut',         None, modelSet)
        self.enableWidget('CutWireAtStop',        ['GeneratorOut'],             modelSet)

        self.enableWidget('GeneratorOnOffBeforeChange', None, modelSet)
        self.enableWidget('GeneratorOnOffByFigur',      None, modelSet)
        self.enableWidget('GeneratorOffByArcLeadOff',   None, modelSet)
        self.enableWidget('GeneratorSettingSeparate',   None, modelSet)
        self.enableWidget('PathCorrectionAfterLeadOn',   None, modelSet)
        self.enableWidget('DWell',                ['GeneratorSettingSeparate'], modelSet)
        self.enableWidget('DWellTime',            ['GeneratorSettingSeparate', 'DWell'], modelSet)
        self.enableWidget('CornerStrategy',       None, modelSet)
        self.enableWidget('CornerStrategyHeader', ['CornerStrategy'],           modelSet)
        self.enableWidget('CornerStrategyLeadin', ['CornerStrategy'], modelSet)
        self.enableWidget('StrategyForRoughcuts', None, modelSet)
        self.enableWidget('OutputTechnologyISO',  None, modelSet)

        self.enableWidget('Subprograms',          None, modelSet)
        self.enableWidget('OutputSubRotated',     ['Subprograms'], modelSet)
        self.enableWidget('OutputSubScaled',      ['Subprograms'], modelSet)
        self.enableWidget('OutputSubMirrored',    ['Subprograms'], modelSet)
        self.enableWidget('OutputSubInExtraFiles',['Subprograms'], modelSet)

        self.enableWidget('OutputHeightOnTechLine', None, modelSet)
        self.enableWidget('G38Function',            None, modelSet)
        self.enableWidget('G68Function',            None, modelSet)
        self.enableWidget('OutputThickness',        None, modelSet)
        self.enableWidget('ConicCornerFunction',    None, modelSet)
        self.enableWidget('ReThreading',            None, modelSet)
        self.enableWidget('RemoteAlarm',            None, modelSet)
        self.enableWidget('OutputFlushing',         None, modelSet)

        self.enableWidget('UseKnowledgeBase',     None, modelSet)
        self.enableWidget('CopyTecToNCFolder',    ['UseKnowledgeBase'], modelSet)
        self.enableWidget('CopyWirToNCFolder',    ['UseKnowledgeBase'], modelSet)

        self.enableWidget('GeometryStrategyM23',  ['GeometryStrategy'], modelSet)
        self.enableWidget('GeometryStrategyM24',  ['GeometryStrategy'], modelSet)

        self.enableWidget('WireStrategyM27',      ['WireStrategy'], modelSet)
        self.enableWidget('WireStrategyM28',      ['WireStrategy'], modelSet)
        self.enableWidget('WireStrategyM29',      ['WireStrategy'], modelSet)

        self.enableWidget('AdditionalOffsetGeometry', None, modelSet)
        self.enableWidget('CutWireAtEndOfProgram', None, modelSet)
        self.enableWidget('PrepareWorkpieceForTilting', None, modelSet)
        self.enableWidget('ConicityCompensationM11',  None, modelSet)
        self.enableWidget('LightOnAtStop',  None, modelSet)
        self.enableWidget('DrawIso',  None, modelSet)

    # is better in the base class -> other machines may have own GroupPage2
    #def enableOnce(self):
    #    pass
    
    def UpdateDatabaseFields(self, ProfileName=None):
        """
        The method is for update the layout when the database setting changes.
        this is the method of page, mean it can directly access the widget, using method "SetValue()" 
        """
        pass
        
    def enableWidgetf(self, enable):
        pass

    def OnautoConfigOff(self, event):  # @UnusedVariable
        self.autoConfigOff( self.cb250.GetValue() )

    def OngeneratorOutChanged(self, event):  # @UnusedVariable
#        postVar['GeneratorOut'] = self.cb223.GetValue()
        self.enablePage()

    def OnGeneratorSettingSeparateChanged(self, event):  # @UnusedVariable
#        postVar['GeneratorSettingSeparate'] = self.cb206.GetValue()
        self.enablePage()
        
    def PathCorrectionAfterLeadOnChanged(self, event):  # @UnusedVariable
#        postVar['GeneratorSettingSeparate'] = self.cb206.GetValue()
        self.enablePage()

    def OndWellChanged(self, event):  # @UnusedVariable
#        wdg = event.GetEventObject()
#        postVar['DWell'] = wdg.GetValue()
        self.enablePage()

    def OnCornerStrategyChanged(self, event):  # @UnusedVariable
#        postVar['CornerStrategy'] = self.cb222.GetValue()
        self.enablePage()

    def OnUseKnowledgeBaseChanged(self, event):  # @UnusedVariable
#        wdg = event.GetEventObject()
#        postVar['UseKnowledgeBase'] = wdg.GetValue()
        self.enablePage()

    def OnGeometryStrategyChanged(self, event):  # @UnusedVariable
#        postVar['GeometryStrategy'] = self.cb231.GetValue()
        self.enablePage()

    def OnWireStrategyChanged(self, event):  # @UnusedVariable
#        postVar['WireStrategy'] = self.cb235.GetValue()
        self.enablePage()

#     def OnOutputUserHeader(self, event):  # @UnusedVariable
# #        postVar['OutputUserDefinedHeader'] = self.cb340.GetValue()
#         self.enablePage()

#     def OnSelectUserDefinedHeader(self, event):
#         BaseGroupPage.SelectUserDefinedHeader(self, event)

    def OnImportTechnologyButton(self, event):
        BaseGroupPage.ImportTechnology(self, event)

class GroupPage3(BaseGroupPage):
    #SIMULATION PAGE
    def __init__(self, parent, id, name="_GRP_PAGE3"):  # @ReservedAssignment
        BaseGroupPage.__init__(self, parent, id, name=name)

        self.createPage()

    def createPage(self):      # Third Side (Simulation und Weitere)
        AngleIsEditable = True
        RangeIsEditable = True
        #
        # Maximale Konizität
        subsizer1 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Taper", name="STB_TAPER"), wx.HORIZONTAL)
        self.sizer.Add(subsizer1, 0, wx.EXPAND)
        ef4 = LabeledEditField(self, wx.ID_ANY, "Maximum taper", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.ANGLE_VALUE, name='TaperMax', propChoice=1)
        ef4.SetToolTipString("Maximum taper value")
        ef4.SetEditable(AngleIsEditable)
        subsizer1.Add(ef4, 1, wx.EXPAND)
        subsizer1.Add(SPACER, 1)

        # Maximaler Verfahrweg
        # Min-Max-Values
        if postVar.get('Min_Max_Values') ==  True:
            leftSideSubsizer = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Machine range", name="STB_UVCONTROL"), wx.HORIZONTAL)
            self.sizer.Add(leftSideSubsizer, 0, wx.EXPAND)
            sub2_1 = wx.BoxSizer(wx.VERTICAL)
            leftSideSubsizer.Add(sub2_1, 1)
            ef5 = LabeledEditField(self, wx.ID_ANY, "Min X", min=-10000.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='xMin', propChoice=1)
            ef5.SetToolTipString("Travellimits minimum value in X")
            ef5.SetEditable(RangeIsEditable)
            sub2_1.Add(ef5, 0, wx.EXPAND)
            ef6 = LabeledEditField(self, wx.ID_ANY, "Min Y", min=-10000.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='yMin', propChoice=1)
            ef6.SetToolTipString("Travellimits minimum value in Y")
            ef6.SetEditable(RangeIsEditable)
            sub2_1.Add(ef6, 0, wx.EXPAND)
            ef7 = LabeledEditField(self, wx.ID_ANY, u"Min Z", min=-10000.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='zMin', propChoice=1)
            ef7.SetToolTipString(u"Travellimits Minimum Value in Z")
            ef7.SetEditable(False)      # for Z-Limits only Max value
            sub2_1.Add(ef7, 0, wx.EXPAND)
            ef8 = LabeledEditField(self, wx.ID_ANY, "Min U", min=-10000.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='uMin', propChoice=1)
            ef8.SetToolTipString("Travellimits minimum value in U")
            ef8.SetEditable(RangeIsEditable)
            sub2_1.Add(ef8, 0, wx.EXPAND)
            ef9 = LabeledEditField(self, wx.ID_ANY, "Min V", min=-10000.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='vMin', propChoice=1)
            ef9.SetToolTipString("Travellimits minimum value in V")
            ef9.SetEditable(RangeIsEditable)
            sub2_1.Add(ef9, 0, wx.EXPAND)

            sub2_2 = wx.BoxSizer(wx.VERTICAL)
            leftSideSubsizer.Add(sub2_2, 1)
            ef10 = LabeledEditField(self, wx.ID_ANY, "Max X", min=-10000.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='xMax', propChoice=1)
            ef10.SetToolTipString("Travellimits maximum value in X")
            ef10.SetEditable(RangeIsEditable)
            sub2_2.Add(ef10, 0, wx.EXPAND)
            ef11 = LabeledEditField(self, wx.ID_ANY, "Max Y", min=-10000.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='yMax', propChoice=1)
            ef11.SetToolTipString("Travellimits maximum value in Y")
            ef11.SetEditable(RangeIsEditable)
            sub2_2.Add(ef11, 0, wx.EXPAND)
            ef12 = LabeledEditField(self, wx.ID_ANY, "Max Z", min=-10000.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='zMax', propChoice=1)
            ef12.SetToolTipString("Travellimits maximum value in Z")
            ef12.SetEditable(RangeIsEditable)
            sub2_2.Add(ef12, 0, wx.EXPAND)
            ef13 = LabeledEditField(self, wx.ID_ANY, "Max U", min=-10000.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='uMax', propChoice=1)
            ef13.SetToolTipString("Travellimits maximum value in U")
            ef13.SetEditable(RangeIsEditable)
            sub2_2.Add(ef13, 0, wx.EXPAND)
            ef14 = LabeledEditField(self, wx.ID_ANY, "Max V", min=-10000.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='vMax', propChoice=1)
            ef14.SetToolTipString("Travellimits maximum value in V")
            ef14.SetEditable(RangeIsEditable)
            sub2_2.Add(ef14, 0, wx.EXPAND)
            
            # correct (for the first) the label texts
            ef5.SetLabel("Min X")
            ef6.SetLabel("Min Y")
            ef7.SetLabel("Min Z")
            ef8.SetLabel("Min U")
            ef9.SetLabel("Min V")
            ef10.SetLabel("Max X")
            ef11.SetLabel("Max Y")
            ef12.SetLabel("Max Z")
            ef13.SetLabel("Max U")
            ef14.SetLabel("Max V")
            #
        else:   # range presentation (instead of Min-Max)
            leftSideSubsizer = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Machine range", name="STB_UVCONTROL"), wx.HORIZONTAL)
            self.sizer.Add(leftSideSubsizer, 0, wx.EXPAND)
            sub2_1 = wx.BoxSizer(wx.VERTICAL)
            leftSideSubsizer.Add(sub2_1, 1)
            ef5 = LabeledEditField(self, wx.ID_ANY, "X-Range", min=0.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='xMax', propChoice=1)
            ef5.SetToolTipString("Travellimits range in X")
            ef5.SetEditable(RangeIsEditable)
            sub2_1.Add(ef5, 1, wx.EXPAND)
            ef6 = LabeledEditField(self, wx.ID_ANY, "Y-Range", min=0.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='yMax', propChoice=1)
            ef6.SetToolTipString("Travellimits range in Y")
            ef6.SetEditable(RangeIsEditable)
            sub2_1.Add(ef6, 1, wx.EXPAND)
            ef7 = LabeledEditField(self, wx.ID_ANY, "Z-Max", min=0.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='zMax', propChoice=1)
            ef7.SetToolTipString("Travellimits maximum value in Z")
            ef7.SetEditable(RangeIsEditable)
            sub2_1.Add(ef7, 1, wx.EXPAND)
            ef13 = LabeledEditField(self, wx.ID_ANY, "U-Range", min=0.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='uMax', propChoice=1)
            ef13.SetToolTipString("Travellimits maximum value in U")
            ef13.SetEditable(RangeIsEditable)
            sub2_1.Add(ef13, 1, wx.EXPAND)
            ef14 = LabeledEditField(self, wx.ID_ANY, "V-Range", min=0.0, max=10000.0, behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='vMax', propChoice=1)
            ef14.SetToolTipString("Travellimits maximum value in V")
            ef14.SetEditable(RangeIsEditable)
            sub2_1.Add(ef14, 1, wx.EXPAND)

            leftSideSubsizer.Add(SPACER, 1)

        # Rotary-Axis
        if 'RotaryAxis' in postVar:
            subsizer3 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Rotary-axis", name="STB_ROTARYAXES"), wx.HORIZONTAL)
            self.sizer.Add(subsizer3, 0, wx.EXPAND)
            self.sub3_1 = wx.BoxSizer(wx.VERTICAL)
            subsizer3.Add(self.sub3_1, 1, wx.EXPAND)
            sub3_2 = wx.BoxSizer(wx.VERTICAL)
            subsizer3.Add(sub3_2, 1, wx.EXPAND)

#            self.ch1 = LabeledComboBox(self, wx.ID_ANY, u"No. of axes", choices=postVar['RotaryAxisLIST'], name='RotaryAxis')
            self.ch1 = LabeledComboBox(self, wx.ID_ANY, "No. of axes", name='RotaryAxis')
            self.ch1.SetToolTipString("?")
            self.sub3_1.Add(self.ch1, 0, wx.EXPAND)
            self.Bind(wx.EVT_CHOICE, self.OnRotaryAxesChanged, self.ch1.cb)

#            self.sub3_1.Add(SPACER, 1, wx.EXPAND)
            self.space1 = wx.StaticText(self, wx.ID_ANY)    # as spacer (can be hidden)
            self.sub3_1.Add(self.space1)
#            self.ch2 = LabeledComboBox(self, wx.ID_ANY, u"Alignment axis 1", choices=postVar['RotaryAlignment1LIST'], name='RotaryAlignment1')
            self.ch2 = LabeledComboBox(self, wx.ID_ANY, "Alignment axis 1", name='RotaryAlignment1')
            self.ch2.SetToolTipString("?")
            self.sub3_1.Add(self.ch2, 0, wx.EXPAND)
            self.ef15 = LabeledEditField(self, wx.ID_ANY, "Distance to alignment 1", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='RotaryDistance1')
            self.ef15.SetToolTipString("?")
            self.sub3_1.Add(self.ef15, 0, wx.EXPAND)
            self.ef16 = LabeledEditField(self, wx.ID_ANY, "Z-value 1", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='RotaryZValue1')
            self.ef16.SetToolTipString("?")
            self.sub3_1.Add(self.ef16, 0, wx.EXPAND)
            if 'RotaryMaxRot1' in postVar:
                self.ef17 = LabeledEditField(self, wx.ID_ANY, "max rot. 1", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.ANGLE_VALUE, name='RotaryMaxRot1')
                self.ef17.SetToolTipString("?")
            self.sub3_1.Add(self.ef17, 0, wx.EXPAND)

#            self.sub3_1.Add(SPACER, 1, wx.EXPAND)
            self.space2 = wx.StaticText(self, wx.ID_ANY)    # as spacer (can be hidden)
            self.sub3_1.Add(self.space2)
#            self.ch3 = LabeledComboBox(self, wx.ID_ANY, u"Alignment axis 2", choices=postVar['RotaryAlignment2LIST'], name='RotaryAlignment2')
            self.ch3 = LabeledComboBox(self, wx.ID_ANY, "Alignment axis 2", name='RotaryAlignment2')
            self.ch3.SetToolTipString("?")
            self.sub3_1.Add(self.ch3, 0, wx.EXPAND)
            self.ef18 = LabeledEditField(self, wx.ID_ANY, "Distance to alignment 2", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='RotaryDistance2')
            self.ef18.SetToolTipString("?")
            self.sub3_1.Add(self.ef18, 0, wx.EXPAND)
            self.ef19 = LabeledEditField(self, wx.ID_ANY, "Z-value 2", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE, name='RotaryZValue2')
            self.ef19.SetToolTipString("?")
            self.sub3_1.Add(self.ef19, 0, wx.EXPAND)
            if 'RotaryMaxRot2' in postVar:
                self.ef20 = LabeledEditField(self, wx.ID_ANY, "max rot. 2", behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.ANGLE_VALUE, name='RotaryMaxRot2')
                self.ef20.SetToolTipString("?")
            self.sub3_1.Add(self.ef20, 0, wx.EXPAND)

            self.AxesDialog(postVar['RotaryAxis'])

        # Nozzles
        if 'UpperNozzleTypeDefault' in postVar and 'LowerNozzleTypeDefault' in postVar:
            subsizer4 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Nozzles", name="STB_NOZZLES"), wx.VERTICAL)
            self.sizer.Add(subsizer4, 0, wx.EXPAND)

##            grid = wx.GridSizer(rows=2, cols=5, hgap=0, vgap=2)
            grid = wx.BoxSizer(wx.HORIZONTAL)
            subsizer4.Add(grid, 0, wx.EXPAND)

            grid.Add(wx.StaticText(self, wx.ID_ANY, getText("Upper nozzle", "STT_UPPERNOZZLE"), name="STT_UPPERNOZZLE"), 0, wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, SMALLBORDER)
            self.rb20 = OptiRadioButton(self, wx.ID_ANY, label="Default", style = wx.RB_GROUP, name='UpperNozzleTypeDefault')
            self.rb20.SetToolTipString("?")
            self.rb20.Bind(wx.EVT_RADIOBUTTON, self.OnSelectNozzleType)
            grid.Add(self.rb20, 0, wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, SMALLBORDER)
            self.rb21 = OptiRadioButton(self, wx.ID_ANY, "STL file", name='UpperNozzleTypeSTL')
            self.rb21.SetToolTipString("?")
            self.rb21.Bind(wx.EVT_RADIOBUTTON, self.OnSelectNozzleType)
            grid.Add(self.rb21, 0, wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, SMALLBORDER)
            self.ef21 = EditField(self, wx.ID_ANY, behaviour=BEHAVIOUR.ALPHANUMERIC, name='UpperNozzleSTLFile')
            self.ef21.SetToolTipString("Upper nozzle STL file name")
            grid.Add(self.ef21, 0, wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, SMALLBORDER)

            self.btnNozzle1 = NiceButton(self, wx.ID_ANY, OPEN_FILE_ICON, name='UpperNozzle')
            self.btnNozzle1.SetToolTipString("Browse for user defined nozzle file")
            self.btnNozzle1.Bind(wx.EVT_BUTTON, self.OnSelectNozzleFile)
            grid.Add(self.btnNozzle1, 0, wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, SMALLBORDER)

            grid = wx.BoxSizer(wx.HORIZONTAL)
            subsizer4.Add(grid, 0, wx.EXPAND)
            
            grid.Add(wx.StaticText(self, wx.ID_ANY, getText("Lower nozzle", "STT_LOWERNOZZLE"), name="STT_LOWERNOZZLE"), 0, wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, SMALLBORDER)
            self.rb22 = OptiRadioButton(self, wx.ID_ANY, label="Default", style = wx.RB_GROUP, name='LowerNozzleTypeDefault')
            self.rb22.SetToolTipString("?")
            self.rb22.Bind(wx.EVT_RADIOBUTTON, self.OnSelectNozzleType)
            grid.Add(self.rb22, 0, wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, SMALLBORDER)
            self.rb23 = OptiRadioButton(self, wx.ID_ANY, "STL file", name='LowerNozzleTypeSTL')
            self.rb23.SetToolTipString("?")
            self.rb23.Bind(wx.EVT_RADIOBUTTON, self.OnSelectNozzleType)
            grid.Add(self.rb23, 0, wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, SMALLBORDER)
            self.ef22 = EditField(self, wx.ID_ANY, behaviour=BEHAVIOUR.ALPHANUMERIC, name='LowerNozzleSTLFile')
            self.ef22.SetToolTipString("Lower nozzle STL file name")
            grid.Add(self.ef22, 0, wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, SMALLBORDER)
            self.btnNozzle2 = NiceButton(self, wx.ID_ANY, OPEN_FILE_ICON, name='LowerNozzle')
            self.btnNozzle2.SetToolTipString("Browse for user defined nozzle file")
            self.btnNozzle2.Bind(wx.EVT_BUTTON, self.OnSelectNozzleFile)
            grid.Add(self.btnNozzle2, 0, wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER, SMALLBORDER)

            self.NozzlesDialog()

    def NozzlesDialog(self):
        """ here we manage which controls of the nozzles dialog are enabled """
        logger.info("%s%s%s%s" % (self.__class__.__name__ , ".NozzlesDialog", postVar['UpperNozzleTypeSTL'],postVar['LowerNozzleTypeSTL']))
        if postVar['UpperNozzleTypeDefault']:
            self.ef21.SetValue('DEFAULT')
        else:
            self.ef21.SetValue(postVar['UpperNozzleSTLFile'])
        self.ef21.Enable(postVar['UpperNozzleTypeSTL'])
        self.btnNozzle1.Enable(postVar['UpperNozzleTypeSTL'])
        if postVar['LowerNozzleTypeDefault']:
            self.ef22.SetValue('DEFAULT')
        else:
            self.ef22.SetValue(postVar['LowerNozzleSTLFile'])
        self.ef22.Enable(postVar['LowerNozzleTypeSTL'])
        self.btnNozzle2.Enable(postVar['LowerNozzleTypeSTL'])

    def AxesDialog(self, axis='0'):
        """ here we manage which controls of the axes dialog are shown """
        if axis == '0':
            self.sub3_1.Show(self.space1, False)
            self.sub3_1.Show(self.space2, False)
            self.sub3_1.Show(self.ch2, False)
            self.sub3_1.Show(self.ch3, False)
            self.sub3_1.Show(self.ef15, False)
            self.sub3_1.Show(self.ef16, False)
            self.sub3_1.Show(self.ef17, False)
            self.sub3_1.Show(self.ef18, False)
            self.sub3_1.Show(self.ef19, False)
            self.sub3_1.Show(self.ef20, False)
        elif axis == '1':
            self.sub3_1.Show(self.space1, True)
            self.sub3_1.Show(self.space2, False)
            self.sub3_1.Show(self.ch2, True)
            self.sub3_1.Show(self.ch3, False)
            self.sub3_1.Show(self.ef15, True)
            self.sub3_1.Show(self.ef16, True)
            self.sub3_1.Show(self.ef17, True)
            self.sub3_1.Show(self.ef18, False)
            self.sub3_1.Show(self.ef19, False)
            self.sub3_1.Show(self.ef20, False)
        elif axis == '2':
            self.sub3_1.Show(self.space1, True)
            self.sub3_1.Show(self.space2, True)
            self.sub3_1.Show(self.ch2, True)
            self.sub3_1.Show(self.ch3, True)
            self.sub3_1.Show(self.ef15, True)
            self.sub3_1.Show(self.ef16, True)
            self.sub3_1.Show(self.ef17, True)
            self.sub3_1.Show(self.ef18, True)
            self.sub3_1.Show(self.ef19, True)
            self.sub3_1.Show(self.ef20, True)

            self.sub3_1.Layout()

    def OnSelectNozzleType(self, event):
        evtObjName  = event.GetEventObject().GetName()

        if evtObjName == 'UpperNozzleTypeDefault' or evtObjName == 'UpperNozzleTypeSTL':
            postVar['UpperNozzleTypeDefault'] = self.rb20.GetValue()
            postVar['UpperNozzleTypeSTL']     = self.rb21.GetValue()
        elif evtObjName == 'LowerNozzleTypeDefault' or evtObjName == 'LowerNozzleTypeSTL':
            postVar['LowerNozzleTypeDefault'] = self.rb22.GetValue()
            postVar['LowerNozzleTypeSTL']     = self.rb23.GetValue()

        self.NozzlesDialog()

    def OnSelectNozzleFile(self, event):
        # evtObjClass = event.GetEventObject().__class__.__name__
        evtObjName  = event.GetEventObject().GetName()
        # evtObjId    = event.GetEventObject().GetId()

        # This is how you pre-establish a file filter so that the dialog
        # only shows the extension(s) you want it to.
        wildcard = "(*.stl)|*.stl"
#                   "SPAM files (*.spam)|*.spam|"    \
#                   "Egg file (*.egg)|*.egg|"        \
#                   "All files (*.*)|*.*"
        dlg = wx.FileDialog(self, message=getMessageW("Choose file for ",PYTHON_MESSAGES,11) + evtObjName,
                            defaultDir=postPath,
                            #defaultFile=postVar['UpperNozzleSTLFile'] if evtObjName == 'UpperNozzleSTLFile' else postVar['LowerNozzleSTLFile'],
                            defaultFile=wx.EmptyString,
                            wildcard=wildcard,
                            style=wx.FD_OPEN
                            )
        # Show the dialog and retrieve the user response. If it is the OK response, process the data.
        #
        if dlg.ShowModal() == wx.ID_OK:
            if evtObjName == 'UpperNozzle':
                postVar['UpperNozzleSTLFile'] = dlg.GetPath()
                self.ef21.SetValue(postVar['UpperNozzleSTLFile'])
            elif evtObjName == 'LowerNozzle':
                postVar['LowerNozzleSTLFile'] = dlg.GetPath()
                self.ef22.SetValue(postVar['LowerNozzleSTLFile'])

            if _DEBUG:
                local_dir  = dlg.GetDirectory()
                file_name = dlg.GetFilename()   
                if logger: logger.info("You selected directory: %s" %  local_dir)
                if logger: logger.info("You selected file: %s" %  file_name)
                if logger: logger.info("You selected path: %s" %  dlg.GetPath())

    def OnRotaryAxesChanged(self, event):
        val = event.GetEventObject().GetStringSelection()

#        postVar['RotaryAxis'] = val

        self.AxesDialog(val)

        self.Fit()
        self.GetParent().Fit()
        self.GetGrandParent().Fit()
        self.GetParent().GetGrandParent().Fit()

        if postVar.get('freezeMaxSize') != True:
            wx.CallAfter(self.GetParent().GetGrandParent().ResizeFPB)



class GroupPage4(BaseGroupPage):
    """ we are a BasePanel. """
    #SPECIAL PAGE PP SPECIFIC (e.g. CMD Output)
    def __init__(self, parent, id, name="_GRP_PAGE4"):  # @ReservedAssignment
        BaseGroupPage.__init__(self, parent, id, name=name)

        self.createPage()

    def createPage(self):
        """ EXPERIMENTAL """

        # row 1
        self.sizer.Add(wx.StaticText(self, wx.ID_ANY, "Name"))
        textCtrl = wx.TextCtrl(self, wx.ID_ANY, "Your name here")
        textCtrl.SetToolTipString("Tooltip")
        self.sizer.Add(textCtrl)

        # row 2
        self.sizer.Add(wx.StaticText(self, wx.ID_ANY, "Email"))
        emailCtrl = wx.TextCtrl(self, wx.ID_ANY, "")
        self.sizer.Add(emailCtrl)

        # row 3
        self.sizer.Add(wx.StaticText(self, wx.ID_ANY, "Gender"))
        self.choice = wx.Choice(self, wx.ID_ANY, choices=["male", "female"], name='ChoiceBox')
        self.sizer.Add(self.choice)
        self.choice.Bind(wx.EVT_CHOICE, self.OnGenderChanged)

        # row 4
        self.sizer.Add(wx.StaticText(self, wx.ID_ANY, "State"))
        self.sizer.Add(wx.TextCtrl(self, wx.ID_ANY, size=(60, -1))) # two chars for state

        # row 5
        self.sizer.Add(wx.StaticText(self, wx.ID_ANY, "My PID is:"))
        self.pid = wx.TextCtrl(self, wx.ID_ANY, size=(150, -1))
        self.pid.SetValue( str(os.getpid()) )
        self.sizer.Add(self.pid)

        # TO TEST THE OTHER INPUT MODES
        """
        lef1 = LabeledEditField(self, wx.ID_ANY, u"SCALE_DISTANCE",   1., behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_DISTANCE)
        self.sizer.Add(lef1, 0, wx.EXPAND)
        lef2 = LabeledEditField(self, wx.ID_ANY, u"ANGLE_VALUE",      1., behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.ANGLE_VALUE)
        self.sizer.Add(lef2, 0, wx.EXPAND)
        lef3 = LabeledEditField(self, wx.ID_ANY, u"PERCENTAGE_VALUE", 1., behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.PERCENTAGE_VALUE)
        self.sizer.Add(lef3, 0, wx.EXPAND)
        lef4 = LabeledEditField(self, wx.ID_ANY, u"SCALE_SPEED",      1., behaviour=BEHAVIOUR.NUMERIC|BEHAVIOUR.SCALE_SPEED)
        self.sizer.Add(lef4, 0, wx.EXPAND)
        lef1.SetValue(1.)
        lef2.SetValue(1.)
        lef3.SetValue(1.)
        lef4.SetValue(1.)
        """

        import wx.lib.resizewidget as rw
        from p2c.window import MyWidget  # @UnresolvedImport

        self.sld = wx.Slider(self, wx.ID_ANY, 75, 0, 750, (-1, -1), (150, -1), wx.SL_LABELS)
        self.sizer.Add(self.sld, 1, wx.EXPAND|wx.TOP, 35)
        self.cw = 75
        self.wid = MyWidget(self, wx.ID_ANY)
        self.sizer.Add(self.wid, 1, wx.EXPAND)
        self.Bind(wx.EVT_SCROLL, self.OnScroll)

        self.sld.SetFocus()

        rw1 = rw.ResizeWidget(self)
        self.sizer.Add(rw1)

        # This one we will reparent to the ResizeWidget...
        self.tst = BasePanel(self, wx.ID_ANY)
        if _DEBUG:
            logger.info("%s%s%s" % (self.tst.__class__.__name__ , " -> pink", self.tst.GetParent().__class__.__name__))
            if _DEBUG & 0x4: self.tst.SetBackgroundColour('pink')
        self.txt = wx.StaticText(self.tst, wx.ID_ANY, "a panel,\nwith limits")
        self.tst.SetMinSize((80,35))
        self.tst.SetMaxSize((300,200))
        rw1.SetManagedChild(self.tst)

        self.Bind(rw.EVT_RW_LAYOUT_NEEDED, self.OnLayoutNeeded)

        self.button = wx.Button(self, wx.ID_ANY, "BREAK FOR DEBUG")
        self.sizer.Add(self.button)
        self.Bind(wx.EVT_BUTTON, self.OnDebugButton)

        # Set up a log window
        self.logWindow = wx.TextCtrl(self, wx.ID_ANY, size=(-1, 100),
                                     style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
        self.sizer.Add(self.logWindow, 0, wx.EXPAND)


    def OnDebugButton(self, event):  # @UnusedVariable
        if _DEBUG:
            logger.info("%s%s" % (self.__class__.__name__ , ".OnDebugButton"))
        wx.Trap()

    def OnScroll(self, event):  # @UnusedVariable
        if _DEBUG:
            logger.info("%s%s" % (self.__class__.__name__ , ".OnScroll"))
        self.cw = self.sld.GetValue()
        self.wid.Refresh()      # invokes the widgets OnPaint method

    def OnLayoutNeeded(self, event):
        # Grab the ... that generated the event
        control = event.GetEventObject()
        label = control.GetName()
        parent = self.GetParent().__class__.__name__
        self.GetSizer().Layout()      # seems useless

        self.Fit()
        self.GetParent().Fit()
        self.GetGrandParent().Fit()
        self.GetParent().GetGrandParent().Fit()
        self.GetGrandParent().GetGrandParent().Fit()
        self.GetParent().GetGrandParent().GetGrandParent().Fit()
        size = self.GetSize()
        # Display the label and some info in the wx.LogTextCtrl
        self.logWindow.AppendText("EVT_RW_LAYOUT_NEEDED event from ==> " + label + \
                                  ", parent = " + parent + ", Size = " + repr(size) + "\n")

        """
        wx.UpdateUIEvent
        """
    def OnGenderChanged(self, event):
        # Grab the ... that generated the event
        control = event.GetEventObject()
        # Get its label
#        label = control.GetLabel()
        label = control.GetName()
        # Get the Event Identifier , such as wxEVT_COMMAND_BUTTON_CLICKED.
        #typ = event.GetEventType()
        # Get the selection
        #sel = event.GetSelection()
        # Get the selected value
        value = event.GetString()
        # Display the label and some info in the wx.LogTextCtrl
        self.logWindow.AppendText("EVT_CHOICE event from ==> " + label + \
                                  ", selected = " + repr(value) + "\n")


class GroupPage5(BaseGroupPage):
    """ we are a BasePanel.
    this is for SETUPSHEET PAGE
    """
    def __init__(self, parent, id, name="_GRP_PAGE5"):  # @ReservedAssignment
        BaseGroupPage.__init__(self, parent, id, name=name)

        # handle background
        IsDifferentBackGroundColourPossible = getattr(opticam.BasePy(), "IsDifferentBackGroundColourPossible", None)
        if callable(IsDifferentBackGroundColourPossible):
            self.isBackgroundColorChangeable = IsDifferentBackGroundColourPossible()
        else:
            self.isBackgroundColorChangeable = False
        
        self.createPage()

        # now we have to call this function after the TransferDataToWindow
        # because the state of some widgets depends of some other widgets which have to be set before
        # ...in BasePostOptionsDialog.Activate()
        # self.enablePage()
        
    def createPage(self):      
        subsizer1 = wx.BoxSizer(wx.HORIZONTAL)
        self.sizer.Add(subsizer1, 0, wx.EXPAND)

        #Left Part of Window
        vSub1 = wx.StaticBoxSizer( StaticBox( self, wx.ID_ANY, wx.EmptyString, name="_STB_L" ), wx.VERTICAL )
       
        #General Options
        _vSub1_2 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "", name="STB_GENERAL_OPTION"), wx.VERTICAL)
        vSub1.Add( _vSub1_2, 0, wx.EXPAND)
        
        self.cb108 = OptiCheckBox(self, 108, label="Create setupsheet", name='SetupSheet')
        self.cb108.SetToolTipString("Output of the textual setupsheet.")
        _vSub1_2.Add(self.cb108, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
         
        self.cb112 = OptiCheckBox(self, 112, label="Create setupsheet (compact)", name='SetupSheetCompact')
        self.cb112.SetToolTipString("Output of the textual setupsheet (compact).")
        _vSub1_2.Add(self.cb112, 1, wx.EXPAND | wx.ALL, SMALLBORDER)

        self.cb113 = OptiCheckBox(self, 113, label="Create setupsheet (extra compact)", name='SetupSheetExtraCompact')
        self.cb113.SetToolTipString("Output of the textual setupsheet (extra compact).")
        _vSub1_2.Add(self.cb113, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        
        self.cb115 = OptiCheckBox(self, 115, label="Create 3D setupsheet", name='SetupSheet3D')
        self.cb115.SetToolTipString("Create extra 3D output file.")
        _vSub1_2.Add(self.cb115, 1, wx.EXPAND | wx.ALL, SMALLBORDER)
        
        # Only show the 3D SetupSheet Check box if it is available in the CAD system (currently only in hyperMill)
        IsPossible_3DPdf = getattr(opticam.BasePy(), "IsPossible_3DPdf", None)
        if callable(IsPossible_3DPdf):
            Possible3D = IsPossible_3DPdf()
            if Possible3D == False:
                self.cb115.SetValue(False)
                self.cb115.Hide()
            else:
                pass          
        else:
            pass
        
        listPictureStyle = [ "Colour", 
                            "Monochrome",
                            "No Graphics"]
        self.radioBoxPicture = OptiRadioBox( self, wx.ID_ANY, label="Picture", pos=wx.DefaultPosition, size=wx.DefaultSize, choices=listPictureStyle[:], majorDimension=1, style=wx.RA_SPECIFY_COLS, name='radioBoxPicture' )
        self.radioBoxPicture.SetSelection( 0 )
        vSub1.Add( self.radioBoxPicture, 0, wx.EXPAND)
            
        # 09/03/2024 jorgk
        # wxSizer::Add() now does checks for flags, that make sense!
        # 09/03/2024 jorgk
        vFlags = wx.ALIGN_CENTER_HORIZONTAL|wx.ALL
        vFlags = wx.ALIGN_LEFT|wx.ALL
        hFlags = wx.ALIGN_CENTER_VERTICAL|wx.ALL
        
        _vSub1_1 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Background option", name="STB_BACKGROUND_OPTION"), wx.VERTICAL)
        self.backgroundColorWhite = OptiCheckBox(self, wx.ID_ANY, label="Backgroundcolor white", name='backgroundColorWhite')
        #self.backgroundColorWhite.Enable(self.isBackgroundColorChangeable)
        _vSub1_1.Add(self.backgroundColorWhite, 0, vFlags, SMALLBORDER )
        vSub1.Add( _vSub1_1, 0, wx.EXPAND )

        vSub1_1 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Report Format", name="STB_REPORT_FORMAT"), wx.VERTICAL)
        self.choiceFile = LabeledComboBox( self, wx.ID_ANY, label="File format", pos=wx.DefaultPosition, size=wx.DefaultSize, name='choiceFile', propChoice=0.5)
        self.choiceFile.SetSelection( 0 )
        vSub1_1.Add( self.choiceFile, 0, wx.EXPAND | wx.ALL, SMALLBORDER )
        
        # wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.EXPAND
        # No wx.ALIGN_CENTER_VERTICAL in vertical sizer!!!
        '''
        self.radioStandardReport = OptiRadioButton( self, wx.ID_ANY, u"Standard Reports", wx.DefaultPosition, wx.DefaultSize, wx.RB_GROUP, name='radioStandardReport' )
        self.radioStandardReport.SetValue( True ) 
        vSub1_1.Add( self.radioStandardReport, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )
        self.radioUserReport = OptiRadioButton( self, wx.ID_ANY, u"User Report", wx.DefaultPosition, wx.DefaultSize, 0, name='radioUserReport' )
        vSub1_1.Add( self.radioUserReport, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )
        vSub1_1_2 = wx.BoxSizer( wx.VERTICAL )
        hsub1_1_1_1 = wx.BoxSizer( wx.HORIZONTAL )
        hsub1_1_1_1.AddSpacer( ( 20, 0), 0, wx.EXPAND, SMALLBORDER )
        self.textReportPath = TextField( self, wx.ID_ANY, u"Report Path:", wx.DefaultPosition, wx.DefaultSize, 0, name='textReportPath' )
        self.textReportPath.Wrap( -1 )
        hsub1_1_1_1.Add( self.textReportPath, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )
        vSub1_1_2.Add( hsub1_1_1_1, 1, wx.EXPAND, SMALLBORDER )
        hsub1_1_1_2 = wx.BoxSizer( wx.HORIZONTAL )
        hsub1_1_1_2.AddSpacer( ( 20, 0), 0, wx.EXPAND, SMALLBORDER )
        self.editReportFile = EditField( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, style=wx.TE_READONLY, name='editReportFile' )
        hsub1_1_1_2.Add( self.editReportFile, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )
        self.btnOpenReportFile = NiceButton( self, wx.ID_ANY, OPEN_FILE_ICON, name='btnOpenReportFile' )
        hsub1_1_1_2.Add( self.btnOpenReportFile, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )
        vSub1_1_2.Add( hsub1_1_1_2, 0, wx.EXPAND, SMALLBORDER )
        vSub1_1.Add( vSub1_1_2, 0, wx.EXPAND, SMALLBORDER )
        '''
        vSub1.Add( vSub1_1, 0, wx.EXPAND )

        self.vSub1_2 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Paper", name="STB_PAPER_FORMAT"), wx.VERTICAL)

        hSub1_2_1 = wx.BoxSizer( wx.HORIZONTAL )
        vSub1_2_1 = wx.BoxSizer( wx.VERTICAL )
        hSub1_2_1.Add( vSub1_2_1, 1, wx.EXPAND, SMALLBORDER )
        
        #Page size/format
        self.pageSize = LabeledComboBox( self, wx.ID_ANY, label="Page size", pos=wx.DefaultPosition, size=wx.DefaultSize, name='pageSize', propChoice=0.5)
        self.vSub1_2.Add( self.pageSize, 0, wx.EXPAND | wx.ALL, SMALLBORDER )
        
        self.radioPortraitFormat = OptiRadioButton( self, wx.ID_ANY, "Portrait A4", wx.DefaultPosition, wx.DefaultSize, wx.RB_GROUP, name='radioPortraitFormat' )
        self.radioPortraitFormat.SetValue( True ) 
        vSub1_2_1.Add( self.radioPortraitFormat, 0, vFlags, SMALLBORDER )

        self.radioLandscapeFormat = OptiRadioButton( self, wx.ID_ANY, "Landscape A4", wx.DefaultPosition, wx.DefaultSize, 0, name='radioLandscapeFormat' )
        vSub1_2_1.Add( self.radioLandscapeFormat, 0, vFlags, SMALLBORDER )

        bmp = getOpticamIcon('Paper_Portrait.bmp')
        self.bitmapPaper = wx.StaticBitmap( self, wx.ID_ANY, bmp, wx.DefaultPosition, wx.DefaultSize, 0 )
        hSub1_2_1.Add( self.bitmapPaper, 0, hFlags, SMALLBORDER )

        self.vSub1_2.Add( hSub1_2_1, 0, wx.EXPAND)
        vSub1.Add( self.vSub1_2, 0, wx.EXPAND )

        subsizer1.Add( vSub1, 1, wx.EXPAND)
        
        #User Logo
        vSub1_3 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "User Logo", name="STB_USER_LOGO"), wx.VERTICAL)
        hSub1_1_1 = wx.BoxSizer( wx.HORIZONTAL )

        self.editLogoFile = EditField( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, style=wx.TE_READONLY, name='editLogoFile' )
        hSub1_1_1.Add( self.editLogoFile, 1, hFlags, SMALLBORDER )

        self.btnOpenLogoFile = NiceButton( self, wx.ID_ANY, OPEN_FILE_ICON, name='btnOpenLogoFile' )
        hSub1_1_1.Add( self.btnOpenLogoFile, 0, hFlags, SMALLBORDER )

        vSub1_3.Add( hSub1_1_1, 0, wx.EXPAND)
        
        vSub1.Add( vSub1_3, 0, wx.EXPAND)
        
        #User Fields
        vSub2_2 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "User Fields", name="STB_USER_FIELDS"), wx.VERTICAL)
        hSub2_2_1 = wx.BoxSizer( wx.HORIZONTAL )
        vSub2_2_1_1 = wx.BoxSizer( wx.VERTICAL )
        vSub2_2_1_2 = wx.BoxSizer( wx.VERTICAL )

        hSub2_2_1.AddSpacer( SPACE )
        self.txtDescription = TextField( self, wx.ID_ANY, "Description", wx.DefaultPosition, wx.DefaultSize, 0, name='txtDescription' )
        self.txtDescription.Wrap( -1 )
        vSub2_2_1_1.Add( self.txtDescription, 0, vFlags, SMALLBORDER )

        hSub2_2_1.AddSpacer( SPACE )
        self.txtValue = TextField( self, wx.ID_ANY, "Value", wx.DefaultPosition, wx.DefaultSize, 0, name='txtValue' )
        self.txtValue.Wrap( -1 )
        vSub2_2_1_2.Add( self.txtValue, 0, vFlags, SMALLBORDER )

        hSub2_2_1.AddSpacer( SPACE )
        hSub2_2_1.Add( vSub2_2_1_1, 1, wx.EXPAND)
        hSub2_2_1.Add( vSub2_2_1_2, 1, wx.EXPAND)
        vSub2_2.Add( hSub2_2_1, 1, wx.EXPAND)
        vSub2_2_2 = wx.BoxSizer( wx.VERTICAL )
        hSub2_2_2_1 = wx.BoxSizer( wx.HORIZONTAL )

        self.txt1 = TextField( self, wx.ID_ANY, "1.", wx.DefaultPosition, wx.DefaultSize, 0, name='txt1' )
        self.txt1.Wrap( -1 )
        hSub2_2_2_1.Add( self.txt1, 0, hFlags, SMALLBORDER )

        self.editDesc1 = EditField( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0, name='editDesc1' )
        hSub2_2_2_1.Add( self.editDesc1, 1, wx.ALL, SMALLBORDER )

        self.editVal1 = EditField( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0, name='editVal1' )
        hSub2_2_2_1.Add( self.editVal1, 1, hFlags, SMALLBORDER )

        vSub2_2_2.Add( hSub2_2_2_1, 1, wx.EXPAND)

        hSub2_2_2_1 = wx.BoxSizer( wx.HORIZONTAL )

        self.txt2 = TextField( self, wx.ID_ANY, "2.", wx.DefaultPosition, wx.DefaultSize, 0, name='txt2' )
        self.txt2.Wrap( -1 )
        hSub2_2_2_1.Add( self.txt2, 0, hFlags, SMALLBORDER )

        self.editDesc2 = EditField( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0, name='editDesc2' )
        hSub2_2_2_1.Add( self.editDesc2, 1, hFlags, SMALLBORDER )

        self.editVal2 = EditField( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0, name='editVal2' )
        hSub2_2_2_1.Add( self.editVal2, 1, hFlags, SMALLBORDER )

        vSub2_2_2.Add( hSub2_2_2_1, 1, wx.EXPAND, SMALLBORDER )

        hSub2_2_2_1 = wx.BoxSizer( wx.HORIZONTAL )

        self.txt3 = TextField( self, wx.ID_ANY, "3.", wx.DefaultPosition, wx.DefaultSize, 0, name='txt3' )
        self.txt3.Wrap( -1 )
        hSub2_2_2_1.Add( self.txt3, 0, hFlags, SMALLBORDER )

        self.editDesc3 = EditField( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0, name='editDesc3' )
        hSub2_2_2_1.Add( self.editDesc3, 1, hFlags, SMALLBORDER )

        self.editVal3 = EditField( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0, name='editVal3' )
        hSub2_2_2_1.Add( self.editVal3, 1, hFlags, SMALLBORDER )

        vSub2_2_2.Add( hSub2_2_2_1, 1, wx.EXPAND)

        vSub2_2.Add( vSub2_2_2, 0, wx.EXPAND)

        vSub1.Add( vSub2_2, 0, wx.EXPAND)
        
        #Right Part of Window
        vSub2 = wx.StaticBoxSizer( StaticBox( self, wx.ID_ANY, wx.EmptyString, name="_STB_R" ), wx.VERTICAL )
        
        #User Options
        vSub2_3 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "User Options", name="STB_USER_OPTIONS"), wx.VERTICAL)

        self.OutputNcFileName = OptiCheckBox(self, wx.ID_ANY, "Output NC filename", wx.DefaultPosition, wx.DefaultSize, style=0, name='OutputNcFileNameWithPath' )
        vSub2_3.Add( self.OutputNcFileName, 0, vFlags, SMALLBORDER )
        self.OutputNcFileName.setSlaves(['OutputNcFileNameWithOutPath','OutputNcFileNameAndPath'])
        
        vSub2_3.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
        self.rbNCWP = OptiRadioButton(self, wx.ID_ANY, "only file name", style = wx.RB_GROUP, name="OutputNcFileNameWithOutPath")
        self.rbNCWP.SetToolTipString("?")
        vSub2_3.Add(self.rbNCWP, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)

        vSub2_3.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)
        self.rbNCAP = OptiRadioButton(self, wx.ID_ANY, label="with path", name="OutputNcFileNameAndPath")
        self.rbNCAP.SetToolTipString("?")
        vSub2_3.Add(self.rbNCAP, 0, wx.ALIGN_LEFT | wx.LEFT, BIGBORDER)

        vSub2_3.Add((0,0), 0, wx.ALIGN_LEFT | wx.ALL, 3)

        if 'SetupsheetExtraFolder' in postVar:
            # 09/03/2024 jorgk
            # wxSizer::Add() now does checks for flags, that make sense!
            # 09/03/2024 jorgk
            # wx.EXPAND must not be used with wx.ALIGN_CENTRE_VERTICAL or wx.ALIGN_CENTRE_HORIZONTAL
            # wx.ALIGN_RIGTH and wx.ALIGN_BOTTOM are also forbidden!
            
            hFlagsI = wx.ALIGN_LEFT|wx.ALIGN_CENTRE_VERTICAL|wx.EXPAND
            hFlagsII = wx.ALIGN_RIGHT|wx.ALIGN_CENTRE_VERTICAL|wx.EXPAND
            hbox = wx.BoxSizer(wx.HORIZONTAL)
            vSub2_3.Add(hbox, 0, wx.EXPAND|wx.ALL, SMALLBORDER)
            self.SetupsheetExtraFolder = OptiCheckBox(self, wx.ID_ANY, label="Store setupsheet in subfolder", name='SetupsheetExtraFolder')
            self.SetupsheetExtraFolder.SetToolTipString("Store setupsheet in separate folder!")
            self.SetupsheetExtraFolder.setSlaves(['SetupsheetExtraFolderName'])
            hbox.Add(self.SetupsheetExtraFolder, 1, wx.ALIGN_LEFT|wx.ALIGN_CENTRE_VERTICAL, SMALLBORDER)

            hbox.AddSpacer( 5 )
            self.SetupsheetExtraFolderName = EditField(self, wx.ID_ANY, size=(150,-1) , behaviour=BEHAVIOUR.ALPHANUMERIC, name='SetupsheetExtraFolderName')
            self.SetupsheetExtraFolderName.SetToolTipString("Subfolder name")
            self.SetupsheetExtraFolderName.Disable()
            hbox.Add(self.SetupsheetExtraFolderName, 1, wx.RIGHT|wx.ALIGN_CENTRE, SMALLBORDER)

        #self.HideSolids = OptiCheckBox( self, wx.ID_ANY, u"Hide Solids on current layer during plotting", wx.DefaultPosition, wx.DefaultSize, style=0, name='HideSolids' )
        #vSub2_3.Add( self.HideSolids, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )

        #self.ShowStartpoint = OptiCheckBox( self, wx.ID_ANY, u"Show Startpoint in picture", wx.DefaultPosition, wx.DefaultSize, style=0, name='ShowStartpoint' )
        #vSub2_3.Add( self.ShowStartpoint, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )

        #self.WhiteBackground = OptiCheckBox( self, wx.ID_ANY, u"White background during plotting", wx.DefaultPosition, wx.DefaultSize, style=0, name='WhiteBackground' )
        #vSub2_3.Add( self.WhiteBackground, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )

        #self.PrintAfterPp = OptiCheckBox( self, wx.ID_ANY, u"Print after Postprocessing", wx.DefaultPosition, wx.DefaultSize, style=0, name='PrintAfterPp' )
        #vSub2_3.Add( self.PrintAfterPp, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, SMALLBORDER )

        self.radioOutModeCut = OptiRadioButton( self, wx.ID_ANY, "Cut Output Mode", wx.DefaultPosition, wx.DefaultSize, wx.RB_GROUP, name='radioOutModeCut' )
        self.radioOutModeCut.SetValue( True ) 
        vSub2_3.Add( self.radioOutModeCut, 0, vFlags, SMALLBORDER )

        self.radioOutModeFeature = OptiRadioButton( self, wx.ID_ANY, "Feature Output Mode", wx.DefaultPosition, wx.DefaultSize, 0, name='radioOutModeFeature' )
        vSub2_3.Add( self.radioOutModeFeature, 0, vFlags, SMALLBORDER )
        

        self.setupSheetDigitsAfter = LabeledComboBox(self, 135, "Digits after Decimal Point", name='setupSheetDigitsAfter', propChoice=0.5)
        self.setupSheetDigitsAfter.SetToolTipString("Number of digits after decimalpoint")
        vSub2_3.Add( self.setupSheetDigitsAfter, 0, wx.EXPAND | wx.ALL, SMALLBORDER)
            
        vSub2.Add( vSub2_3, 0, wx.EXPAND)
        
        #SetupSheet Templates
        vSub2_4 = wx.StaticBoxSizer(StaticBox(self, wx.ID_ANY, "Setupsheet Templates", name="STB_SETUPSHEET_TEMPLATES"), wx.VERTICAL)
        
        hSub2_4_0 = wx.BoxSizer( wx.HORIZONTAL )
        
        self.STImportSetupsheetTemplateFile = TextField( self, wx.ID_ANY, "Import setupsheet templates to local folder", wx.DefaultPosition, wx.DefaultSize, 0, name="ST_IMPORT_SETUPSHEET_TEMPLAETE_FILE" )
        hSub2_4_0.Add( self.STImportSetupsheetTemplateFile, 0, hFlags, SMALLBORDER )
        
        self.btnImportSetupsheetTemplateFile = NiceButton( self, wx.ID_ANY, '2_Save Default_Eingangskorb.ico', name='btnImportSetupsheetTemplateFile' )
        hSub2_4_0.Add( self.btnImportSetupsheetTemplateFile, 0, hFlags, SMALLBORDER )
        
        vSub2_4.Add( hSub2_4_0, 0, wx.EXPAND)
        
        #Use SetupSheet Template
        self.SetupSheetUseTemplate = OptiCheckBox(self, wx.ID_ANY, "Use setupsheet template", wx.DefaultPosition, wx.DefaultSize, style=0, name='SetupSheetUseTemplate' )
        self.SetupSheetUseTemplate.Disable()
        self.SetupSheetUseTemplate.setSlaves(['btnOpenSetupsheetTemplateFile','editSetupsheetTemplateFile'])
        vSub2_4.Add( self.SetupSheetUseTemplate, 0, vFlags, SMALLBORDER )
        hSub2_4_1 = wx.BoxSizer( wx.HORIZONTAL )

        self.editSetupsheetTemplateFile = EditField( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, style=wx.TE_READONLY, name='editSetupsheetTemplateFile' )
        self.editSetupsheetTemplateFile.Disable()
        hSub2_4_1.Add( self.editSetupsheetTemplateFile, 1, hFlags, SMALLBORDER )

        self.btnOpenSetupsheetTemplateFile = NiceButton( self, wx.ID_ANY, OPEN_FILE_ICON, name='btnOpenSetupsheetTemplateFile' )
        self.btnOpenSetupsheetTemplateFile.Disable()
        hSub2_4_1.Add( self.btnOpenSetupsheetTemplateFile, 0, hFlags, SMALLBORDER )
        
        if "SetupSheetUseTemplate" in postVar:
            self.SetupSheetUseTemplate.Enable()
            bChecked = postVar["SetupSheetUseTemplate"]
            if bChecked:
                self.editSetupsheetTemplateFile.Enable()
                self.btnOpenSetupsheetTemplateFile.Enable()
        
        vSub2_4.Add( hSub2_4_1, 0, wx.EXPAND)
        
        #Use SetupSheet (Compact) Template
        self.SetupSheetCompactUseTemplate = OptiCheckBox(self, wx.ID_ANY, "Use setupsheet (compact) template", wx.DefaultPosition, wx.DefaultSize, style=0, name='SetupSheetCompactUseTemplate' )
        self.SetupSheetCompactUseTemplate.Disable()
        self.SetupSheetCompactUseTemplate.setSlaves(['btnOpenSetupsheetCompactTemplateFile','editSetupsheetCompactTemplateFile'])
        vSub2_4.Add( self.SetupSheetCompactUseTemplate, 0, vFlags, SMALLBORDER )
        hSub2_4_2 = wx.BoxSizer( wx.HORIZONTAL )
        
        self.editSetupsheetCompactTemplateFile = EditField( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, style=wx.TE_READONLY, name='editSetupsheetCompactTemplateFile' )
        self.editSetupsheetCompactTemplateFile.Disable()
        hSub2_4_2.Add( self.editSetupsheetCompactTemplateFile, 1, hFlags, SMALLBORDER )

        self.btnOpenSetupsheetCompactTemplateFile = NiceButton( self, wx.ID_ANY, OPEN_FILE_ICON, name='btnOpenSetupsheetCompactTemplateFile' )
        self.btnOpenSetupsheetCompactTemplateFile.Disable()
        hSub2_4_2.Add( self.btnOpenSetupsheetCompactTemplateFile, 0, hFlags, SMALLBORDER )
        
        if "SetupSheetCompactUseTemplate" in postVar:
            self.SetupSheetCompactUseTemplate.Enable()
            bChecked = postVar["SetupSheetCompactUseTemplate"]
            if bChecked:
                self.editSetupsheetCompactTemplateFile.Enable()
                self.btnOpenSetupsheetCompactTemplateFile.Enable()

        vSub2_4.Add( hSub2_4_2, 0, wx.EXPAND)
        vSub2.Add( vSub2_4, 0, wx.EXPAND)        
        subsizer1.Add( vSub2, 1, wx.EXPAND)  
                
        #A list of masters for this group page
        self.panelMasterList = ['SetupSheet','SetupSheetCompact','SetupSheetExtraCompact']
        #A list if sub-masters which control their own slaves
        self.subMasterList = ['SetupsheetExtraFolder','OutputNcFileNameWithPath','SetupSheetUseTemplate','SetupSheetCompactUseTemplate']
        #A List of all additional widgets to be excluded from panel master control for any reason
        self.exclusionList = ['SetupsheetExtraFolderName', 'SetupSheet3D']
        #Get Lists of all widget items and widget names controlled by the defined masters 
        self.WDGName, self.WDGItem = self.setPanelMaster(self, self.panelMasterList, self.subMasterList, self.exclusionList)            
        
        '''Bind wx.Events to Widgets'''
        #self.radioStandardReport.Bind( wx.EVT_RADIOBUTTON, self.OnReportChanged )
        #self.radioUserReport.Bind( wx.EVT_RADIOBUTTON, self.OnReportChanged )
        #self.btnOpenReportFile.Bind( wx.EVT_BUTTON, self.OnOpenReportBtn )
        self.choiceFile.Bind( wx.EVT_CHOICE, self.OnChoiceChanged )
        self.pageSize.Bind( wx.EVT_CHOICE, self.OnPageSizeChanged )
        self.radioPortraitFormat.Bind( wx.EVT_RADIOBUTTON, self.OnPaperChanged )
        self.radioLandscapeFormat.Bind( wx.EVT_RADIOBUTTON, self.OnPaperChanged )
        self.btnOpenLogoFile.Bind( wx.EVT_BUTTON, self.OnOpenLogoBtn )
        self.btnImportSetupsheetTemplateFile.Bind( wx.EVT_BUTTON, self.OnImportSetupsheetTemplateFile )
        self.btnOpenSetupsheetTemplateFile.Bind( wx.EVT_BUTTON, self.OnOpenSetupsheetTemplateFile )
        self.btnOpenSetupsheetCompactTemplateFile.Bind( wx.EVT_BUTTON, self.OnOpenSetupsheetCompactTemplateFile )
        self.cb108.Bind( wx.EVT_CHECKBOX, self.OnSetupSheetBox )
        self.cb112.Bind( wx.EVT_CHECKBOX, self.OnSetupSheetBox )
        self.cb113.Bind( wx.EVT_CHECKBOX, self.OnSetupSheetBox )

    def enablePage(self):      
        ''' Enables/disables a list of chosen widgets of this page.'''

        #ENABLED = True
        #DISABLED = False
        
        MstSt = self.getCBStatus(self.panelMasterList)
        #Only if all Masters are disabled, initialize the panel with all slave widgets disabled, else keep enabled.
        if all(st is False for st in MstSt):
            for widget in self.WDGName:
                #Disable all widgets of the panels excluding the defined masters
                self.enableWidget(widget, self.panelMasterList)

        isMetric = postVar.get('OutputUnitsMetric', True)
        self.setDigitsList(isMetric)
    

    def enableOnce(self):
        """ Do this once """
        #check if papersize widget is needed (only for .rtf files)
        selection = self.choiceFile.GetStringSelection()
        if selection.lower().endswith('.rtf'):
            self.pageSize.Enable(True)
            #self.vSub1_2.Show(self.pageSize, True)
        else:
            self.pageSize.Enable(False)
            #self.vSub1_2.Show(self.pageSize, False)
        #
        #we have to check if the correct bitmap for paper is set
        if postVar['radioPortraitFormat'] == True:
            logo = 'Paper_Portrait.bmp'
        else:
            logo = 'Paper_Landscape.bmp' 
        bmp = getOpticamIcon(logo)
        self.bitmapPaper.SetSize((bmp.Width,bmp.Height))
        self.bitmapPaper.SetBitmap(bmp)
        
    #Event for SetupSheet Check Boxes
    def OnSetupSheetBox( self, event ):
        #Check status of panel masters every time this event is triggered
        MstSt = self.getCBStatus(self.panelMasterList)

        if event.IsChecked():
            #Enable widgets as soon as one of the SetupSheet check boxes is checked
            for widget in self.WDGItem:
                #Disable all widgets of the panels excluding the defined masters and exclusions
                widget.Enable()
            #This widgets have to be done separately because they depend on other (global) variables
            self.backgroundColorWhite.Enable(self.isBackgroundColorChangeable)
            self.enableOnce()
        
        else:
            #Only disable widgets if all SetupSheet Check Boxes are unchecked
            if all(st is False for st in MstSt):
                for widget in self.WDGName:
                    #Use Name List here as the enableWidget function also disables the check boxes
                    self.enableWidget(widget, self.panelMasterList) 
                    
                                                
    def OnOpenReportBtn( self, event ):
        #evtObjName  = event.GetEventObject().GetName()

        dlg = wx.DirDialog(self, "Choose a directory:",
                           style=wx.DD_DEFAULT_STYLE
                           #| wx.DD_DIR_MUST_EXIST
                           #| wx.DD_CHANGE_DIR
                           )

        # If the user selects OK, then we process the dialog's data.
        # This is done by getting the path data from the dialog - BEFORE
        # we destroy it.

        if dlg.ShowModal() == wx.ID_OK:
            self.editReportFile.SetValue(dlg.GetPath())

        # Only destroy a dialog after you're done with it.
        dlg.Destroy()
        event.Skip()

    def OnOpenLogoBtn( self, event ):
        evtObjName  = event.GetEventObject().GetName()
        #evtObjId    = event.GetEventObject().GetId()
        #wildcard = "(*.xml)|*.xml"

        dlg = wx.FileDialog(self, message=getMessageW("Choose file for ",PYTHON_MESSAGES,11) + evtObjName,
                            #defaultDir=postPath,
                            #defaultFile=wx.EmptyString,
                            #wildcard=wildcard,
                            style=wx.FD_OPEN
                            )
        # Show the dialog and retrieve the user response. If it is the OK response, process the data.
        #
        if dlg.ShowModal() == wx.ID_OK:
            #postVar['UpperNozzleSTLFile '] = dlg.GetPath()
            self.editLogoFile.SetValue(dlg.GetPath())

        if _DEBUG:
            local_dir  = dlg.GetDirectory()
            file_name = dlg.GetFilename()   
            if logger: logger.info("You selected directory: %s" %  local_dir)
            if logger: logger.info("You selected file: %s" %  file_name)
            if logger: logger.info("You selected path: %s" %  dlg.GetPath() )

        event.Skip()
    
    def OnImportSetupsheetTemplateFile( self, event ):
        evtObjName  = event.GetEventObject().GetName()
        #evtObjId    = event.GetEventObject().GetId()
        wildcard = "(*.xml)|*.xml"
        strMaschine = opticam.getCurrentDoc().GetMachine().Name.getPyString()
        strDest = os.path.join(postPath, strMaschine, "setuptemplates")
        if not os.path.exists(strDest):
            try:
                os.makedirs(strDest)
            except:
                pass

        dlg = wx.FileDialog(self, message=getMessageW("Choose file for ", PYTHON_MESSAGES, 11) + evtObjName,
                            defaultDir=strDest,
                            #defaultFile=wx.EmptyString,
                            wildcard=wildcard,
                            style=wx.FD_OPEN | wx.FD_MULTIPLE
                            )
        # Show the dialog and retrieve the user response. If it is the OK response, process the data.
        #
        if dlg.ShowModal() == wx.ID_OK:
            #postVar['UpperNozzleSTLFile '] = dlg.GetPath()
            # copy the xml file to "posts3/xxxxx/setuptemplates"
            for stFile in dlg.Paths:
                shutil.copy2(stFile, strDest)

        if _DEBUG:
            local_dir  = dlg.GetDirectory()
            file_name = dlg.GetFilename()   
            if logger: logger.info("You selected directory: %s" %  local_dir)
            if logger: logger.info("You selected file: %s" %  file_name)
            if logger: logger.info("You selected path: %s" %  dlg.GetPath())

        event.Skip()
    
    def OnOpenSetupsheetTemplateFile( self, event ):
        evtObjName  = event.GetEventObject().GetName()
        #evtObjId    = event.GetEventObject().GetId()
        wildcard = "(*.xml)|*.xml"
        strMaschine = opticam.getCurrentDoc().GetMachine().Name.getPyString()
        strDest = os.path.join(postPath, strMaschine, "setuptemplates")
        if not os.path.exists(strDest):
            try:
                os.makedirs(strDest)
            except:
                pass

        dlg = wx.FileDialog(self, message=getMessageW("Choose file for ",PYTHON_MESSAGES,11) + evtObjName,
                            defaultDir=strDest,
                            #defaultFile=wx.EmptyString,
                            wildcard=wildcard,
                            style=wx.FD_OPEN
                            )
        # Show the dialog and retrieve the user response. If it is the OK response, process the data.
        #
        if dlg.ShowModal() == wx.ID_OK:
            #postVar['UpperNozzleSTLFile '] = dlg.GetPath()
            self.editSetupsheetTemplateFile.SetValue(dlg.GetPath())

        if _DEBUG:
            local_dir  = dlg.GetDirectory()
            file_name = dlg.GetFilename()   
            if logger: logger.info("You selected directory: %s" %  local_dir)
            if logger: logger.info("You selected file: %s" %  file_name)
            if logger: logger.info("You selected path: %s" %  dlg.GetPath())

        event.Skip()
    
    def OnOpenSetupsheetCompactTemplateFile( self, event ):
        evtObjName  = event.GetEventObject().GetName()
        #evtObjId    = event.GetEventObject().GetId()
        wildcard = "(*.xml)|*.xml"
        strMaschine = opticam.getCurrentDoc().GetMachine().Name.getPyString()
        strDest = os.path.join(postPath, strMaschine, "setuptemplates")
        if not os.path.exists(strDest):
            try:
                os.makedirs(strDest)
            except:
                pass

        dlg = wx.FileDialog(self, message=getMessageW("Choose file for ",PYTHON_MESSAGES,11) + evtObjName,
                            defaultDir=strDest,
                            #defaultFile=wx.EmptyString,
                            wildcard=wildcard,
                            style=wx.FD_OPEN
                            )
        # Show the dialog and retrieve the user response. If it is the OK response, process the data.
        #
        if dlg.ShowModal() == wx.ID_OK:
            #postVar['UpperNozzleSTLFile '] = dlg.GetPath()
            self.editSetupsheetCompactTemplateFile.SetValue(dlg.GetPath())

        if _DEBUG:
            local_dir  = dlg.GetDirectory()
            file_name = dlg.GetFilename()   
            if logger: logger.info("You selected directory: %s" %  local_dir)
            if logger: logger.info("You selected file: %s" %  file_name)
            if logger: logger.info("You selected path: %s" %  dlg.GetPath())

        event.Skip()

    def OnReportChanged( self, event):
        self.enablePage()
        event.Skip()

    def OnChoiceChanged( self, event ):
        evtObj = event.GetEventObject()
        #selection = evtObj.GetSelection()    # return index
        selection = evtObj.GetStringSelection()
        if selection.lower().endswith('.rtf'):
            self.pageSize.Enable(True)
            #self.vSub1_2.Show(self.pageSize, True)
            if 'pageSizeLIST' not in postVar:
                postVar['pageSizeLIST'] = GetRtfPageSizesListList()
                self.pageSize.SetItems(postVar['pageSizeLIST'])
                if postVar['pageSize'] not in postVar['pageSizeLIST']:
                    if len(postVar['pageSizeLIST']) > 0:
                        postVar['pageSize'] = postVar['pageSizeLIST'][0]
                    else:
                        postVar['pageSize'] = ""
                self.pageSize.SetStringSelection(postVar['pageSize'])
        else:
            self.pageSize.Enable(False)
            #self.vSub1_2.Show(self.pageSize, False)
        #self.Layout()    # only neccessary if showed/hided with sizer

    def OnPageSizeChanged( self, event ):
        pass

    def OnPaperChanged( self, event ):
        evtObj = event.GetEventObject()
        if evtObj.Name == 'radioLandscapeFormat':
            logo = 'Paper_Landscape.bmp'
        else:
            logo = 'Paper_Portrait.bmp'

        bmp = getOpticamIcon(logo)
        self.bitmapPaper.SetSize((bmp.Width,bmp.Height))
        self.bitmapPaper.SetBitmap(bmp)
        event.Skip()

    def OnOutputNcFileName(self, event):  # @UnusedVariable
        """
        """
        self.enablePage()
        
    def OnExtraFolder(self, event):  # @UnusedVariable
        """
        """
        self.enablePage()
        
    def setDigitsList(self, isMetric=True):
        if hasattr(self, 'setupSheetDigitsAfter'):
            digits = self.setupSheetDigitsAfter.GetValue()     # act. value
            if isMetric:
                digitsList = ['0', '1', '2', '3', '4', '5', '6']
            else:
                digitsList = ['1', '2', '3', '4', '5', '6']
    
            # if act. value is not in the new itemslist -> take the first value from the itemlist
            if digits not in digitsList:
                digits = digitsList[2]
            self.setupSheetDigitsAfter.SetItems(digitsList)
            self.setupSheetDigitsAfter.SetValue(digits)
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
def ImageBrowser(parent=None, local_dir=iconsDir):
    import  wx.lib.imagebrowser    as  ib
    # get current working directory
    ret = None

    # set the initial directory for the demo bitmaps
#    initial_dir = os.path.join(dir, 'bitmaps')
    initial_dir = local_dir

    # open the image browser dialog
    dlg = ib.ImageDialog(parent, initial_dir)

    dlg.Centre()

    if dlg.ShowModal() == wx.ID_OK:
        # show the selected file
        #path = os.path.abspath( dlg.GetFile() )
        file_name = os.path.basename( dlg.GetFile() )
        local_dir  = os.path.dirname( dlg.GetFile() )
        if _DEBUG:
            logger.info("You selected directory: %s" % local_dir)
            logger.info("You selected file: %s" % file_name)
            logger.info("You selected icon: %s" % dlg.GetIcon() )
        ret = (local_dir, file_name)
    else:
        if _DEBUG:
            logger.info("You pressed Cancel\n")

    dlg.Destroy()

    return ret

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
def ResetPythonDialogsToDefaults(mode=None):
    # 
    # mode can be used in the future to control way of resetting (bitwise usage)
    # activate this in main system with <shift-ctrl-F9>
    msg1 = getMessageW('Resets python dialog settings - changes are effective after restart.', PYTHON_MESSAGES, 755)
    #msg2 = getMessageW('Python', PYTHON_MESSAGES, 0)
    ret = opticam.MessageBoxWExt(msg1, 'Python', opticam.WINDOW_OKCANCEL)
    if ret == 1:        # OK
        BaseDialog.ResetFlag = True
    elif ret == 2:      # CANCEL
        pass

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

class PostOptionsDialog(BasePostOptionsDialog):
    '''Represents the robofil-main-window for the PostOptions user-dialogs.'''     # can be accessed via __doc__
    def __init__(self, parent=None, modal=False, hasPages="-1"):

        postVar.clear()     # start new
        postVar['winTitle'] = 'Base Postprocessor Options'
        postVar['winLogo'] = 'OPTICAM_Logo.ico'

        BasePostOptionsDialog.__init__(self, parent, postVar['winTitle'], modal)

        # create the GroupPanel and add all the child widgets to main sizer
        fpnl = BaseGroupPanel(self.panel, wx.ID_ANY)
        self.vbxV1.Add(fpnl, 0, wx.EXPAND|wx.TOP, BORDER)

    def OnOK(self, event):
        # IMPORTANT: CALL BASE-CLASS METHOD first (reads out data from the controls)
        BasePostOptionsDialog.OnOK(event)

    def OnESC(self, event):
        # IMPORTANT: CALL BASE-CLASS METHOD first (reads out data from the controls)
        BasePostOptionsDialog.OnESC(self, event)


#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

from tabpanel import BaseTabPanel #TODO: move to top of file

class TabPanel(BaseTabPanel):
    '''Represents a sub-window with several tabs.'''     # can be accessed via __doc__

    def createGroup1(self):
        # Generell        
        scrPanel = ScrolledBasePanel(self, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL|wx.BORDER_NONE, scrollable=True)

        page = GroupPage1(scrPanel, wx.ID_ANY)
        
        szr = wx.BoxSizer( wx.VERTICAL )
        szr.Add(page, 0, wx.EXPAND)        
        scrPanel.SetSizerAndFit(szr)

        self.AddPage(scrPanel, "General", select=True)
        
    def createGroup2(self):
        # NC-Ausgabe Optionen
        scrPanel = ScrolledBasePanel(self, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL|wx.BORDER_NONE, scrollable=True)

        page = GroupPage2(scrPanel, wx.ID_ANY)

        szr = wx.BoxSizer( wx.VERTICAL )
        szr.Add(page, 0, wx.EXPAND)        
        scrPanel.SetSizerAndFit(szr)
        
        self.AddPage(scrPanel, "NC output", select=False)
        
    def createGroup3(self):
        # Simulation
        scrPanel = ScrolledBasePanel(self, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL|wx.BORDER_NONE, scrollable=True)

        page = GroupPage3(scrPanel, wx.ID_ANY)
        
        szr = wx.BoxSizer( wx.VERTICAL )
        szr.Add(page, 0, wx.EXPAND)        
        scrPanel.SetSizerAndFit(szr)
        
        self.AddPage(scrPanel, "Simulation", select=False)
        
    def createGroup4(self):
        # implement additional pages in the derived classes
        # -> create a new one or overwrite there
#        scrPanel = ScrolledBasePanel(self, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL|wx.BORDER_NONE, scrollable=True)
#
#        page = GroupPage4(scrPanel, wx.ID_ANY)
#        
#        szr = wx.BoxSizer( wx.VERTICAL )
#        szr.Add(page, 0, wx.EXPAND)        
#        scrPanel.SetSizerAndFit(szr)
#
#        self.AddPage(scrPanel, "MyPage", select=False)
        pass

    def createGroup5(self):
        # Setupsheet
        scrPanel = ScrolledBasePanel(self, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL|wx.BORDER_NONE, scrollable=True)

        page = GroupPage5(scrPanel, wx.ID_ANY)
        
        szr = wx.BoxSizer( wx.VERTICAL )
        szr.Add(page, 0, wx.EXPAND)        
        scrPanel.SetSizerAndFit(szr)
        
        self.AddPage(scrPanel, "Setupsheet", select=False)
        
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



def run(parent = None):
    if parent is None:      # choose the best handler as parent for the options-window
        parent = getCurrentDoc().DocumentWindow()
    postDlg = PostOptionsDialog(parent, modal=False)     # Dialog with no blocking
    # Resize BaseDialog
    postDlg.CreateControls()
    postDlg.Activate()

if __name__ == '__main__':
    run()