import sys
from sys import exit
import os
import time
import openpyxl
import tkinter
from numpy import exp, log, log10, sin, cos, tan, arcsin, arccos, arctan, sqrt


v = os.environ.get('tklibPath', None)
if v:
    tklib_path = v
else:
    script_path = sys.argv[0]
    tkProgRoot  = os.path.join(script_path, '../../..')
    tklib_path  = os.path.abspath(os.path.join(tkProgRoot, 'tklib/python'))

print(f"Add [{tklib_path}] to PYTHONPATH by sys.path.append()")
sys.path.append(tklib_path)


from tklib.tkutils import getarg, getintarg, getfloatarg, pint, pfloat, terminate, get_os, split_file_path, get_dirname
from tklib.tkinifile import tkIniFile
from tklib.tkparams import tkParams
from tklib.tkgui.tkapplication_gui import tkApplication_GUI
import tklib.tkgui.tktkinter as tktkinter

import bayes_gp_plain_shimizu as c_engine


"""
GUI for bayes_gp_plain.py
"""


usage_str = '''
"(i)   usage: python {}".format(sys.argv[0])
'''[1:-1]


#==============================================
# Global bariables
#==============================================

prog_name = 'Bayes/GP GUI'
version = [1, 3, 1]


#=============================
# Treat argments
#=============================
def usage(app):
#    cparams = app.get_params()
#    app.usage(infile = cparams.infile)
    for s in app.usage_str.split('\n'):
        cmd = 'print({})'.format(s.rstrip())
        eval(cmd)

def initialize(app, config):
#================================
# Global variables
#================================
    ctkvars = app.tkvars
    tkvars  = ctkvars.get_param_dict()

# Non-configurable configuration
    app.prm_file_type  = [('prm file', '*.prm')]
    app.data_file_type = [('data file', '*.csv')]

    app.resource_dir   = os.path.join(app.script_dir, 'resource')

# Configurable configuration
    config = app.config
    config.lang            = 'en'
    config.debug           = 0
    config.print_level     = 0
    config.confirm_on_exit = True
    config.minsize         = [200, 200]
    config.geometry        = "507x447"
    config.left_pane_width = 500
    config.message_box_width  = 100
    config.message_box_height = 4
    config.head_label_width   = 10
    config.entry_width        = 30
    config.button_width       = 12

# Define var types in config for auto type conversion in config.read_parameters()
    config.editor_path = ''
    config.infile      = ''
    config.outfile     = ''
    config.outresfile  = ''
    config.score_mode  = 'EI'

    config.program_path = ''


def update_vars(app, cparams):
    argv = app.argv
#    if len(argv) <= 1:
#        app.terminate(usage = usage)

#    cparams.infile = getarg(1, cparams.infile)


def create_menu(app, config, cparams, root_window):
    menu_bar  = app.create_menu()

    menu_file = tktkinter.Menu(app, menu_bar, tearoff = 0)
    menu_file.add_command(label = app.p('Open'), accelerator = 'Ctrl+O', 
                command = lambda: data_path_button_click(app, tkvars))
    menu_file.add_command(label = app.p('exit'), accelerator='Alt+E', command = lambda: app.on_closing())
    menu_bar.add_cascade(label = app.p('File'), menu = menu_file)

    menu_tool = tkinter.Menu(menu_bar, tearoff = 0)
    menu_tool.add_command(label = app.p('Setup'), accelerator = 'Ctrl+u', 
                command = lambda e: app.dialog_setup(
                        widgets = 'editor_path|confirm_on_exit|debug_mode'))
    menu_bar.add_cascade(label = app.p('Tool'), menu = menu_tool)
#    menu_bar.bind_all("<Alt-o>", onOpen)
    menu_bar.bind_all("<Alt-e>", lambda e: app.on_closing())
    menu_bar.bind_all("<Alt-u>", lambda e: app.dialog_setup(
                        widgets = 'editor_path|python3_path|python2_path|perl_path|confirm_on_exit|debug_mode'))

    return menu_bar

