#! /usr/bin/env python
#  -*- coding: utf-8 -*-
#
# Support module generated by PAGE version 7.5h
#  in conjunction with Tcl version 8.6
#    Jun 16, 2022 06:55:40 AM CDT  platform: Linux
#    Jun 17, 2022 02:53:04 AM CDT  platform: Linux
#    Jun 17, 2022 10:14:41 AM CDT  platform: Linux
#    Jun 17, 2022 11:08:34 AM CDT  platform: Linux
#    Jun 17, 2022 11:17:18 AM CDT  platform: Linux
#    Jun 18, 2022 04:31:32 AM CDT  platform: Linux
#    Jun 18, 2022 04:39:57 AM CDT  platform: Linux
#    Jun 18, 2022 05:45:39 AM CDT  platform: Linux
#    Jun 18, 2022 06:59:19 AM CDT  platform: Linux
#    Jun 18, 2022 07:52:19 AM CDT  platform: Linux
# ======================================================
#     widgetdemo_support.py
#  ------------------------------------------------------
# Created for PAGE 7.5h
# Written by G.D. Walters
# Copyright (c) 2022 by G.D. Walters
# This source code is released under the MIT License
# ======================================================
# Changes
#    Added support for Listbox Selectmode
#    Fix for showing Notebook Tab colours when running under Windows
# ======================================================
import sys
import datetime
from ScrolledCheckedListBox import ScrolledCheckedListBox
import glob
import os
# import platform
import webbrowser
from PIL import Image, ImageTk
# =============================================
import tkinter as tk
import tkinter.ttk as ttk
from tkinter.constants import *
# =============================================
import tkinter.messagebox as messagebox
# ===================================================
global has_ttkthemes
try:
    from ttkthemes import ThemedStyle

    has_ttkthemes = True
except:
    has_ttkthemes = False
# ===================================================

# =============================================
import widgetdemo
# =============================================
Version = "0.96.3"
debug = True
# =============================================


def main(*args):
    '''Main entry point for the application.'''
    global root
    root = tk.Tk()
    root.protocol('WM_DELETE_WINDOW', root.destroy)
    # Creates a toplevel widget.
    global _top1, _w1
    _top1 = root
    _w1 = widgetdemo.Main(_top1)
    startup()
    root.mainloop()


def startup():
    _top1.title(f'PAGE Widget Demo {Version}')
    location = widgetdemo._location
    global ImageDir
    ImageDir = os.path.join(location, "images", "icons")
    print(f'ImageDir: {ImageDir}')
    """
    The startup function will initialize various widgets and variables for the
    demo program.
    """
    global tab_names, page_2_seen
    page_2_seen = False
    tab_names = [
        "Standard Tk Widgets",
        "ttk Themed Widgets",
        "Enhanced Widgets",
        "Special Twists on Normal Widgets",
    ]
    # ===================================================
    # Set the next line to True if you want to see the debugging text
    # ===================================================
    # debug = False
    # ===================================================
    # Setup my own base style for the TNotebook

    setup_base_style()
    setup_application_general()
    setup_tab_0()
    setup_tab_1()
    setup_tab_2()
    setup_tab_3()


def setup_base_style():
    # ===================================================
    # Sets up a base style for the TNotebook.
    #   I blatently stole this from Don and hacked it to make it work
    #   for me.  You can use this as a guide to make your own.
    # ===================================================
    style = ttk.Style()
    global usros
    if sys.platform == "Linux" or sys.platform == "linux2":
        usros = 'Linux'
    elif sys.platform == "darwin":
        usros = "OS x"
    elif sys.platform == "win32":
        usros = "Windows"
    else:
        usros = 'Unknown'
    print(f'Running under {usros}')
    if usros == 'Windows':
        # style.theme_use('winnative')"
        # PAGE sets "winnative" in GUI module
        pass
    else:
        style.theme_use('default')
    style.map(
        "TNotebook.Tab",
        background=[
            ("selected", "gray54"),
            ("active", "gray86"),
            ("!active", "sandybrown"),
        ],
        foreground=[("selected", "white"), ("active", "black"),
                    ("!active", "black")],
    )


def setup_application_general():
    # ===================================================
    # Statusbar Clock stuff
    # ===================================================
    global timer_id
    timer_id = root.after(0, on_time_update)
    # ===================================================
    # Clear and initialize the status bars
    _w1.StatusInfo2.set("")
    nfo = f"Currently Viewing Tab 0"
    _w1.StatusInfo1.set(nfo)
    # ===================================================
    # Setup the callback that triggers when user changes a Notebook Tab
    _w1.TNotebook1.bind("<<NotebookTabChanged>>", on_TabChange)


def setup_tab_0():
    # ===================================================
    # Tk Widget Setup
    # ===================================================
    _w1.Checkbutton1.invoke()
    _w1.Radiobutton1.invoke()
    _w1.Radiobutton6.invoke()
    _w1.Radiobutton9.invoke()
    _w1.Radiobutton12.invoke()
    _w1.EntryDisplay.set("")
    _w1.ListDisplay.set("")
    # _w1.ScaleDisplay.set("")
    # ===================================================
    # Listbox Setup
    # ===================================================
    global demodata
    demodata = ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight"]
    for itm in demodata:
        _w1.Listbox1.insert("end", itm)
    _w1.Listbox1.bind("<<ListboxSelect>>", on_listboxSelect)
    # ===================================================
    # Entry Widget Bindings
    # ===================================================
    #_w1.Entry1.bind("<Button-3>", lambda e: widgetdemo.popup1(e, 1))
    _w1.Entry1.bind("<KeyRelease>", lambda e: on_entryKeyPress(e))
    # ===================================================
    # Setup for Canvas demo and start it
    # ===================================================
    start_canvas(329, 248)
    # ===================================================
    # Text widget demo code for Tk Textwidget
    # ===================================================
    setup_textwidget(1)
    # ===================================================
    # Scale and Spinbox demo code
    # ===================================================
    global AnimateTk_id, AniTkRunning, tkup
    AniTkRunning = False
    _w1.btnAnimateText.set("Start Animation")
    # _w1.ScaleDisplay.set(0)
    tkup = True
    # ===================================================
    # Message widget demo code
    # ===================================================
    setup_messagewidget()


