try:
    import tktooltip
except ImportError:
    pass
import tkinter as tk
import tkinter.ttk as ttk
from ctypes import windll, POINTER, Structure, c_bool, sizeof, windll, pointer, c_int
from ctypes.wintypes import DWORD, HWND, ULONG
from enum import Enum
from typing import Literal

from tkdev.devicon import Icon_Empty, Icon_Folder, Icon_Info, Icon_Error, Icon_Warring, Icon_Question, Icon_Questhead, Icon_Hourglass, Icon_QuickFish, Icon_TkinterDev
from tkdev.devresize import DevResize
from tkdev.devnet import WindowEffect
from tkdev.devcore import DevAction, DevSysTray
from tkdev.devdraw import DrawButton
from tkdev.devpre import DevPreToolbox, DevPreTooltip
import warnings

try:
    from deprecated.sphinx import deprecated
except ImportError:
    pass

try:
    from win32gui import *
    from win32con import *
    from win32api import *
    from win32ui import *
    from win32com import *
except ImportError:
    pass
try:
    import darkdetect
except ImportError:
    pass

dwm = windll.dwmapi
SetWindowCompositionAttribute = windll.user32.SetWindowCompositionAttribute
SetWindowCompositionAttribute()
windll.shcore.SetProcessDpiAwareness(1)
ScaleFactor = windll.shcore.GetScaleFactorForDevice(0)

try:
    taskbar_height = GetMonitorInfo(MonitorFromPoint((0, 0))).get("Monitor")[3] - \
                     GetMonitorInfo(MonitorFromPoint((0, 0))).get("Work")[3]
except NameError:
    pass
Auto = "auto"
Light = "light"
Dark = "dark"

DWMWA_USE_IMMERSIVE_DARK_MODE = 20


def UpGrade(Library, Basic=True, Pypi="https://pypi.tuna.tsinghua.edu.cn/simple/"):
    import os
    import sys
    if Basic:
        print(f"{sys.executable} -m pip install {Library}  -i {Pypi} --upgrade")
        os.system(f"{sys.executable} -m pip install {Library}  -i {Pypi} --upgrade")
    else:
        print(f"{sys.executable} -m pip install {Library} --upgrade")
        os.system(f"{sys.executable} -m pip install {Library} --upgrade")


def Install(Library, Basic=True, Pypi="https://pypi.tuna.tsinghua.edu.cn/simple/"):
    import os
    import sys
    if Basic:
        print(f"{sys.executable} -m pip install {Library}  -i {Pypi}")
        os.system(f"{sys.executable} -m pip install {Library}  -i {Pypi}")
    else:
        print(f"{sys.executable} -m pip install {Library}")
        os.system(f"{sys.executable} -m pip install {Library}")


def Install_ALL(Basic=True, Pypi="https://pypi.tuna.tsinghua.edu.cn/simple/"):
    Install("tkinter-tooltip", Basic=Basic, Pypi=Pypi)
    Install("pywin32", Basic=Basic, Pypi=Pypi)
    if sys.platform == "win32" and sys.getwindowsversion().build >= 22000:
        Install("win32mica", Basic=Basic, Pypi=Pypi)
    Install("BlurWindow", Basic=Basic, Pypi=Pypi)
    Install("darkdetect", Basic=Basic, Pypi=Pypi)
    Install("tkcap", Basic=Basic, Pypi=Pypi)
    Install("Deprecated", Basic=Basic, Pypi=Pypi)


def UnInstall(Library):
    import os
    import sys
    if Basic:
        print(f"{sys.executable} -m pip uninstall {Library}")
        os.system(f"{sys.executable} -m pip uninstall {Library} ")


class AccentState(Enum):
    ACCENT_DISABLED = 0,
    ACCENT_ENABLE_GRADIENT = 1,
    ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
    ACCENT_ENABLE_BLURBEHIND = 3,
    ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
    ACCENT_INVALID_STATE = 5,


class WindowComPositionAttribute(Enum):
    WCA_UNDEFINED = 0,
    WCA_NCRENDERING_ENABLED = 1,
    WCA_NCRENDERING_POLICY = 2,
    WCA_TRANSITIONS_FORCEDISABLED = 3,
    WCA_ALLOW_NCPAINT = 4,
    WCA_CAPTION_BUTTON_BOUNDS = 5,
    WCA_NONCLIENT_RTL_LAYOUT = 6,
    WCA_FORCE_ICONIC_REPRESENTATION = 7,
    WCA_EXTENDED_FRAME_BOUNDS = 8,
    WCA_HAS_ICONIC_BITMAP = 9,
    WCA_THEME_ATTRIBUTES = 10,
    WCA_NCRENDERING_EXILED = 11,
    WCA_NCADORNMENTINFO = 12,
    WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
    WCA_VIDEO_OVERLAY_ACTIVE = 14,
    WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
    WCA_DISALLOW_PEEK = 16,
    WCA_CLOAK = 17,
    WCA_CLOAKED = 18,
    WCA_ACCENT_POLICY = 19,
    WCA_FREEZE_REPRESENTATION = 20,
    WCA_EVER_UNCLOAKED = 21,
    WCA_VISUAL_OWNER = 22,
    WCA_LAST = 23