def create_toolbar(app, config, cparams, root_window):
    ctkvars = app.tkvars
    tkvars  = ctkvars.get_param_dict()
    config  = app.configparams

    def toolbar_clickevent(event):
        pass

    tool_bar = app.create_toolbar(bg = 'blue')

    setupButton = tktkinter.Button(app, tool_bar, text = "Setup", font = ("", 10),
                    command = lambda: app.dialog_setup(
                                    entry_width = 50, button_width = 10, edit_button_width = 10, 
                                    shell_button_width = 0, 
                                    widgets = 'editor_path|confirm_on_exit|debug_mode',
                                    is_print = True))
    setupButton.pack(side = tkinter.LEFT, anchor = 'w', padx = 1, pady = 0)

    def edit_inifile():
        editor = config.get("editor_path", None)
        if editor is None== '' or editor == '':
            tktkinter.dialog_okcancel(app, title = app.p('Error'), message = 'editor_path is not specified.')
            return
        
        tktkinter.execute_command(app, config.editor_path, working_dir = '.', is_print = True, files = [config.inifile])

    edit_ini_Button = tktkinter.Button(app, tool_bar, text = 'Edit ini file', font = ("", 10),
                    command = edit_inifile)
    edit_ini_Button.pack(side = tkinter.LEFT, anchor = 'w', padx = 1, pady = 0)

    def lang_sel_change(e):
        config.lang = tkvars['lang_combobox'].get()
        phrases = {'WillApplyUponReboot': {'ja': f'日本語に変更されました。再起動後に有効になります',
                                           'en': f'Changed to English. Will be applied after reboot'
                                          }
                  }
        tktkinter.dialog_okcancel(app, title = app.p('Quit'), message = app.p('WillApplyUponReboot', phrases = phrases))
        

    tkvars['lang'] = tkinter.StringVar(value = config.lang)
#    optionmenu = tkinter.OptionMenu(tool_bar, tool_bar, 'ja', 'en')
#    optionmenu.pack(side = tkinter.LEFT, anchor = 'w', padx = 1, pady = 0)
    combobox = tkinter.ttk.Combobox(tool_bar, values = ('ja', 'en'), width = 2)
    combobox.set(tkvars['lang'].get())
    combobox.bind('<<ComboboxSelected>>', lang_sel_change)
    combobox.pack(side = tkinter.LEFT, anchor = 'w', padx = 1, pady = 0)
    tkvars['lang_combobox'] = combobox

    exitButton = tktkinter.Button(app, tool_bar, text = 'Exit', font = ("", 10),
                    command = lambda: app.on_closing(), anchor = tkinter.NW)
    exitButton.pack(side = tkinter.LEFT, anchor = 'w', padx = 1, pady = 0)

def copy_tkvars(app, cparams, tkvars):
    config  = app.configparams

#    for key in ["script_path", "prmpath", "infile", "outfile", "max_num_probes", "num_search_each", "num_rand_basis", "interval", "score_mode"]:
    for key in ["program_path", "infile", "outfile", 
                "nx_2D", "ny_2D",
                "max_num_probes", "num_search_each", "num_rand_basis", "interval", "score_mode", "random_seed", "standardize",
                "fontsize", "legend_fontsize"]:
        cparams.set_attr(key, tkvars[key].get())

    for key in ["program_path", "infile", "outfile", "outresfile","fontsize", "legend_fontsize"]:
        config.set_attr(key, tkvars[key].get())

    cparams.set_attr('figsize', [tkvars['fig_width'].get(), tkvars['fig_height'].get()])

def copy_config(app, cparams, config):
    keys0 = config.__dict__.keys()
    for key in cparams.__dict__.keys():
        if key in keys0:
            cparams.set_attr(key, cparams.get(key, None))

def create_graph_tab(app, config, cparams, parent_notebook):
    config  = app.configparams
    ctkvars = app.tkvars
    tkvars  = ctkvars.get_param_dict()

    page1_frame = tktkinter.Frame(app, parent_notebook, bg = 'dim gray')
    page1_frame.pack()
    parent_notebook.add(page1_frame, text = app.p('Graph'))
    notebook_frame = page1_frame

# Graph parameter block
    graph_grid_frame = tkinter.Frame(page1_frame)
    frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, graph_grid_frame,
                  varname = "fig_width", vartype = 'int',
                  defval = [config, 12], from_ = 1, to = 100, increment = 1, box_width = 6,
                  reset_val = 12,