def setup_tab_1():
    # ===================================================
    # ttk Widget Setup
    # ===================================================
    _w1.TCheckbutton1.invoke()
    _w1.TRadiobutton1.invoke()
    _w1.TSpinData.set("0")
    #_w1.TEntry1.bind("<Button-3>", lambda e: widgetdemo.popup1(e, 2))
    _w1.TEntry1.bind("<KeyRelease>", lambda e: on_TentryKeyPress(e))
    _w1.tch61.set(0)
    _w1.TBtnScaleAnimateText.set("Start Animation")
    _w1.TBtnProgText.set("Animate")
    _w1.TBtnProgAnimate.configure(state=DISABLED)
    # # ===================================================
    # # Setup the TCombobox and styles/themes
    # # ===================================================
    get_styles()
    _w1.TCombobox1.bind("<<ComboboxSelected>>", lambda e: on_ComboSelect(e))
    # # ===================================================
    # # Setup for ttk Animation
    # # ===================================================
    global Ani1Running, Ani2Running
    global Animate1_id, Ani1Running
    Ani1Running = False
    Ani2Running = False


def setup_tab_2():
    # ===================================================
    # Enhanced Widget setup routines
    # ===================================================
    setup_textwidget(2)
    # ===================================================
    # Setup the ScrolledEntry widget with a very long line.
    # ===================================================
    _w1.ScrolledTextData.set(
        "This is a very long line of data that can be scrolled to see the entire thing"
    )
    # ===================================================
    # Setup the ScrolledSpinbox
    # ===================================================
    value_list = [
        "The time has come for all good men to come to the aid of the party",
        "The quick red fox jumps over the lazy brown dog.",
        "Orange",
        "Banana",
        "I like to watch the minions.",
        "Here is another very long line for the ScrolledSpinbox widget!",
    ]
    value_list.sort()
    _w1.Scrolledspinbox1.configure(values=value_list)
    # ===================================================
    # Scrolled Listbox Setup
    # ===================================================
    global demodata2
    demodata2 = [
        "Eggs",
        "Bacon",
        "Toast",
        "Pancakes",
        "Waffles",
        "Omelette",
        "Coffee",
        "Milk",
        "Orange Juice",
        "Cereal",
        "Oatmeal",
        "Grapefruit",
    ]
    for itm in demodata2:
        _w1.Scrolledlistbox1.insert("end", itm)
    _w1.Scrolledlistbox1.bind("<<ListboxSelect>>", on_listboxSelect2)
    # ===================================================
    # Buttonbar (Scrolled Window) Stuff
    # ===================================================
    # Due to an issue with the ScrolledWindow in imbedded TNotebook
    # tabs, only call the build_buttonbar() function when
    #    a) Tab index two has NOT been seen
    #    b) Call it from the on_TabChange function
    # ===================================================
    _w1.IconName.set("")

    global folderimage
    global ImageDir

    photo_location = os.path.join(ImageDir, "document.png")
    print(f"Location: {photo_location}")
    folderimage = tk.PhotoImage(file=photo_location)
    setup_treeview()
    # ===================================================
    # Custom Control stuff
    # ===================================================
    LoadCustom()


def setup_tab_3():
    # ===================================================
    # Special Twists Tab startup
    # ===================================================
    _w1.Label11.bind("<Button-1>", lambda e: LabelLinkClick(1))
    _w1.Label12.bind("<Button-1>", lambda e: LabelLinkClick(2))
    _w1.Label13.bind("<Button-1>", lambda e: LabelLinkClick(3))
    root.update_idletasks()
    _w1.RepeatedCount.set("")
    global flash_count
    flash_count = 0
    global rcnt
    rcnt = 0
    _w1.RptDelay.set(500)
    _w1.RptInterval.set(200)
    _w1.Button6.bind("<ButtonRelease-1>", on_RepeatButtonReset)
    on_RepeatDelay()
    on_RepeatInterval()
    _w1.TimesToFlash.set(1)


def on_TabChange(e):
    global tab_names, page_2_seen, currenttab
    # ===================================================
    # Assigns the current TNotebook tab index (zero based) to the
    #    currenttab variable
    # ===================================================
    currenttab = _w1.TNotebook1.index("current")
    # ===================================================
    # Show the user which tab they are viewing in the status bar info #1
    # ===================================================
    nfo = f"Currently Viewing Tab {tab_names[currenttab]}"
    _w1.StatusInfo1.set(nfo)
    # ===================================================
    # To track the page_2_seen variable, enable the next print statement
    # ===================================================
    if debug:
        print(f"Page 2 seen: {page_2_seen}")
        print(f'CurrentTab: {currenttab}')
    if currenttab == 1:
        # ===================================================
        # Advertise the ScrolledTreeview widget (on Tab 2) in Status bar info #2
        #    if we are on the ttk Widget screen
        # ===================================================
        msg = (
            "To see the style for the ScrolledTreeview, \nchange to Enhanced Widgets tab"
        )
        _w1.StatusInfo2.set(msg)
    elif currenttab == 2:
        if page_2_seen == False:
            # ===================================================
            # Build the button bar ONLY IF the tab has not been shown before
            # ===================================================
            build_buttonbar()
            page_2_seen = True
        _w1.StatusInfo2.set('')
    else:
        # ===================================================
        # otherwise, clear the status bar info #2 label
        # ===================================================
        _w1.StatusInfo2.set("")