class DwmWindowAttribute(Enum):
    DWMWA_NCRENDERING_ENABLED = 1
    DWMWA_NCRENDERING_POLICY = 2
    DWMWA_TRANSITIONS_FORCEDISABLED = 3
    DWMWA_ALLOW_NCPAINT = 4
    DWMWA_CAPTION_BUTTON_BOUNDS = 5
    DWMWA_NONCLIENT_RTL_LAYOUT = 6
    DWMWA_FORCE_ICONIC_REPRESENTATION = 7
    DWMWA_FLIP3D_POLICY = 8
    DWMWA_EXTENDED_FRAME_BOUNDS = 9
    DWMWA_HAS_ICONIC_BITMAP = 10
    DWMWA_DISALLOW_PEEK = 11
    DWMWA_EXCLUDED_FROM_PEEK = 12
    DWMWA_CLOAK = 13
    DWMWA_CLOAKED = 14
    DWMWA_FREEZE_REPRESENTATION = 15
    DWMWA_PASSIVE_UPDATE_MODE = 16
    DWMWA_USE_HOSTBACKDROPBRUSH = 17
    DWMWA_USE_IMMERSIVE_DARK_MODE = 18
    DWMWA_WINDOW_CORNER_PREFERENCE = 19
    DWMWA_BORDER_COLOR = 20
    DWMWA_CAPTION_COLOR = 21
    DWMWA_TEXT_COLOR = 22
    DWMWA_VISIBLE_FRAME_BORDER_THICKNESS = 23
    DWMWA_LAST = 24


class Accent_Poltcy(Structure):
    """ 设置客户区的具体属性 """
    _fields_ = [
        ('AccentState', DWORD),
        ('AccentFlags', DWORD),
        ('GradientColor', DWORD),
        ('AnimationId', DWORD),
    ]


class WindowComPositionAttributeData(Structure):
    _fields_ = [
        ('Attribute', DWORD),
        ('Data', POINTER(Accent_Poltcy)),  # POINTER()接收任何ctypes类型，并返回一个指针类型
        ('SizeOfData', ULONG),
    ]


def dwm_set_window_attribute(window: tk.Tk, attribute, value):
    dwm.DwmSetWindowAttribute(GetParent(window.winfo_id()), attribute, value)


def window_move(widget: tk.Widget, window: tk.Tk):
    def move(evt):
        ReleaseCapture()
        SendMessage(GetParent(window.winfo_id()), WM_SYSCOMMAND,
                    SC_MOVE + HTCAPTION, 0)

    widget.bind("<B1-Motion>", move)


def window_dark(window: tk.Tk):
    dwm.DwmSetWindowAttribute(GetParent(window.winfo_id()), DWMWA_USE_IMMERSIVE_DARK_MODE, True)


def window_light(window: tk.Tk):
    dwm.DwmSetWindowAttribute(GetParent(window.winfo_id()), DWMWA_USE_IMMERSIVE_DARK_MODE, False)


def window_screenshot(window: tk.Tk, image_name: str = "Image.png"):
    from tkcap import CAP
    cap = CAP(window)
    window.after(800, cap.capture(image_name))
    return cap


def window_acrylic(window: tk.Tk, dark=False, acrylic: bool = False, hexColor: bool = False):
    from BlurWindow.blurWindow import GlobalBlur
    GlobalBlur(GetParent(window.winfo_id()), hexColor=hexColor, Acrylic=acrylic, Dark=dark, QWidget=window)


def window_acrylic2(window: tk.Tk, shadow: bool = True):
    effent = WindowEffect()
    effent.setAcrylicEffect(hWnd=GetParent(window.winfo_id()), isEnableShadow=shadow)


def window_long(window: tk.Tk, long):
    def long():
        hwnd = GetParent(window.winfo_id())
        res = SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~long)

    window.after(1, long)


def window_ex_long(window: tk.Tk, long):
    hwnd = GetParent(window.winfo_id())
    res = SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~long)


def window_tiled(window: tk.Tk):
    hwnd = GetParent(window.winfo_id())
    res = SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_TILED)


def window_alpha(window: tk.Tk, alpha: int):
    hwnd = GetParent(window.winfo_id())
    res = SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SIZEBOX)


def window_mica_light(window: tk.Tk):
    try:
        import win32mica as mc
        mc.debugging = False
    except ImportError:
        pass
    mc.ApplyMica(GetParent(window.winfo_id()), mc.MICAMODE.LIGHT)