#                  help_text = 'Width of graph window. Default: 12',
                  button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'},
                  button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'},
                  igridrow = 4)
    frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, graph_grid_frame,
                  varname = "fig_height", vartype = 'int',
                  defval = [config, 8], from_ = 1, to = 100, increment = 1, box_width = 6, 
                  reset_val = 8,
#                  help_text = 'Hight of graph window. Default: 8',
                  button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'},
                  button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'},
                  igridrow = 5)
    frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, graph_grid_frame,
                  varname = "fontsize", vartype = 'int',
                  defval = [config, 16], from_ = 1, to = 100, increment = 1, box_width = 6, 
                  reset_val = 16,
                  help_text = 'Size of graph font. Default: 16',
                  button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'},
                  button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'},
                  igridrow = 6)
    frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, graph_grid_frame,
                  varname = "legend_fontsize", vartype = 'int',
                  defval = [config, 8], from_ = 1, to = 100, increment = 1, box_width = 6, 
                  reset_val = 8,
                  help_text = 'Size of legend font. Default: 8',
                  button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'},
                  button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'},
                  igridrow = 7)

    return notebook_frame

def create_main_tab(app, config, cparams, parent_notebook):
    config  = app.configparams
    ctkvars = app.tkvars
    tkvars  = ctkvars.get_param_dict()

    page1_frame = tktkinter.Frame(app, parent_notebook, bg = 'dim gray')
    page1_frame.pack()
    parent_notebook.add(page1_frame, text = app.p('Analyze'))
    notebook_frame = page1_frame

    applications = app.get_external_apps(config.get("editor_path", None))

    path_grid_frame = tkinter.Frame(page1_frame)
# Parameter path frame
    """
    tktkinter.make_path_frame(app, cparams, page1_frame, path_grid_frame, 
                    tkvars, varname = 'prmpath', 
                    file_type = [("Parameter", "*.prm"), ("All", "*.*")],
                    working_dir = '.', 
                    is_print = True, igridrow = 0)
    """

# Input path frame
    def open_file(input_entry, output_entry, outres_entry, file_type = None, ini_dir = None):
        ini = tkIniFile(path = config.inifile)
        if ini_dir is None:
            ini_dir = ini.get_string(section = "work_dir", key = "last_dir", def_val = '.', is_print = False)

        tktkinter.path_button_click(app, input_entry, file_type = file_type, ini_dir = ini_dir)
        file_path = input_entry.get()

        outfile = app.replace_path(file_path, 
                    template = ["{dirname}", "{filebody}-predict{i}.xlsx"], ext_dict = {'i': '{i}'})
        output_entry.set(outfile)
        cparams.outfile = outfile

        outresfile = app.replace_path(file_path, 
                    template = ["{dirname}", "{filebody}-save{i}.npz"], ext_dict = {'i': '{i}'})
        outres_entry.set(outresfile)
        cparams.outresfile = outresfile

        ini.write_string(section = "work_dir", key = "last_dir", value = dir, is_print = False)


    tktkinter.make_path_frame(app, cparams, page1_frame, path_grid_frame, 
                    tkvars, varname = 'infile', 
                    file_type = [("Excel", "*.xlsx"), ("CSV", "*.csv"), ("All", "*.*")],
                    working_dir = '.', 
                    head_label_width = config.head_label_width,
                    entry_width = config.entry_width,
                    button_width = config.head_label_width,
                    edit_button_width = 0,
                    shell_button_width = 0,
                    open_command = lambda app, cparams, file_type, ini_dir: \
                                        open_file(tkvars["infile"], tkvars["outfile"], tkvars["outresfile"], file_type, ini_dir = None),
#                    post_open_command = lambda: post_open(tkvars["infile"], tkvars["outfile"]),
                    is_print = True, igridrow = 1)

# Output path frame
    tktkinter.make_path_frame(app, cparams, page1_frame, path_grid_frame, 
                    tkvars, varname = 'outfile', 
                    file_type = [("Excel", "*.xlsx"), ("All", "*.*")],
                    working_dir = '.', 
                    head_label_width = config.head_label_width,
                    entry_width = config.entry_width,
                    button_width = config.button_width,
                    edit_button_width = 0,
                    shell_button_width = 0,
                    is_print = True, igridrow = 2)