def on_btnExit(*args):
    if debug:
        print('widgetdemo_support.on_btnExit')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    sys.exit()


def on_mnuTab(*args):
    if debug:
        print('widgetdemo_support.on_mnuTab')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    which = args[0]
    if which == 0:
        _w1.TNotebook1.select(0)
    elif which == 1:
        _w1.TNotebook1.select(1)
    elif which == 2:
        _w1.TNotebook1.select(2)
    elif which == 3:
        _w1.TNotebook1.select(3)
    elif which == 4:
        sys.exit()


def on_CheckClick(*args):
    if debug:
        print('widgetdemo_support.on_CheckClick')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    displaylist = ["Off", "On"]
    c1 = _w1.che50.get()
    c2 = _w1.che51.get()
    c3 = _w1.che52.get()
    c4 = _w1.che53.get()
    disp = (
        f"{displaylist[c1]} - {displaylist[c2]} - {displaylist[c3]} - {displaylist[c4]}"
    )
    _w1.CheckDisplay.set(disp)


def on_HScale(*args):
    if debug:
        print('widgetdemo_support.on_HScale')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    valu = _w1.HScaleData.get()
    _w1.VScaleData.set(valu)
    _w1.SpinData.set(valu)
    _w1.SpinDisplay.set(valu)


def on_MsgJustify(*args):
    if debug:
        print('widgetdemo_support.on_MsgJustify')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    """
    Demonstrates the ability to change the justification of the entire message widget
    on the fly.  Not really useful in real life, but shows the the effect of the justify
    attribute of the messgae widget.
    """

    which = _w1.selectedButton2.get()
    if debug:
        print(which)
    if which == 1:
        _w1.Message1.configure(justify=LEFT)
    elif which == 2:
        _w1.Message1.configure(justify=CENTER)
    elif which == 3:
        _w1.Message1.configure(justify=RIGHT)


def on_RadioClick(*args):
    if debug:
        print('widgetdemo_support.on_RadioClick')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    which = _w1.selectedButton.get()
    disp = f"Option {which}"
    _w1.RadioDisplay.set(disp)


def on_Spin(*args):
    if debug:
        print('widgetdemo_support.on_Spin')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    valu = _w1.SpinData.get()
    _w1.VScaleData.set(valu)
    _w1.HScaleData.set(valu)
    _w1.SpinDisplay.set(valu)


def on_VScale(*args):
    if debug:
        print('widgetdemo_support.on_VScale')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    valu = _w1.VScaleData.get()
    _w1.SpinData.set(valu)
    _w1.HScaleData.set(valu)
    _w1.SpinDisplay.set(valu)


def on_popClear(*args):
    if debug:
        print('widgetdemo_support.on_popClear')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    if args[0] == 1:
        _w1.EntryData.set("")
        _w1.EntryDisplay.set("")
    else:
        _w1.TEntryData.set("")
        _w1.TEntryDisplay.set("")


def on_popCloseMenu(*args):
    if debug:
        print('widgetdemo_support.on_popCloseMenu')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()


def on_popCopy(*args):
    if debug:
        print('widgetdemo_support.on_popCopy')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    if args[0] == 1:
        root.clipboard_clear()  # clear clipboard contents
        root.clipboard_append(_w1.EntryData.get())
    else:
        root.clipboard_clear()  # clear clipboard contents
        root.clipboard_append(_w1.TEntryData.get())


def on_popExit(*args):
    if debug:
        print('widgetdemo_support.on_popExit')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    sys.exit()


def on_popPaste(*args):
    if debug:
        print('widgetdemo_support.on_popPaste')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    dat = root.clipboard_get()
    if args[0] == 1:
        _w1.EntryData.set(dat)
        _w1.EntryDisplay.set(dat)
    else:
        _w1.TEntryData.set(dat)
        _w1.TEntryDisplay.set(dat)


def on_LBActiveStyle(*args):
    if debug:
        print('widgetdemo_support.on_LBActiveStyle')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    which = _w1.selectedButton3.get()
    if which == 1:
        _w1.Listbox1.configure(activestyle=DOTBOX)
    elif which == 2:
        _w1.Listbox1.configure(activestyle=UNDERLINE)
    elif which == 3:
        _w1.Listbox1.configure(activestyle=NONE)
    else:
        pass


def on_LBSelectMode(*args):
    if debug:
        print('widgetdemo_support.on_LBSelectMode')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    which = _w1.selectedButton4.get()
    if which == 1:
        _w1.Listbox1.config(selectmode=SINGLE)
    elif which == 2:
        _w1.Listbox1.config(selectmode=BROWSE)
    elif which == 3:
        _w1.Listbox1.config(selectmode=MULTIPLE)
    elif which == 4:
        _w1.Listbox1.config(selectmode=EXTENDED)
    else:
        pass


# ===================================================
# Statusbar clock display code
# ===================================================
def on_time_update():
    # ======================================================
    # Callback function for the Time display
    # ======================================================
    global timer_id
    nowstring = f"{datetime.datetime.now():%X}"
    _w1.StatusTime.set(nowstring)
    timer_id = root.after(500, on_time_update)


def on_listboxSelect(e):
    indx = _w1.Listbox1.curselection()
    itm = _w1.Listbox1.get(indx[0])
    debug = True
    if debug:
        print(f"Selected Item: {indx[0]} - {itm}")
        print(f'Index: {indx}')
    if int(_w1.selectedButton4.get()) > 2:
        if debug:
            print(f'Selected: {indx}')
        _w1.ListDisplay.set(f"Selected: {indx}")
    else:
        _w1.ListDisplay.set(f"Selected Item: {indx[0]} - {itm}")