def window_mica_dark(window: tk.Tk):
    try:
        import win32mica as mc
        mc.debugging = False
    except ImportError:
        pass
    mc.ApplyMica(GetParent(window.winfo_id()), mc.MICAMODE.DARK)


def window_pos_bottom_right(window: tk.Tk, padx: int = 15, pady: int = 15):
    window.after(1, lambda: window.geometry(
        f"+{window.winfo_screenwidth() - window.winfo_width() - padx - 10}+"
        f"{window.winfo_screenheight() - taskbar_height - window.winfo_height() - pady - 35}"))


def window_pos_bottom_left(window: tk.Tk, padx: int = 15, pady: int = 15):
    window.after(1, lambda: window.geometry(
        f"+{padx}+{window.winfo_screenheight() - taskbar_height - window.winfo_height() - pady - 35}"))


def window_pos_top_right(window: tk.Tk, padx: int = 15, pady: int = 15):
    window.after(1, lambda: window.geometry(
        f"+{window.winfo_screenwidth() - window.winfo_width() - padx - 10}+{pady}"))


def window_pos_top_left(window: tk.Tk, padx: int = 15, pady: int = 15):
    window.after(1, lambda: window.geometry(
        f"+{padx}+{pady}"))


def window_sizebox(window: tk.Tk):
    def sizebox():
        hwnd = GetParent(window.winfo_id())
        res = SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SIZEBOX)

    window.after(1, sizebox)


def window_maxbox(window: tk.Tk):
    def max():
        hwnd = GetParent(window.winfo_id())
        res = SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_MAXIMIZEBOX)

    window.after(1, max)


def window_minbox(window: tk.Tk):
    def min():
        hwnd = GetParent(window.winfo_id())
        res = SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_MINIMIZEBOX)

    window.after(1, min)


def window_grayed_closebox(window: tk.Tk):
    def close():
        hwnd = GetParent(window.winfo_id())
        res = EnableMenuItem(GetSystemMenu(hwnd, False), SC_CLOSE, MF_BYCOMMAND | MF_GRAYED)

    window.after(1, max)


def window_enabled_closebox(window: tk.Tk):
    def close():
        hwnd = GetParent(window.winfo_id())
        res = EnableMenuItem(GetSystemMenu(hwnd, False), SC_CLOSE, MF_BYCOMMAND | MF_ENABLED)

    window.after(1, max)


def window_popup(window: tk.Tk):
    def popup():
        hwnd = GetParent(window.winfo_id())
        res = SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_POPUPWINDOW)

    window.after(1, popup)


def window_custom_taskbar(window: tk.Tk):
    def over():
        hwnd = GetParent(window.winfo_id())
        res = SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_OVERLAPPEDWINDOW)
        SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_DRAWFRAME)

    window.after(1, over)
    window.update()


def window_custom_border_taskbar(window: tk.Tk):
    def custom():
        hwnd = GetParent(window.winfo_id())
        res = SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_BORDER)

    window.after(1, custom)
    window.update()


def window_add_taskbar(window: tk.Tk):
    hwnd = GetParent(window.winfo_id())
    res = SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_TOOLWINDOW | WS_EX_APPWINDOW)
    # re-assert the new window style
    window.wm_withdraw()
    window.after(1, lambda: window.wm_deiconify())


def window_border(window: tk.Tk):
    def border():
        hWnd = GetParent(window.winfo_id())
        SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) & ~WS_CAPTION)
        SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_DRAWFRAME)
        UpdateWindow(hWnd)
    window.after(100, border)

def window_embed(window: tk.Tk, toplevel: tk.Toplevel, iswindow: bool = True):
    def embed():
        SetParent(GetParent(toplevel.winfo_id()), window.winfo_id())
        toplevel.deiconify()
        if iswindow:
            window.attributes("-topmost", False)

    if iswindow:
        window.attributes("-topmost", True)
    window.after(1, embed)


def window_centre(window: tk.Tk):
    x = window.winfo_screenwidth() / 2 - window.winfo_width() / 2
    y = window.winfo_screenheight() / 2 - window.winfo_height() / 2
    window.geometry(f"{window.winfo_width()}x{window.winfo_height()}+{round(x)}+{round(y)}")


def window_custom(window: tk.Tk):
    hwnd = GetParent(window.winfo_id())
    res = SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_CAPTION)
    window.update()


def resize_widget(widget: tk.Widget, size: int = 10):
    try:
        widget.after(1, lambda: DevResize(widget, size=size))
    except tk.TclError:
        pass


class DevAccumulatorButton(tk.Button):
    def __init__(self):
        super(DevAccumulatorButton, self).__init__()
        pass