# npz path frame
    tktkinter.make_path_frame(app, cparams, page1_frame, path_grid_frame, 
                    tkvars, varname = 'outresfile', 
                    file_type = [("npz", "*.npz"), ("All", "*.*")],
                    working_dir = '.', 
                    head_label_width = config.head_label_width,
                    entry_width = config.entry_width,
                    button_width = config.button_width,
                    edit_button_width = 0,
                    shell_button_width = 0,
                    is_print = True, igridrow = 3)

# Button
    def analyze(app, cparams, tkvars):
        copy_tkvars(app, cparams, tkvars)
        print("")
        print("Execute analysis")
        c_engine.execute(app, cparams, wait_by_input = False)

    def validate(app, cparams, tkvars):
        copy_tkvars(app, cparams, tkvars)
        print("")
        print("Execute analysis")
        c_engine.validate(app, cparams, wait_by_input = False)

    def usage_cli(app, cparams, tkvars):
        copy_tkvars(app, cparams, tkvars)
        print("")
#        cparams.infile = tkvars['infile'].get()
        c_engine.usage(app)

    button_frame = tkinter.Frame(page1_frame)
    button1 = tktkinter.Button(app, button_frame, text = 'analyze', width = 8, font = ("", 16),
                        command = lambda: analyze(app, cparams, tkvars))
    button1.pack(side = tkinter.LEFT)
    button2 = tktkinter.Button(app, button_frame, text = 'validate', width = 8, font = ("", 16),
                        command = lambda: validate(app, cparams, tkvars))
    button2.pack(side = tkinter.LEFT)
    button3 = tktkinter.Button(app, button_frame, text = 'citation', width = 8, font = ("", 10),
                        command = lambda: c_engine.citation(app))
    button3.pack(side = tkinter.RIGHT)
    button4 = tktkinter.Button(app, button_frame, text = 'usage(cli)', width = 8, font = ("", 10),
                        command = lambda: usage_cli(app, cparams, tkvars))
    button4.pack(side = tkinter.RIGHT)
    button_frame.pack(side = tkinter.TOP, anchor = 'w', padx = 2, pady = 2, fill = tkinter.X, expand = True)

# Parameter block
    vars_grid_frame = tkinter.Frame(page1_frame)
    frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                  varname = 'nx_2D', vartype = 'int', 
                  defval = [config, 11], from_ = 1, to = 101, increment = 10, box_width = 6, 
                  reset_val = 11,
#                  help_text = 'ma_num_probes',
                  button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'},
                  button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'},
                  igridrow = 0)
    frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                  varname = 'ny_2D', vartype = 'int', 
                  defval = [config, 11], from_ = 1, to = 100, increment = 10, box_width = 6, 
                  reset_val = 11,
#                  help_text = 'ma_num_probes',
                  button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'},
                  button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'},
                  igridrow = 1)
    frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                  varname = 'max_num_probes', vartype = 'int', 
                  defval = [config, 1], from_ = 1, to = 100, increment = 5, box_width = 6, 
                  reset_val = 1,
#                  help_text = 'ma_num_probes',
                  button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'},
                  button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'},
                  igridrow = 2)
    frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                  varname = 'num_search_each', vartype = 'int',
                  defval = [config, 1], from_ = 1, to = 100, increment = 5, box_width = 6, 
                  reset_val = 1,
#                  help_text = 'Number of probes at each iteration. Default: 0',
                  button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'},
                  button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'},
                  igridrow = 3)
    frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                  varname = "num_rand_basis", vartype = 'int',
                  defval = [config, 200], from_ = 1, to = 5000, increment = 50, box_width = 6, 
                  reset_val = 200,
#                  help_text = 'Number of random Gauss bases. Default: 200',
                  button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'},
                  button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'},
                  igridrow = 4)
    frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                  varname = "interval", vartype = 'int',
                  defval = [config, 0], from_ = 1, to = 5000, increment = 10, box_width = 6, 
                  reset_val = 0,
#                  help_text = 'Iterations to update hyper parameters. Default: 0',
                  button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'},
                  button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'},
                  igridrow = 5)
    frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                  varname = "score_mode", vartype = 'str',
                  defval = [config, 'EI'], values = ['EI', 'PI', 'TS'], box_width = 6, 
                  reset_val = 'EI',