def on_entryKeyPress(e):
    if e.keysym == "Return":
        # do something here
        dat = _w1.EntryData.get()
        _w1.EntryDisplay.set(dat)


def setup_textwidget(which):
    """
    This sets the text into the tk text widget and sets the header line to a bold font
    """
    txtdata = """24. The Text widget
Text widgets are a much more generalized method for handling multiple lines of text than the Label widget. Text widgets are pretty much a complete text editor in a window:
• You can mix text with different fonts, colors, and backgrounds.
• You can intersperse embedded images with text. An image is treated as a single character. See Section 24.3, “Text widget images” (p. 86).
• An index is a way of describing a specific position between two characters of a text widget. See Section 24.1, “Text widget indices” (p. 84).
• A text widget may contain invisible mark objects between character positions. See Section 24.2, “Text widget marks” (p. 86).
• Text widgets allow you to define names for regions of the text called tags. You can change the appearance of a tagged region, changing its font, foreground and background colors, and other option. See Section 24.5, “Text widget tags” (p. 87).
• You can bind events to a tagged region. See Section 54, “Events” (p. 157).
• You can even embed a text widget in a “window” containing any Tkinter widget—even a frame widget containing other widgets. A window is also treated as a single character. See Section 24.4, “Text widget windows” (p. 87)."""

    if which == 1:
        _w1.Text1.insert(1.0, txtdata)
        header = ("Comic Sans MS", 20, "bold")
        _w1.Text1.tag_add("line", "1.0", "1.end")
        _w1.Text1.tag_config("line", font=header)
    else:
        _w1.Scrolledtext1.insert(1.0, txtdata)
        header = ("Comic Sans MS", 20, "bold")
        _w1.Scrolledtext1.tag_add("line", "1.0", "1.end")
        _w1.Scrolledtext1.tag_config("line", font=header)


def setup_messagewidget():
    """
    TK message box Setup function
    This sets the msg into the Message widget and left justifys it
    """
    # Data to put into Message Widget
    msg = """
    print('widgetdemo_support.on_tkRButton2')
    for arg in args:
        print('another arg:', arg)
    sys.stdout.flush()
    """
    _w1.MessageData.set(msg)
    # Initialize First Radio Button in Message Demo
    _w1.Radiobutton6.invoke()


# ===================================================
# START OF CANVAS DEMO FUNCTION
# ===================================================
def start_canvas(WIDTH, HEIGHT):

    # Original code from https://codereview.stackexchange.com/questions/175813/python-tkinter-bouncing-ball-animation
    import time

    canvas = _w1.Canvas1
    colour = "dodgerblue2"
    SIZE = 50

    class Ball:
        def __init__(self, tag):
            self.shape = canvas.create_oval(0,
                                            0,
                                            SIZE,
                                            SIZE,
                                            fill=colour,
                                            tags=tag)
            self.speedx = 9
            self.speedy = 9
            self.active = True

        def ball_update(self):
            canvas.move(self.shape, self.speedx, self.speedy)
            pos = canvas.coords(self.shape)
            if pos[2] >= WIDTH or pos[0] <= 0:
                self.speedx *= -1
            if pos[3] >= HEIGHT or pos[1] <= 0:
                self.speedy *= -1

    global switcher
    switcher = True

    def cycle():
        global switcher
        canvas.tag_raise("bg")
        if switcher:
            ball2.ball_update()
            ball2.ball_update()
            canvas.tag_raise("ball")
        else:
            ball.ball_update()
            ball.ball_update()
            canvas.tag_raise("ball2")
        _top1.update_idletasks()
        switcher = not switcher
        _top1.after(40, cycle)

    bg = canvas.create_rectangle(0,
                                 0,
                                 WIDTH + 1,
                                 HEIGHT + 1,
                                 fill="forestgreen",
                                 tags="bg")
    ball = Ball("ball")
    ball.ball_update()
    ball2 = Ball("ball2")

    _top1.after(0, cycle)


# ===================================================
# END OF CANVAS DEMO FUNCTION
# ===================================================


def on_ScaleAnimate(*args):
    if debug:
        print('widgetdemo_support.on_ScaleAnimate')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    global AnimateTk_id, AniTkRunning

    if AniTkRunning == False:
        AniTkRunning = True
        _w1.btnAnimateText.set("Stop Animation")
        AnimateTk_id = root.after(0, on_animateTk_update)
    else:
        _w1.btnAnimateText.set("Start Animation")
        root.after_cancel(AnimateTk_id)
        AniTkRunning = False


def on_animateTk_update():
    """
    root.after callback for the Tk Widget animation routine.
    """

    global AnimateTk_id, tkup
    val1 = _w1.SpinData.get()
    valu = int(float(val1))
    if tkup:
        if valu < 11:
            valu += 1
        else:
            tkup = False
    else:
        if valu > -1:
            valu -= 1
        else:
            tkup = True
    _w1.SpinData.set(valu)
    on_Spin()
    AnimateTk_id = root.after(250, on_animateTk_update)


def on_FixLabelBackgrounds(*args):
    if debug:
        print('widgetdemo_support.on_FixLabelBackgrounds')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    # ===================================================
    # Use an existing widget that gets the background set to get the background colour
    #   This sets the Toplevel background to whatever Style considers a "normal"
    #   background colour by quering the background of the first TLabelframe.
    # ===================================================
    if _w1.tch57.get() == 1:
        bg = sty.lookup(_w1.TLabelframe1, "background")
        _top1.configure(background=bg)
        # Since most styles/themes ignore TLabel background,
        #   Set the TLabel2 background
        tlabels = [
            _w1.TLabel1,
            _w1.TLabel2,
            _w1.TLabel3,
            _w1.TLabel4,
            _w1.TLabel5,
            _w1.TLabel6,
            _w1.TLabel7,
            _w1.TLabel8,
            _w1.TLabel9,
            _w1.TLabel10,
            _w1.TLabel11,
            _w1.TLabel12,
        ]
        for tlab in tlabels:
            tlab.configure(background=bg)
        root.update()
    nbg = sty.lookup(_w1.TNotebook1_t2, "background")
    if debug:
        print(f"Notebook tab background: {nbg}")