class DevAppBar(tk.Frame):
    def __init__(self, master: tk.Widget = None, title: str = "", background="#ffffff", foreground="#000000"):
        super(DevAppBar, self).__init__(master=master, relief=tk.FLAT, background=background)
        self.title = tk.Label(self, text=title, justify=tk.LEFT, background=background, foreground=foreground)
        self.title.pack(fill=tk.Y, side=tk.LEFT, padx=10, pady=5)

    def show(self):
        self.pack(fill=tk.X, ipadx=10, ipady=10)


class DevButton(tk.Button):
    def __init__(self, master, text: str = "", borderwidth: int = 0, image=None, font=("等线 Light", 10, "bold"),
                 command=None,
                 default_bg="#ffffff", default_fg="#000000",
                 active_bg="#177aff", active_fg="#d6eaff",
                 click_bg="#175bff", click_fg="#d6deff"):
        super(DevButton, self).__init__(master=master, relief=tk.FLAT, text=text, font=float, command=command,
                                        borderwidth=borderwidth, image=image,
                                        background=default_bg, foreground=default_fg)
        self.default_bg = default_bg
        self.default_fg = default_fg
        self.active_bg = active_bg
        self.active_fg = active_fg
        self.click_bg = click_bg
        self.click_fg = click_fg
        self.bind("<Leave>", self.nofocus)
        self.bind("<Enter>", self.focus)
        self.bind("<Button-1>", self.click)

    def nofocus(self, event=None):
        self.configure(background=self.default_bg, foreground=self.default_fg)

    def focus(self, event=None):
        self.configure(background=self.active_bg, foreground=self.active_fg)

    def click(self, event=None):
        self.configure(activebackground=self.click_bg, activeforeground=self.click_fg)


class DevDrag(object):
    def __init__(self, widget: tk.Widget, dragwidget: tk.Widget, iswindow: bool = False, x: bool = True, y: bool = True,
                 click_func=None, noclick_func=None, move_func=None):
        """
        这个组件能够拖动组件移动，实现更高级的功能 \n widget设为拖动命令的组件，你拖动这个组件，拖动的组件会移动 \n dragwidget设为被拖动的组件 \n
        iswindow是声明你要拖动的组件是窗口还是组件，是窗口填True，是组件填False

        :param widget:
        :param dragwidget:
        :param iswindow:
        """
        self.widget = widget
        self.dragwidget = dragwidget
        self.iswindow = iswindow
        self.movex = tk.IntVar(self.widget, value=0)
        self.movey = tk.IntVar(self.widget, value=0)
        self.moved = tk.BooleanVar(self.widget, value=False)
        if click_func is None:
            self.widget.bind("<Button-1>", self.click)
        else:
            self.widget.bind("<Button-1>", click_func)
        if noclick_func is None:
            self.widget.bind("<ButtonRelease-1>", self.noclick)
        else:
            self.widget.bind("<ButtonRelease-1>", noclick_func)
        if move_func is None:
            self.widget.bind("<B1-Motion>", self.move)
        else:
            self.widget.bind("<B1-Motion>", move_func)
        self.x = x
        self.y = y

    def move(self, event=None):
        if not self.moved.get():
            return

        if self.x:
            newx = self.dragwidget.winfo_x() + (event.x - self.movex.get())
        else:
            newx = self.dragwidget.winfo_x()

        if self.y:
            newy = self.dragwidget.winfo_y() + (event.y - self.movey.get())
        else:
            newy = self.dragwidget.winfo_y()
        geometry = f"{self.dragwidget.winfo_width()}x{self.dragwidget.winfo_height()}+{newx}+{newy}"
        if self.iswindow:
            self.dragwidget.geometry(geometry)
        else:
            self.dragwidget.place(x=newx, y=newy, width=self.dragwidget.winfo_width(),
                                  height=self.dragwidget.winfo_height())
        self.widget.update()

    def click(self, event=None):
        self.movex.set(event.x)
        self.movey.set(event.y)
        self.moved.set(True)

    def noclick(self, event=None):
        self.moved.set(False)


class DevDocs(tk.PanedWindow):
    def __init__(self, master: tk.Widget):
        super(DevDocs, self).__init__(master=master, orient=tk.HORIZONTAL, height=3)
        self.docsvar = tk.StringVar()
        self.docslist_area = tk.Frame(self)
        self.docslist = tk.Listbox(self.docslist_area, listvariable=self.docsvar)
        self.docslist.bind("<<ListboxSelect>>", self.check)
        self.docslist.pack(fill=tk.BOTH, expand=tk.YES)
        self.docscheck = {}
        self.docstext_area = tk.Frame(self)
        self.docstext = tk.Text(self.docstext_area)
        self.docstext.pack(fill=tk.BOTH, expand=tk.YES)

        self.add(self.docslist_area)
        self.add(self.docstext_area)

    def check(self, event=None):
        self.docstext.delete("0.0", tk.END)
        list = self.docslist.curselection()
        self.docstext.insert("0.0", self.docscheck[list])

    def add_docs(self, list_name: str = "", docs_text: str = ""):
        self.docslist.insert(tk.END, list_name)
        self.docscheck[list_name] = docs_text