#                  help_text = 'Type of aquisition function. Default: EI',
                  button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'},
                  button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'},
                  igridrow = 6)
    frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                  varname = "random_seed", vartype = 'str',
                  defval = '', 
                  reset_val = '',
#                  help_text = 'Seed for random numbers. Leave blank ("": null) to apply random seed. ' \
#                            + 'Specify an integer if you need reprodcible random numbers. Default: ""[null]',
                  button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'},
                  button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'},
                  igridrow = 7)

    frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                  varname = "fraction_test", vartype = 'float',
                  defval = 0.0, from_ = 0.0, to = 1.0, increment = 0.1, box_width = 6, 
                  reset_val = 0.0,
#                  help_text = 'Fraction or number of test data. < 1.0 specifies fraction >= 1 specifies the number. Default: 0.0',
                  button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'},
                  button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'},
                  igridrow = 8)

    frame = tktkinter.make_check_box(app, cparams, tkvars, page1_frame, vars_grid_frame,
                  varname = "standardize", label = 'standardize', 
                  reset_val = 1,
#                  help_text = 'Number of random Gauss bases. Default: 200',
                  button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'},
                  button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'},
                  onvalue = 1, offvalue = 0,
                  igridrow = 9)

# Message text box
    textframe = tktkinter.Frame(app, page1_frame, bg = 'dim gray')
    message_box = tktkinter.Text(app, textframe, 
                        width = config.get("message_box_width", 100), height = config.get("message_box_height", 5))
    scrollbar = tkinter.Scrollbar(textframe, orient = tkinter.VERTICAL, command = message_box.yview)
    message_box["yscrollcommand"] = scrollbar.set
    message_box.grid(row = 0, column = 0)
    scrollbar.grid(row = 0, column = 1, sticky = (tkinter.N, tkinter.S))
    textframe.pack(side = tkinter.TOP, anchor = 'w', expand = True, padx = 2, pady = 2)
    tkvars['message_box'] = message_box

    return notebook_frame


def create_canvas_tab(app, config, cparams, pane, title):
    title = app.p(title)
    frame = tktkinter.Frame(app, pane, bg='dim gray')
    pane.add(frame, text = title)

    app.canvas = tktkinter.Canvas(app, frame)

    return frame

def create_left_frame4(app, config, cparams,  pane, title):
    title = app.p(title)
    frame = tktkinter.Frame(app, pane, bg='dim gray')
    pane.add(frame, text = title)

    treeview = tkinter.ttk.Treeview(frame, columns=["colA", "colB", "colC"])
    treeview.column("#0", width=100)
    treeview.column("colA", width=80)
    treeview.column("colB", width=80)
    treeview.column("colC", width=80)
    treeview.heading("#0", text="階層列")
    treeview.heading("colA", text="データ列A")
    treeview.heading("colB", text="データ列B")
    treeview.heading("colC", text="データ列C")
    itemAId = treeview.insert("",      tkinter.END, text="itemA", open=True, values=("data1a", "data1b", "data1c"))
    itemBId = treeview.insert(itemAId, tkinter.END, text="itemB", open=True, values=("data2a", "data2b", "data2c"))
    itemCId = treeview.insert(itemBId, tkinter.END, text="itemC", values=("data3a", "data3b", "data3c"))
    itemDId = treeview.insert("",      tkinter.END, text="itemD", values=("data4a", "data4b", "data4c"))
    treeview.pack()        

def create_left_frame3(app, config, cparams,  pane, title):
    title = app.p(title)
    frame = tktkinter.Frame(app, pane, bg='dim gray')
    pane.add(frame, text = title)
    textframe = tktkinter.Frame(app, frame, bg='dim gray')
    textframe.pack()
    text = tkinter.Text(textframe, height = 4, width = 20)
    scrollbar = tkinter.Scrollbar(textframe, orient = tkinter.VERTICAL, command=text.yview)
    text["yscrollcommand"] = scrollbar.set
    text.grid(row=0, column=0)
    scrollbar.grid(row=0, column=1, sticky=(tkinter.N, tkinter.S))

    listbox = tkinter.Listbox(frame)
    for month in ("1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"):
        listbox.insert(tkinter.END, month)
    listbox.pack()

    output_text = tktkinter.Text(app, frame,
        width = 60,
        height = 10)
    output_text.pack(side = tkinter.TOP, anchor = 'w', expand = True, padx = 2, pady = 2)