def on_TChkForceBorders(*args):
    if debug:
        print('widgetdemo_support.on_TChkForceBorders')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    if _w1.tch58.get() == 1:
        TLFramelist = [
            _w1.TLabelframe1,
            _w1.TLabelframe2,
            _w1.TLabelframe3,
            _w1.TLabelframe4,
            _w1.TLabelframe5,
            _w1.TLabelframe6,
            _w1.TLabelframe7,
        ]
        for tlf in TLFramelist:
            tlf.configure(borderwidth=1)
            tlf.configure(relief=RAISED)
        _w1.TPanedwindow1_p1.configure(borderwidth=1)
        _w1.TPanedwindow1_p2.configure(borderwidth=1)
        _w1.TPanedwindow1_p1.configure(relief=GROOVE)
        _w1.TPanedwindow1_p2.configure(relief=GROOVE)
        _w1.TPanedwindow2_p1.configure(borderwidth=1)
        _w1.TPanedwindow2_p1.configure(relief=GROOVE)
        _w1.TPanedwindow2_p2.configure(borderwidth=1)
        _w1.TPanedwindow2_p2.configure(relief=GROOVE)


def on_THScale(*args):
    if debug:
        print('widgetdemo_support.on_THScale')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    valu = _w1.THScaleData.get()
    _w1.TSpinDisplay.set(valu)
    _w1.TSpinData.set(valu)
    _w1.TVScaleData.set(valu)


def on_TProgAnimate(*args):
    if debug:
        print('widgetdemo_support.on_TProgAnimate')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    global Ani2Running
    if Ani2Running == False:
        Ani2Running = True
        _w1.TBtnProgText.set("Stop Animation")
        _w1.TProgressbar1.start()
    else:
        Ani2Running = False
        _w1.TBtnProgText.set("Animate")
        _w1.TProgressbar1.stop()


def on_TProgCheck(*args):
    if debug:
        print('widgetdemo_support.on_TProgCheck')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    global Ani2Running
    if _w1.tch61.get() == 1:
        _w1.TBtnProgAnimate.configure(state=NORMAL)
    else:
        _w1.TBtnProgAnimate.configure(state=DISABLED)


def on_TSpin(*args):
    if debug:
        print('widgetdemo_support.on_TSpin')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    valu = _w1.TSpinData.get()
    _w1.TSpinDisplay.set(valu)
    _w1.TVScaleData.set(valu)
    _w1.THScaleData.set(valu)


def on_TSpinAnimate(*args):
    if debug:
        print('widgetdemo_support.on_TSpinAnimate')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    global Animate1_id, Ani1Running
    if Ani1Running == False:
        Ani1Running = True
        _w1.TBtnScaleAnimateText.set("Stop Animation")
        Animate1_id = root.after(0, on_animate1_update)
    else:
        Ani1Running = False
        _w1.TBtnScaleAnimateText.set("Start Animation")
        root.after_cancel(Animate1_id)


def on_animate1_update():
    global Animate1_id
    val1 = _w1.TSpinData.get()
    # Convert val1 to a float then to an integer - Keeps a conversion error from happening.
    valu = int(float(val1))
    on_TSpin()
    valu += 1
    if valu > 10:
        valu = 0
    _w1.TSpinData.set(valu)
    Animate1_id = root.after(250, on_animate1_update)


def on_TVScale(*args):
    if debug:
        print('widgetdemo_support.on_TVScale')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    valu = _w1.TVScaleData.get()
    _w1.TSpinDisplay.set(valu)
    _w1.THScaleData.set(valu)
    _w1.TSpinData.set(valu)


def on_FlashButton(*args):
    if debug:
        print('widgetdemo_support.on_FlashButton')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    ttf = int(_w1.TimesToFlash.get())
    if ttf > 1:
        for counter in range(1, ttf):
            _w1.Button5.flash()
    else:
        _w1.Button5.flash()


def on_FlashButtonCount(*args):
    if debug:
        print('widgetdemo_support.on_FlashButtonCount')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()


def on_RepeatDelay(*args):
    if debug:
        print('widgetdemo_support.on_RepeatDelay')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    _w1.Button6.configure(repeatdelay=int(_w1.RptDelay.get()))


def on_RepeatInterval(*args):
    if debug:
        print('widgetdemo_support.on_RepeatInterval')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    _w1.Button6.configure(repeatinterval=int(_w1.RptInterval.get()))


def on_TentryKeyPress(e):
    if e.keysym == "Return":
        dat = _w1.TEntryData.get()
        _w1.TEntryDisplay.set(dat)


# ===================================================
# Callback for the TCombobox that selects the ttk Theme to be used
# ===================================================
def on_ComboSelect(e):
    selected = _w1.combobox.get()
    if debug:
        print(f"Combobox Select: {selected}")
    _w1.TNotebook1_t1.configure(background="#d9d9d9")
    _w1.TNotebook1_t2.configure(background="#d9d9d9")

    global sty
    selected = _w1.combobox.get()
    if debug:
        print(f"Selected Style: {selected}")
    _w1.TComboDisplay.set(f"Combobox Select {selected}")
    sty.theme_use(selected)

    # Added following block of code. Since the mappings do not
    # stick over changes of theme something like this should be
    # added. I think that there is more like the stuff at the top of
    # the GUI module. Rozen
    style = ttk.Style()
    style.map(
        "TNotebook.Tab",
        background=[
            ("selected", "gray54"),
            ("active", "gray86"),
            ("!active", "sandybrown"),
        ],
        foreground=[("selected", "white"), ("active", "black"),
                    ("!active", "black")],
    ) # End of block
    
    if _w1.tch57.get() == 1:
        on_TChkForceBorders()
    on_FixTLabelFrameBorders()
    on_FixLabelBackgrounds()