class DevExtend(tk.Frame):
    def __init__(self, master: tk.Widget, label: tk.Widget = tk.Label, text: str = "", widget: tk.Widget = tk.Message):
        super(DevExtend, self).__init__(master=master)
        self.label = label
        self.text = text
        self.widget = widget

        self.label.pack(fill=tk.X, side=tk.TOP)
        self.extend_area = tk.Frame()
        self.extend_area.pack(fill=tk.BOTH, expand=tk.YES)


class DevFoldFrame(tk.Frame):
    def __init__(self):
        super(DevFoldFrame, self).__init__()


class DevHeaderBar(tk.Frame):
    def __init__(self, master: tk.Tk, border: bool = True, background="#ffffff", double_max: bool = True):
        super(DevHeaderBar, self).__init__(master=master, background=background, height=35)
        self.master = master
        self.master.configure(background="#fdfdfd")
        self.hWnd = GetParent(self.master.winfo_id())
        if border:
            window_border(self.master)
        elif not border:
            window_custom_taskbar(self.master)
        window_move(self, self.master)
        self.ismaximize = False
        if double_max:
            self.bind("<Double-Button-1>", lambda evt: self.maximize())

    def add_close_button(self, text: str = "🗙", font=("微软雅黑", 9),
                         background="#ffffff", foreground="#000000",
                         activebackground="#c42b1c", activeforeground="#ffffff"):
        self.close_button = tk.Button(self, text=text, border=0, font=font,
                                      background=background, foreground=foreground,
                                      activebackground=activebackground, activeforeground=activeforeground,
                                      command=lambda: self.master.destroy())
        self.close_button.pack(side=tk.RIGHT, ipady=1, ipadx=10, fill=tk.Y)

    def add_maximize_button(self, text: str = "🗖", font=("微软雅黑", 9),
                            background="#ffffff", foreground="#000000",
                            activebackground="#e9e9e9", activeforeground="#b5b5b5"):
        self.maxmize_button = tk.Button(self, text=text, border=0, font=font,
                                        background=background, foreground=foreground,
                                        activebackground=activebackground, activeforeground=activeforeground,
                                        command=self.maximize_event)
        self.maxmize_button.pack(side=tk.RIGHT, ipady=2, ipadx=12, fill=tk.Y)

    def add_minimize_button(self, text: str = "🗕", font=("微软雅黑", 9),
                            background="#ffffff", foreground="#000000",
                            activebackground="#e9e9e9", activeforeground="#b5b5b5"):
        self.minimize_button = tk.Button(self, text=text, border=0, font=font,
                                         background=background, foreground=foreground,
                                         activebackground=activebackground, activeforeground=activeforeground,
                                         command=self.minimize)
        self.minimize_button.pack(side=tk.RIGHT, ipady=2, ipadx=12, fill=tk.Y)

    def maximize_event(self):
        if self.ismaximize:
            self.master.state("normal")
            self.maxmize_button.configure(text="🗖")
            self.ismaximize = False
        elif not self.ismaximize:
            self.master.state("zoomed")
            self.maxmize_button.configure(text="🗗")
            self.ismaximize = True

    def minimize(self):
        self.master.state('icon')

    def maximize(self):
        if self.ismaximize:
            self.master.state("normal")
            self.ismaximize = False
        elif not self.ismaximize:
            self.master.state("zoomed")
            self.ismaximize = True


class DevImage(tk.Label):
    def __init__(self, master: tk.Widget, image: tk.PhotoImage = None, ):
        super(DevImage, self).__init__(master=master, image=image)


class DevMenu(tk.Menubutton):
    def __init__(self, master=None, menu: tk.Menu = None, text: str = "", bg="#fafafa", fg="#000000",
                 active_bg="#3c7bfc", active_fg="#ffffff"):
        super(DevMenu, self).__init__(master=master, menu=menu, text=text, relief=tk.FLAT, background=bg, foreground=fg,
                                      activebackground=active_bg, activeforeground=active_fg)


class DevMenuBar(tk.Frame):
    def __init__(self, master: tk.Widget, bg="#fafafa"):
        super(DevMenuBar, self).__init__(master=master, background=bg)

    def add_menu(self, menu: DevMenu, side=tk.LEFT):
        menu.pack(side=side)

    def show(self):
        self.pack(fill=tk.X, side=tk.TOP)


class DevObject(object):
    def __init__(self):
        self.obj = {}

    def add_widget(self, widget: tk.Widget, id: str):
        self.obj[id] = widget

    def set_widget(self, id: str, widget: tk.Widget):
        self.obj[id] = widget

    def get_widget(self, id: str) -> tk.Widget:
        return self.obj[id]