#    tkvars['outputtext'] = output_text

def create_left_frame2(app, config, cparams,  pane, title):
    title = app.p(title)
    frame = tktkinter.Frame(app, pane, bg='dim gray')
    pane.add(frame, text = title)

    mb = tkinter.Menubutton(frame, text="menubutton:Select alphabet")
    mb.pack()
    menu = tkinter.Menu(mb)
    menu.add_command(label="A")
    menu.add_command(label="B")
    mb["menu"] = menu

    scale = tkinter.Scale(frame, width = 20, length = 300, label = 'title', 
                orient = tkinter.HORIZONTAL, showvalue = True,
                from_ = 0, to = 100, tickinterval = 20)
    scale.pack()

    class CustomDialog(tkinter.simpledialog.Dialog):
        def __init__(self, master, title=None) -> None:
            super(CustomDialog, self).__init__(parent=master, title=title)

        def body(self, master) -> None:
            entry = tkinter.Entry(master)
            entry.grid(column=0, row=0)
    
        def buttonbox(self):
            box = tkinter.Frame(self)
            self.button1 = tkinter.Button(box, text="OK", width=10, command=self.ok, state=tkinter.DISABLED)
            self.button1.pack(side=tkinter.LEFT, padx=5, pady=5)
            self.button2 = tkinter.Button(box, text="Cancel", width=10, command=self.cancel)
            self.button2.pack(side=tkinter.LEFT, padx=5, pady=5) 
            box.pack() 

        def switchButtonState(self):
            if self.button1['state'] == tk.DISABLED:
                self.button1['state'] = tk.NORMAL 

        def apply(self):  # ダイアログボックスを閉じた後
            pass
#            print(self.var.get()) 

    def display_dialog():
        CustomDialog(pane)
#        tkinter.simpledialog.Dialog(pane)

    button = tktkinter.Button(app, frame, text = "dialog", command = display_dialog)
    button.pack(side = 'top', anchor = 'w', padx = 5, pady = 5)
    
    progressbar = tkinter.ttk.Progressbar(frame, value = 50)
    progressbar.pack()

    check_var = tkinter.BooleanVar(value = True)
#    check_var.set(True)

# イベントハンドラーでget()しないと正常に初期化されない
    def checked_button():
#        print("checked", check_var.get())
        check_var.get()
        
    check = tkinter.Checkbutton(frame, variable = check_var, text = '選択しますか？',
                                onvalue = True, offvalue = False,
                                command = checked_button)
    check.pack()

    var = tkinter.StringVar()
    var.set('aaa')
    optionmenu = tkinter.OptionMenu(frame, var, 'aaa', 'bbb')
    optionmenu.pack()

    combobox = tkinter.ttk.Combobox(frame, values=('aaa', 'bbb', 'ccc'))
    combobox.pack()
        
    rdvar = tkinter.StringVar()
    rdvar.set('B')
    aButton = tkinter.Radiobutton(frame, variable = rdvar, 
                value = 'A', text = 'Option A') #, command = self.showValue)
    aButton.pack()

    bButton = tkinter.Radiobutton(frame, variable = rdvar,
                value = 'B', text = 'Option B') #, command=self.showValue)
    bButton.pack()

    spinbox = tkinter.Spinbox(frame, cursor = 'clock', 
                from_ = 0, to = 100, increment = 3, format = '%12.6f')
    spinbox.pack()

    return frame

def create_window(app, config, cparams):
    ctkvars = app.tkvars
    tkvars  = ctkvars.get_param_dict()

    root_window = app.create_window(title = sys.argv[0], geometry = config.geometry, minsize = config.minsize)
#    menu_bar = create_menu(app, config, cparams, root_window)
    tool_bar = create_toolbar(app, config, cparams, root_window)
# 2分割ウインドウを使う場合。いづれのpaneもnotebook型ウインドウが作られる
#    panes = app.add_root_panes(root = root_window, type = "pane2", sashwidth = 2, left_pane_width = 600)
#    main_pane, left_notebook, right_notebook = panes
# 1分割ウインドウを使う場合。paneはnotebook型ウインドウが作られる
    panes = app.add_root_panes(type = "pane1", sashwidth = 2)
    left_notebook = panes[0]