# ===================================================
# Gets a list of the ttk Themes that are supported on
#   the user's system.
# ===================================================
def get_styles():

    global style_names, sty, usros
    # Try to set the default theme to "default" for non-windows or "winnative"for Windows.
    if has_ttkthemes:
        # You must use "ThemedStyle" to get the style names that ttkthemes provides.
        # If you don't only only get the names that the OS provides.
        sty = ThemedStyle()
    else:
        sty = ttk.Style()
    style_names = list(sty.theme_names())
    if debug:
        print(style_names)
    style_names.sort(reverse=False)
    # Load the theme names into the Combobox widget
    _w1.TCombobox1["values"] = style_names
    # Force the combobox to the default theme for the OS
    if usros == "Windows":
        ndx = style_names.index("winnative")
    else:
        ndx = style_names.index("default")
    if debug:
        print(f"NDX: {ndx}")
    _w1.TCombobox1.current(ndx)
    selected = _w1.combobox.get()
    dsply = f"Combobox Select {selected}"
    _w1.TComboDisplay.set(f"Combobox Select {selected}")


def on_FixTLabelFrameBorders():
    # Get the style layout
    s = ttk.Style()
    layout = s.layout("TPanedwindow")
    if debug:
        print(s)
        print(layout)
        print(s.element_options("TPanedwindow.border"))


def on_listboxSelect2(e):
    indx = _w1.Scrolledlistbox1.curselection()
    itm = _w1.Scrolledlistbox1.get(indx[0])
    if debug:
        print(f"Selected Item: {indx[0]} - {itm}")
    _w1.ListDisplay2.set(f"Selected Item: {indx[0]} - {itm}")


# ===================================================
# Code for Special twists Notebook tab
# ===================================================
def LabelLinkClick(*args):
    if debug:
        print("Into LabelLinkClick")
        for arg in args:
            print(arg)
    which = args[0]
    if debug:
        print(which)
    if which == 1:
        url = "https://fullcirclemagazine.org"
    elif which == 2:
        url = "https://sourceforge.net/projects/page/"
    elif which == 3:
        url = "https://thedesignatedgeek.xyz"
    webbrowser.open_new_tab(url)


def on_RepeatButtonReset(e):
    """
    Simply resets the repeat count to 0
    """
    global rcnt
    rcnt = 0
    _w1.RepeatedCount.set(rcnt)


# ===================================================
# Statusbar clock display code
# ===================================================
def on_time_update():

    # ======================================================
    # Callback function for the Time display
    # ======================================================
    global timer_id
    nowstring = f"{datetime.datetime.now():%X}"
    _w1.StatusTime.set(nowstring)
    timer_id = root.after(500, on_time_update)


def build_buttonbar():

    global b, id, label, md_list, original, ImageDir, location
    b = {}
    id = {}
    global original
    original = []
    inner_frame = _w1.Scrolledwindow1_f
    filedef = os.path.join(ImageDir, "*.png")
    md_list = glob.glob(filedef)
    md_list.sort()
    for cntr in range(len(md_list)):
        if os.path.exists(md_list[cntr]):
            img = Image.open(md_list[cntr])
            img.thumbnail((80, 30))
            thumb = img.copy()
            original.append(ImageTk.PhotoImage(thumb))
    for cntr in range(len(md_list)):
        row, col = divmod(cntr, 1)
        b[cntr] = tk.Button(
            inner_frame,
            width=105,
            text=md_list[cntr].replace(ImageDir + "/", ''),
            image=original[cntr],
            compound=TOP,
            wraplength=105,
            activebackground="lawngreen",
        )
        b[cntr].grid(row=cntr * row + 1, column=col, sticky="wesn")
        b[cntr].grid_propagate(0)
        id[b[cntr].winfo_id()] = cntr
        b[cntr].bind("<Button-1>", on_bbarClick)
    b[0].wait_visibility()
    bbox = inner_frame.bbox()
    inner_frame.grid_propagate(0)
    _w1.Scrolledwindow1.configure(scrollregion=bbox)
    _top1.update_idletasks()


def clear_bbar():
    # Attempt to clear images from the button bar list.
    # Only needs to be run if the button bar has been build and
    # that happens once when the user clicks on Tab #2 (third page)
    if debug:
        print('Into Clear BBar')
    if page_2_seen:
        for cntr in range(len(b)):
            img = b[cntr].cget('image')
            if debug:
                print(f'button image {img}')
    if page_2_seen == True:
        md_list.clear()
        if debug:
            print(f'Clearing {len(b)} images')
        for cntr in range(len(b)):
            if debug:
                print(f'Clearing image for button {cntr}')
            b[cntr].config(image='')
            b[cntr].place_forget()
        b.clear()
        id.clear()
        original.clear()


# ===================================================
# Start of Treeview Setup code
# ===================================================
def setup_treeview():
    _w1.Scrolledtreeview1.bind("<<TreeviewSelect>>", lambda e: update_tree(e))
    _w1.Scrolledtreeview1.bind("<<TreeviewOpen>>", lambda e: tree_open(e))
    _w1.Scrolledtreeview1.bind("<<TreeviewClose>>", lambda e: tree_close(e))
    _w1.Scrolledtreeview1.bind("<Button-1>", lambda e: on_TV_Click(e))
    init_tree(_w1.Scrolledtreeview1)