class DevPopupWindow(tk.Toplevel):
    def __init__(self, master, widget: tk.Widget):
        """
        这个组件有些不稳定，还在研发当中，请谨慎使用

        :param master:
        :param wiget:
        """
        super(DevPopupWindow, self).__init__(master=master)
        self.overrideredirect(True)
        self.withdraw()
        widget.bind("<Button-1>", lambda event: self.popup(widget.winfo_x() + widget.winfo_width(),
                                                           widget.winfo_y() + widget.winfo_height()))
        self.bind("<Button-3>", lambda event: self.withdraw())

    def popup(self, x=0, y=0):
        self.deiconify()
        self.geometry(f"+{x}+{y}")


class DevBorder(object):
    def __init__(self, widget: tk.Widget = None, iswindow: bool = True, border_color="#e1e1e1"):
        self.widget = widget
        self.iswindow = iswindow
        self.top = tk.Frame(widget, height=0, cursor="sb_v_double_arrow", background=border_color)
        self.top.pack(side=tk.TOP, ipady=1, fill=tk.X)
        self.bottom = tk.Frame(widget, height=0, cursor="sb_v_double_arrow", background=border_color)
        self.bottom.pack(side=tk.BOTTOM, ipady=1, fill=tk.X)
        self.left = tk.Frame(widget, height=0, cursor="sb_h_double_arrow", background=border_color)
        self.left.pack(side=tk.LEFT, ipadx=1, fill=tk.Y)
        self.right = tk.Frame(widget, height=0, cursor="sb_h_double_arrow", background=border_color)
        self.right.pack(side=tk.RIGHT, ipadx=1, fill=tk.Y)

    def top_click(self, evt=None):
        self._topx = self.top.winfo_x()
        self._topy = self.top.winfo_y()
        self._widgetx = self.widget.winfo_x()
        self._widgety = self.widget.winfo_y()
        self._widgetrootx = self.widget.winfo_rootx()
        self._widgetrooty = self.widget.winfo_rooty()

    def top_move(self, evt=None):
        widgetx = 0
        if self.iswindow:
            self.widget.geometry(f"")

    def bottom_move(self, evt=None):
        if self.iswindow:
            self.widget.geometry(f"{self.widget.winfo_width()}x{self.bottom.winfo_y()}")


class DevStack(tk.Frame):
    def __init__(self):
        super(DevStack, self).__init__()
        self._pages = {}

    def add_page(self, page: tk.Widget, id: int = 0):
        self._pages[id] = page

    def show_page(self, id: int):
        self._pages[id].pack(fill=tk.BOTH, expand=tk.YES)
        for item in self._pages.keys():
            if not item == id:
                self.hide_page(item)
                print("Hide" + str(item))
            else:
                print("Show" + str(item))

    def hide_page(self, id: int):
        self._pages[id].pack_forget()

    def get_pages(self):
        return self._pages


class DevSideBar(tk.Frame):
    def __init__(self, master: tk.Widget, background="#ffffff", ):
        super(DevSideBar, self).__init__(master=master, background=background)

    def add_action(self, text: str = "", icon: str = None, commnad=None,
                   default_bg: str = "#ffffff", default_fg: str = "#000000",
                   font=("等线 Light", 10, "bold"), side=tk.TOP,
                   active_bg: str = "#177aff", active_fg: str = "#d6eaff",
                   click_bg: str = "#175bff", click_fg: str = "#d6deff"):
        if icon is None:
            button_icon = None
        else:
            button_icon = tk.PhotoImage(file=icon)
        return DevButton(self, text=text, image=button_icon, command=commnad,
                         default_bg=default_bg, default_fg=default_fg, font=font,
                         active_bg=active_bg, active_fg=active_fg,
                         click_bg=click_bg, click_fg=click_fg).pack(side=side)

    def show(self, side: str = tk.LEFT):
        self.pack(side=side, fill=tk.Y)


class DevStatusBar(tk.Frame):
    def __init__(self, master: tk.Widget = None, default_text: str = "", sizegrip: bool = True, background="#fcfcfc",
                 foreground="#000000"):
        """
        简单的状态栏，使用show可以将它显示出来，使用add_status在鼠标指针移动到组件上时，状态栏会显示状态文本。

        :param master:
        :param default_text:
        :param background
        """
        super(DevStatusBar, self).__init__(master=master, background=background, )
        self.widgetlist = []
        self.master = master
        self.default_text = default_text
        self.style = ttk.Style()
        self.style.configure("Dev.TSizegrip", background=background, foreground=foreground)
        self.status = tk.Label(self, text=default_text, background=background, foreground=foreground)
        self.status.pack(side=tk.LEFT, expand=tk.NO)
        self.sizegrip = ttk.Sizegrip(self, style="Dev.TSizegrip")
        if sizegrip:
            self.sizegrip.pack(side=tk.RIGHT, anchor=tk.SE, expand=tk.NO)

    def add_status(self, widget: tk.Widget, status: str = ""):
        self.widgetlist.append(widget)
        widget.bind("<Enter>", lambda event: self.status.configure(text=status))
        widget.bind("<Leave>", lambda event: self.status.configure(text=self.default_text))

    def set_sizegrip(self, sizegrip: ttk.Sizegrip):
        self.sizegrip = sizegrip

    def show(self):
        self.pack(fill=tk.X, side=tk.BOTTOM)