# 左ペインのnotebookにタブを追加
    ltabframe1 = create_main_tab(app, config, cparams, left_notebook)
    ltabframe2 = create_graph_tab(app, config, cparams, left_notebook)
    ltabframe3 = app.create_development_tab(config, cparams, left_notebook, copy_tkvars = copy_tkvars)
    ltabframe4 = app.create_editor_tab(config, cparams, left_notebook, title = 'Editor test',
                    entry_width = 35, 
                    eval_button_args = { 'text': 'eval', 'width': 4, "command": None },
                    )
#    ltabframe6 = create_canvas_tab(app, config, cparams, left_notebook, title = 'Canvas test')
    ltabframe6 = create_left_frame2(app, config, cparams, left_notebook, title = 'Widget test1')
    ltabframe7 = create_left_frame3(app, config, cparams, left_notebook, title = 'Widget test2')
    ltabframe8 = create_left_frame4(app, config, cparams, left_notebook, title = 'Widget test3')

    app.mainloop()


def main():
#==================================================================
# Initialize parameters
#==================================================================
    app = tkApplication_GUI(usage_str = usage_str, globals = globals(), locals = locals(), 
                        use_user_inifile = True,
                        inifile_dirs = ['../../user', 'user'], create_inidir = False)
    app.env = os.environ
    
# 設定パラメータオブジェクト
    config  = app.configparams
    cparams = app.get_params()   # 計算エンジンのパラメータオブジェクト
    ctkvars = app.tkvars
    tkvars  = ctkvars.get_param_dict()
    mtime = time.localtime(os.path.getctime(app.script_path))

    print("")
    print( "################################################")
    print(f"# {app.script_path} ver {version[0]}.{version[1]}.{version[2]}")
    print(f"#       Modified time: {mtime.tm_year}/{mtime.tm_mon}/{mtime.tm_mday} {mtime.tm_hour}:{mtime.tm_min}:{mtime.tm_sec}")
    print( "################################################")

    print(f"Initialize parameters")
    initialize(app, config)

# 本GUIの設定パラメータオブジェクト
    config = app.configparams
# GUIウィジェット変数オブジェクトと辞書型
    ctkvars = app.tkvars
    tkvars  = ctkvars.get_param_dict()

    print(f"Read configration from [{config.inifile}]")
    config.read_parameters(path = config.inifile)

    print(f"Update parameters by command-line arguments")
    update_vars(app, cparams)

    app.resource_path = os.path.join(app.resource_dir, f'resource_{app.config.lang}.resource')
    app.phrases       = app.read_resource(app.resource_path, app.config.lang) #, app.phrases)

    work_dir = None
    infile = config.get('infile', None)
    if infile is not None:
        work_dir, basename, filebody, ext = split_file_path(infile)

    if work_dir is None:
        work_dir = config.get('work_dir', None)

    if work_dir is not None and work_dir != '':
        if os.path.exists(work_dir):
            os.chdir(work_dir)

    create_window(app, config, cparams)

    infile = config.get('infile', None)
    if infile is not None:
        work_dir, basename, filebody, ext = split_file_path(infile)
    if work_dir is not None:
        config.work_dir = work_dir

# ウィジェットの設定tkvarsをcparams,confgにコピー
    copy_tkvars(app, cparams, tkvars)
    copy_tkvars(app, config, tkvars)
# メインウインドウサイズをconfigにコピー
    config.geometry = app.root_window_geometry
    print("")
    print(f"Save configuration to [{config.inifile}]")
    config.save_parameters(path = config.inifile, section = 'Configure', sort_by_keys = True, IsPrint = False)

# 必要があれば、入力ファイルに対応するパラメータファイルを保存
    if tkvars.get("prmpath", None) is not None:
        cparams.prmpath  = tkvars["prmpath"].get()  #os.path.splitext(cparams.path)[0] + '.prm'
        if cparams.prmpath != '':
            print(f"Save parameters to [{cparams.prmpath}]")
            ret = cparams.save_parameters(cparams.prmpath, section = 'Parameters', 
                    sort_by_keys = True, IsPrint = False, update_commandline = False)
            if not ret:
                app.terminate(f"Error in main(): Cannot write to [{cparams.prmpath}]", usage = usage)

    app.terminate()


if __name__ == "__main__":
    main()