def init_tree(tree):
    global folderimage
    tree["columns"] = ("Recipe", "Recid")
    tree.column("#0", width=40, stretch=tk.NO)
    tree.column("Recipe", width=160, stretch=tk.NO)
    tree.column("Recid", width=100, stretch=tk.NO)
    tree.heading("#0", text="", anchor=tk.W)
    tree.heading("Recipe", text="Recipe", anchor=tk.W)
    tree.heading("Recid", text="Recid", anchor=tk.W)
    node = tree.insert("", 1, text="", image=folderimage)
    populate_tree(tree, node)


def populate_tree(tree, node):
    global first
    cntr = 0
    recs = set_recs()
    for r in recs:
        title = r[1]
        recid = r[0]
        id = tree.insert(node, 2, values=(title, recid))
        if cntr == 0:
            first = id
        cntr += 1
    tree.item(node, open=True)
    tree.focus(first)
    tree.selection_set(first)
    CurrentID = _w1.Scrolledtreeview1.set(first, 1)


def set_recs():
    recs = [
        (1, "Orange Chicken", "Greg", "4", None, 0, 1, None, None),
        (
            2,
            "Baked Beef and Rice",
            "Southern Living Magazine, April, 1974.",
            "6",
            None,
            0,
            1,
            None,
            None,
        ),
        (
            3,
            "101 Garlic Chicken",
            "File ftp://ftp.idiscover.co.uk/pub/food/mealmaster/recipes/garlic.zip",
            "10",
            None,
            0,
            1,
            None,
            None,
        ),
        (4, "Spanish Rice", "Greg's mind", "4", None, 0, 1, None, None),
        (5, "Barbecue Sauce - Indonesian", "Meal master", "16", None, 0, 1,
         None, None),
        (6, "Sauted Chicken", "Greg's mind", "4", None, 0, 1, None, None),
        (
            11,
            "30 minute peach pork saute",
            'Canadian Living magazine, Aug 95 Article "30-Minute Summer Suppers"',
            "4",
            None,
            0,
            1,
            None,
            None,
        ),
        (14, "Fruit For Greg Cookies", "Greg", "20-30", None, 0, 1, None,
         None),
        (18, "Greg's BBQ Sauce", "Greg", "", None, 0, 1, None, None),
        (19, "Nicole's Wonderful White Chili", "web", "4", None, 0, 1, None,
         None),
        (20, "Texas White Chili", "web", "4", None, 0, 1, None, None),
        (21, "Sloppy Joe Seasoning Mix", "Web", "6", None, 0, 1, None, None),
        (22, "Snow Balls in a Jar", "web", "4 dozen", None, 0, 1, None, None),
        (23, "BBQ Cowboy Beans", "web", "6", None, 0, 1, None, None),
        (24, "Lemon Supreme Pie", "Web", "6-8", None, 0, 1, None, None),
        (25, "Pineapple Chiffon Pie", "web", "6-8", None, 0, 1, None, None),
        (26, "Pumpkin Cookies", "Carol", "", None, 0, 1, None, None),
        (
            27,
            "Easy Caribbean Lime Pie",
            "Back of Lime Juice Box",
            "6-8",
            None,
            0,
            1,
            None,
            None,
        ),
        (
            31,
            "Chimichuri Sauce for Steaks",
            "Foodnetwork.com",
            "1 1/2 cups",
            None,
            0,
            1,
            None,
            None,
        ),
        (32, "Boudin Sausage", "Emeril Live", "4 1/2 pounds", None, 0, 1, None,
         None),
        (
            34,
            "Chipotle Cashew Chicken with Brown Rice 2",
            "Rachael Ray",
            "4-6",
            None,
            0,
            1,
            None,
            None,
        ),
        (
            35,
            "Crispy Chicken Cutlets with Basil-Parsley Sauce",
            "Rachael Ray",
            "4",
            None,
            0,
            1,
            None,
            None,
        ),
        (36, "Cheesy Risi e Bisi", "Rachael Ray", "4", None, 0, 1, None, None),
        (37, "Basil- Parsley Sauce", "Rachael Ray", "4", None, 0, 1, None,
         None),
        (
            38,
            "Strip Steak with Pepper Cream Sauce",
            "Alton Brown",
            "4",
            None,
            0,
            1,
            None,
            None,
        ),
        (39, "Sweet and Sour Pork", "Alton Brown", "4-6", None, 0, 1, None,
         None),
        (
            40,
            "Classic Peanut Brittle",
            "karosyrup.com",
            "1 pound",
            None,
            0,
            1,
            None,
            None,
        ),
        (41, "BUTTERY PEANUT BRITTLE", "www.cooks.com", "", None, 0, 1, None,
         None),
        (
            42,
            "Pickled Pepper-Onion Relish",
            "Complete Guide to Home Canning",
            "9 half pints",
            None,
            0,
            1,
            None,
            None,
        ),
        (
            43,
            "Cheesy Beer Fondue",
            "Semi-Homemade Cooking with Sandra Lee",
            "4 servings",
            None,
            0,
            1,
            None,
            None,
        ),
        (44, "Chocolate Caramels", "web", "Yields - 64\\r\\n", None, 0, 1,
         None, None),
        (
            45,
            "B-B-Q Hamburger (Sloppy Joes)",
            "Aunt Jeannette",
            "4",
            None,
            0,
            1,
            None,
            None,
        ),
        (
            46,
            "Blue Ribbon Almond Roca Cookies",
            "Emeril's Holiday Cookie Contest",
            "3 dozen",
            None,
            0,
            1,
            None,
            None,
        ),
        (47, "MILKY WAY Sandies", "web", "Makes 24 cookies.", None, 0, 1, None,
         None),
        (
            48,
            "Moscow Mule recipe",
            "web",
            "Scale ingredients to servings 2 oz vodka",
            None,
            0,
        ),
    ]
    return recs