class DevSubWindow(tk.Frame):
    def __init__(self, master, title_label: str = "Title", background="white", resize_size: int = 10,
                 button_side=tk.RIGHT,
                 titlebar_background="white",
                 close: bool = True, max: bool = True, min: bool = True, title: bool = True,
                 title_bg="#ffffff", title_fg="#000000",
                 close_bg="#ffffff", max_bg="#ffffff", min_bg="#ffffff", close_func=None,
                 close_active_bg="#e81123", close_active_fg="#f5f5f5", max_active_bg="#c2c2c2", max_active_fg="#ffffff",
                 min_active_bg="#c2c2c2", min_active_fg="#ffffff",
                 close_fg="#000000", max_fg="#000000", min_fg="#000000"):
        """
        实现了子窗口的功能，在tkinter中没有子窗口，我终于研究成功了。他是个框架，你可以将他使用pack、place进行显示

        :param master:
        :param title:
        :param background:
        :param titlebar_background:
        :param titlebar_foreground:
        """
        super(DevSubWindow, self).__init__(master=master, background=background, borderwidth=1, relief=tk.RIDGE)
        self.titlebar = DevTitleBar(master=self, iswindow=False, widget=self, button_side=button_side,
                                    background=titlebar_background,
                                    close=close, max=max, min=min, title=title, title_label=title_label,
                                    title_bg=title_bg, title_fg=title_fg,
                                    close_bg=close_bg, max_bg=max_bg, min_bg=min_bg, close_func=None,
                                    close_active_bg=close_active_bg, close_active_fg=close_active_fg,
                                    max_active_bg=max_active_bg,
                                    max_active_fg=max_active_fg, min_active_bg=min_active_bg,
                                    min_active_fg=min_active_fg,
                                    close_fg=close_fg, max_fg=max_fg, min_fg=min_fg)
        self.titlebar.pack(fill=tk.X, side=tk.TOP)
        self.bind("Configure", DevResize)
        resize_widget(self, size=resize_size)
        self.update()

    def set_titlebar(self, titlebar):
        self.titlebar = titlebar

    def show(self):
        self.place(x=0, y=0, width=300, height=300)


try:
    class DevToolTip(tktooltip.ToolTip):
        def __init__(self, widget: tk.Widget,
                     msg: str = "",
                     delay: float = 1.0,
                     follow: bool = True,
                     refresh: float = 1.0,
                     x_offset: int = +10,
                     y_offset: int = +10,
                     parent_kwargs: dict = {"bg": "black", "padx": 1, "pady": 1},
                     foreground: str = "#ffffff", background="#1c1c1c",
                     **message_kwargs):
            """
            本人比较懒，不想写，就用了tkinter-tooltip组件，请不要喷我

            :param widget:
            :param msg:
            :param delay:
            :param follow:
            :param refresh:
            :param x_offset:
            :param y_offset:
            :param parent_kwargs:
            :param foreground:
            :param background:
            :param message_kwargs:
            """
            super(DevToolTip, self).__init__(widget=widget, msg=msg, delay=delay, follow=follow, refresh=refresh,
                                             x_offset=x_offset, y_offset=y_offset, parent_kwargs=parent_kwargs,
                                             fg=foreground, bg=background)
except NameError:
    pass


class DevToast(tk.Toplevel):
    def __init__(self, master: tk.Tk = None,
                 title: str = "Title", message: str = "Message", height: int = 80):
        super(DevToast, self).__init__(master=master)
        self.overrideredirect(True)
        self.title = tk.Label(self, text=title, justify=tk.LEFT, anchor=tk.W)
        self.title.pack(side=tk.TOP, fill=tk.X)
        self.message = tk.Label(self, text=message, justify=tk.LEFT, anchor=tk.W)
        self.message.pack(side=tk.TOP, fill=tk.X)
        self.height = height
        self.withdraw()

    def show_toast(self):
        window_pos_bottom_right(self)
        self.deiconify()
        self.after(5000, self.withdraw)


class DevTabber(tk.Frame):
    def __init__(self, master: tk.Widget):
        super(DevTabber, self).__init__(master=master)
        self.actions = {}
        self.actions_button = {}

    def add_action(self, name: str, action: DevAction, use_ttk: bool = False) -> tk.Widget:
        self.actions[name] = action
        if use_ttk:
            self.actions_button[name] = ttk.Button(self, text=action.text, image=action.icon, command=action.command)
        else:
            self.actions_button[name] = tk.Button(self, text=action.text, image=action.icon,
                                                  background=action.background, foreground=action.foreground,
                                                  activebackground=action.active_background,
                                                  activeforeground=action.active_foreground,
                                                  command=action.command)
        return self.actions_button[name]

    def show(self):
        self.pack(fill=tk.X, side=tk.BOTTOM)

    def remove_action(self, name: str):
        self.actions_button[name].forget()

    def get_action(self, name: str):
        return self.actions[name]

    def get_action_button(self, name: str):
        return self.actions_button[name]


class DevWindow(tk.Tk):
    def __init__(self, title: str = ""):
        super(DevWindow, self).__init__()
        from sys import getwindowsversion
        self.title(title)
        self.geometry("630x300")
        self.iconbitmap(Icon_Empty)
        self.configure(background="#ffffff")
        if getwindowsversion().build >= 22621:
            # 因为22621版本号改了标题栏，所以就改成标题栏的颜色
            self.configure(background="#eff4f9")

    def wm_screenshot(self, image="Image.png"):
        window_screenshot(self, image)

    screenshot = wm_screenshot

    def wm_acrylic(self, mode: Literal["auto", "light", "dark"] = Auto,
                   mica: bool = False, acrylic: bool = False, hexColor: bool = False):
        if mica:
            self.mica(mode)

        if mode == "auto":
            if darkdetect.isLight():
                window_acrylic(self, dark=False, acrylic=acrylic, hexColor=hexColor)
                self.configure(background="#eff4f9")
            if darkdetect.isDark():
                window_acrylic(self, dark=True, acrylic=acrylic, hexColor=hexColor)
                self.configure(background="#000000")
        elif mode == "light":
            window_acrylic(self, dark=False, acrylic=acrylic, hexColor=hexColor)
            self.configure(background="#eff4f9")
        elif mode == "dark":
            window_acrylic(self, dark=True, acrylic=acrylic, hexColor=hexColor)
            self.configure(background="#000000")
        self.update()

    acrylic = wm_acrylic

    def wm_mica(self, mode: Literal["auto", "light", "dark"] = Auto, all: bool = False):
        import platform
        if platform.system() == "Windows":
            if all:
                self.configure(background=self.cget("background"))
                self.attributes("-transparent", self.cget("background"))
                self.update()
            if mode == "auto":
                if darkdetect.isLight():
                    window_mica_light(self)
                    self.configure(background="#d3d3d3")
                if darkdetect.isDark():
                    window_mica_dark(self)
                    self.configure(background="#000000")
            elif mode == "light":
                window_mica_light(self)
                self.configure(background="#d3d3d3")
            elif mode == "dark":
                window_mica_dark(self)
                self.configure(background="#000000")
        self.update()

    mica = wm_mica

    def wm_remove_titlebar(self):
        self.after(0, lambda: window_custom_border_taskbar(self))

    remove_titlebar = wm_remove_titlebar

    def wm_remove_titlebar_none_border(self):
        window_custom_taskbar(self)

    remove_titlebar_none_border = wm_remove_titlebar_none_border

    def wm_run(self):
        self.mainloop()

    run = wm_run

    def wm_statusbar(self, statusBar: tk.Widget = None):
        self._statusBar = statusBar
        self._statusBar.pack(fill=tk.X, side=tk.BOTTOM)
        return self._statusBar

    statusbar = wm_statusbar

    def wm_titlebar(self, titleBar: DevHeaderBar = None, overtitlebar: bool = True, border: bool = True):
        self.minsize(100, 30)
        self._titlebar = titleBar
        self._titlebar.pack(fill=tk.X, side=tk.TOP)
        return self._titlebar

    titlebar = wm_titlebar

    def wm_menubar(self, menubar: DevMenuBar = None):
        menubar.show()

    menubar = wm_menubar

    def wm_centre(self):
        self.after(1, lambda evt=None: window_centre(self))

    centre = wm_centre

    def min_window(self):
        self.state("iconic")

    def dpi(self):
        self.tk.call('tk', 'scaling', ScaleFactor / 75)


class DevToplevel(tk.Toplevel, DevWindow):
    def __init__(self, master: tk.Tk = None, title: str = ""):
        super(DevToplevel, self).__init__(master=master)
        self.title(title)
        self.geometry("630x300")
        self.iconbitmap(Icon_Empty)


if __name__ == '__main__':
    Window = DevWindow()
    ToolTip = DevPreTooltip(Window, Window)
    Window.mainloop()