def update_tree(e):
    if debug:
        print("Update_Tree")


def on_TV_Click(e):
    if debug:
        print("On_TV_Click")
    row = _w1.Scrolledtreeview1.identify_row(e.y)
    col = _w1.Scrolledtreeview1.identify_column(e.x)
    if row == "":
        pass
    elif row == "I001":  # and (col == '#0'):
        pass
    else:
        if debug:
            print(f"Row: {row}  Col: {col}")
        title = _w1.Scrolledtreeview1.set(row, 0)
        CurrentID = _w1.Scrolledtreeview1.set(row, 1)
        if debug:
            print(f"Title: {title} CurrentID: {CurrentID}")
        titl = f"PAGE Widget Demo"
        msg = f"Recipe Title: {title} ID: {CurrentID}"
        messagebox.showinfo(titl, msg, parent=root, icon=messagebox.INFO)


def tree_close(e):
    pass


def tree_open(e):
    print("Tree_open")


# ===================================================
# End of Treeview support code
# ===================================================


# ===================================================
# Statusbar clock display code
# ===================================================
def on_time_update():
    # ======================================================
    # Callback function for the Time display
    # ======================================================
    global timer_id
    nowstring = f"{datetime.datetime.now():%X}"
    _w1.StatusTime.set(nowstring)
    timer_id = root.after(500, on_time_update)


def on_bbarClick(event):
    global md_list, ImageDir
    if debug:
        print('on_btnClick')
    selected = id[event.widget.winfo_id()]
    fn = md_list[selected].replace(ImageDir + "/", '')
    if debug:
        print(fn)

    # Remove extension
    fn2 = fn.rsplit(".", 1)[0]
    _w1.IconName.set(fn2)


def LoadCustom():

    global ListInfo, ListInfo2
    # =======================================================
    # Create the list of text items for the ScrolledCheckBox
    # =======================================================
    ListInfo = [
        "Appetizer",
        "Snack",
        "Barbecue",
        "Cake",
        "Candy",
        "Beverages",
        "Breads",
        "Canning & Freezing",
        "Cookies",
        "Desserts",
        "Meats",
        "Main Dish",
        "Snacks",
        "Rice",
        "Poultry",
        "Sauces",
        "Soups",
        "American",
        "Mexican",
        "Asian",
    ]
    ListInfo2 = [
        ["Appetizer", 1],
        ["Snack", 2],
        ["Barbecue", 3],
        ["Cake", 4],
        ["Candy", 5],
        ["Beverages", 6],
        ["Breads", 7],
        ["Canning & Freezing", 8],
        ["Cookies", 9],
        ["Desserts", 10],
        ["Eggs & Cheese", 11],
        ["Fish & Seafood", 12],
        ["Meats", 13],
        ["Pies", 14],
        ["Poultry", 15],
        ["Rice", 16],
        ["Pasta", 17],
        ["Cereal", 18],
        ["Salads & Dressings", 19],
        ["Sauces", 20],
    ]

    initialize_custom_widget()


def initialize_custom_widget():

    _w1.Custom1.cback = on_Customclick
    # To use a single list of item names comment out the next line and
    # uncomment the second line down.
    _w1.Custom1.load(ListInfo2)
    # w.Custom1.load(ListInfo)
    clear_label()
    set_labels()


def on_btnGetChecks(*args):
    """
    Support callback function to print the checked items for the ScrolledListCheckbox
    custom control
    """
    if debug:
        print("widgetdemo_support.on_btnGetChecks")
        for arg in args:
            print("another arg:", arg)
        sys.stdout.flush()
    lst = _w1.Custom1.get()
    print(lst)


def on_btnClearChecks(*args):
    """
    Support callback function to clear the checks for the ScrolledListCheckbox
    custom control
    """
    if debug:
        print("widgetdemo_support.on_btnClearChecks")
        for arg in args:
            print("another arg:", arg)
        sys.stdout.flush()
    _w1.Custom1.clear()
    clear_label()


def clear_label():
    _w1.CustomWidgetData.set("")


def update_label():
    dat = _w1.Custom1.get()
    lst = []
    for x in dat:
        # print(len(x),x)
        if len(x) == 2:
            t = x[0]
            k = x[1]
            lst.append(t)
        else:
            lst.append(x)
    s = ", ".join(lst)
    # print(f'S-Type: {type(s)} - {s}')
    _w1.CustomWidgetData.set(s)


def set_labels():
    _w1.Custom1.set(["Appetizer", "Candy", "Breads"])
    update_label()


def on_Customclick(s=None):
    # ======================================================
    # On event, scrolled frame returns a list containing:
    #    item number selected
    #    text of checkbox selected
    # ======================================================
    update_label()
    if debug:
        print(_w1.Custom1.get())


# Custom = tk.Frame  # To be updated by user with name of custom widget.
Custom = ScrolledCheckedListBox


def on_RepeatButton(*args):
    if debug:
        print('widgetdemo_support.on_RepeatButton')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    global rcnt
    rcnt += 1
    _w1.RepeatedCount.set(rcnt)


def on_TCheck(*args):
    if debug:
        print('widgetdemo_support.on_TCheck')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    displaylist = ["Off", "On"]
    c1 = _w1.tch47.get()
    c2 = _w1.tch48.get()
    c3 = _w1.tch49.get()
    disp = f"{displaylist[c1]} - {displaylist[c2]} - {displaylist[c3]}"
    _w1.TCheckDisplay.set(disp)


def on_TRadio(*args):
    if debug:
        print('widgetdemo_support.on_TRadio')
        for arg in args:
            print('    another arg:', arg)
        sys.stdout.flush()
    which = _w1.TselectedButton.get()
    _w1.TRadioDisplay.set(f"Option {which} selected")


if __name__ == '__main__':
    widgetdemo.start_up()
