添加菜单

This commit is contained in:
cxykevin 2024-04-07 21:38:42 +08:00
parent bc0f82125c
commit 8046c09321
3 changed files with 291 additions and 0 deletions

Binary file not shown.

265
magictk/submenu.py Normal file
View File

@ -0,0 +1,265 @@
import json
import tkinter
import sys
from tkinter import ttk
from tkinter import font as tkfont
try:
import color_tmpl
except ImportError:
from magictk import color_tmpl
try:
import photoload
except ImportError:
from magictk import photoload
transcolor = "#41342F"
usetrans = sys.platform.startswith('win')
def set_font():
global use_font
font_family = ["Helvetica Neue", "Helvetica", "PingFang SC", "Hiragino Sans GB",
"Microsoft YaHei",
"微软雅黑",
"Arial", "sans-serif"]
t_family = tkfont.families(root=None, displayof=None)
for i in font_family:
if i in t_family:
use_font = i
break
else:
print("Unknown font")
class MenuObjs:
def __init__(self):
self.menu_lst = []
self.menu_func = []
self.menu_effect = []
def first_action(self, menuobj):
pass
def addmenu(self, name, func, effect={}):
self.menu_lst.append(name)
self.menu_func.append(func)
self.menu_effect.append(effect)
class Menu:
__relh = 0
__color_bd = "border_base"
__color_bg = "background"
__color_fg = "primary"
__color_fg1 = "primary_light"
__color_fg2 = "primary_light2"
color = color_tmpl.default_color
__close_mode = 0
__last_highlight = 0
__y_move = 0
___last_move = 1
___last_highlight = 0
ht = 12
lt = 22
ft = 34
def __anim(self, *args):
if (self.__close_mode == 0):
if (self.__relh != self.h):
if (self.h-self.__relh <= 1):
self.__relh = self.h
elif (self.h-self.__relh > 32):
self.__relh += 32
else:
self.__relh += (self.h-self.__relh) >> 1
self.toplevel.geometry(
f"{self.w}x{self.__relh}+{self.x}+{self.y}")
elif self.__close_mode == 1:
if (self.__relh != 0):
if (self.__relh-0 <= 1):
self.toplevel.destroy()
self.__close_mode = 2
return
elif (self.__relh-0 > 32):
self.__relh -= 32
else:
self.__relh -= (self.__relh-0) >> 1
self.toplevel.geometry(
f"{self.w}x{self.__relh}+{self.x}+{self.y}")
else:
return -1
if (self.___last_move != self.__y_move):
n = 0
for i in self.__itemsf:
self.canvas.moveto(i, 24, n*self.ft+self.ht +
self.__y_move+(self.ft-self.font[1]*2.5)//2)
n += 1
n = 0
for i in self.__items:
self.canvas.moveto(i, 2, n*self.ft+self.ht-4 +
self.__y_move)
n += 1
self.___last_move = self.__y_move
n = 0
for i in self.menuobj.menu_effect:
if (len(i) != 0):
self.canvas.itemconfigure(
self.__itemsf[n], justify=tkinter.LEFT, **i)
self.canvas.moveto(self.__itemsf[n], 24, n*self.ft+self.ht +
self.__y_move+(self.ft-self.font[1]*2.5)//2)
else:
self.canvas.itemconfigure(
self.__itemsf[n], justify=tkinter.LEFT, fill=self.color["regular_text"], font=self.font)
self.canvas.moveto(self.__itemsf[n], 24, n*self.ft+self.ht +
self.__y_move+(self.ft-self.font[1]*2.5)//2)
n += 1
def __mouse_move(self, event: tkinter.Event):
y = event.y
self.__last_highlight = max(
-1, min(len(self.__items), int((y-self.ht-self.__y_move)//self.ft)))
if (self.__last_highlight == -1 or self.__last_highlight >= len(self.__items)):
if (self.___last_highlight != -2):
self.canvas.itemconfig(
self.__items[self.___last_highlight], fill=self.color["background"])
self.___last_highlight = -2
elif (self.___last_highlight != self.__last_highlight):
self.canvas.itemconfig(
self.__items[self.__last_highlight], fill=self.color["placeholder_light"])
self.canvas.itemconfig(
self.__items[self.___last_highlight], fill=self.color["background"])
self.___last_highlight = self.__last_highlight
def close(self, *args):
self.__close_mode = 1
if (self.__closecallback is not None):
self.__closecallback(self)
def __init__(self, root, menuobj: MenuObjs, w=200, h=300, x=100, y=300, color_list: None | dict = None, closeonleave=True, fontsize=10, closecallback=None):
set_font()
self.__closecallback = closecallback
self.font = (use_font, fontsize)
self.__items = []
self.__itemsf = []
self.menuobj = menuobj
self.w = w
self.h = h
self.x = x
self.y = y
if (color_list is not None):
self.color = color_list
self.toplevel = tkinter.Toplevel(bg=transcolor)
self.toplevel.wm_attributes('-topmost', True)
self.toplevel.overrideredirect(True)
self.toplevel.geometry(f"{self.w}x{self.__relh}+{self.x}+{self.y}")
if (usetrans):
self.toplevel.wm_attributes('-transparentcolor', transcolor)
self.root = root
self.canvas = tkinter.Canvas(
self.toplevel, bg=self.color["background"], highlightthickness=0, width=self.w+1, height=self.h+1)
self.canvas.place(x=-1, y=-1)
self.root.anim.append(self.__anim)
self.toplevel.focus()
self.__draw_menu()
self.__draws()
if (closeonleave):
self.toplevel.bind("<FocusOut>", self.close)
if (not usetrans):
self.toplevel.bind("<Leave>", self.close)
self.canvas.bind("<Motion>", self.__mouse_move)
self.__bind_scroll()
self.canvas.bind("<ButtonRelease-1>", self.__click)
self.toplevel.bind_all("<Escape>", self.close)
self.toplevel.bind_all("<Return>", self.__click)
def __draw_menu(self):
n = 0
for i in self.menuobj.menu_lst:
self.__items.append(self.canvas.create_rectangle(
2, n*self.ft+self.ht, self.w, (n+1)*self.ft+self.ht, fill=self.color["background"], width=0))
self.__itemsf.append(self.canvas.create_text(
10, n*self.ft+self.ht, text=i, font=self.font, justify=tkinter.LEFT, fill=self.color["regular_text"]))
n += 1
def __draw_corner(self, r_x, r_y, x, y, **kwargs):
border_info = json.loads(photoload.loadres("menuborder"))
y_n = 0
for i in border_info:
x_n = 0
for j in i:
if (r_x == 0):
px = x+x_n+1
else:
px = x+4-x_n-1
if (r_y == 0):
py = y+y_n+1
else:
py = y+4-y_n-1
if (j < 0):
lcolor = -j
else:
lcolor = j
if (lcolor == 255):
x_n += 1
continue
if (j < 0):
if (usetrans):
g_color = transcolor
else:
g_color = self.color["background"]
else:
g_color = color_tmpl.mix_color(
self.color["background"], self.color[self.__color_bd], int((1-lcolor/255)*1000)/1000)
self.canvas.create_rectangle(
px, py, px, py, width=0, fill=g_color)
x_n += 1
y_n += 1
def __draws(self):
self.__draw_corner(0, 0, 0, 0)
self.__draw_corner(1, 0, self.w-4+1, 0)
self.__draw_corner(0, 1, 0, self.h-4+1)
self.__draw_corner(1, 1, self.w-4+1, self.h-4+1)
self.canvas.create_line(
1, 5, 1, self.h-3, width=1, fill=self.color[self.__color_bd])
self.canvas.create_line(
5, 1, self.w-3, 1, width=1, fill=self.color[self.__color_bd])
self.canvas.create_line(
self.w, 5, self.w, self.h-3, width=1, fill=self.color[self.__color_bd])
self.canvas.create_line(
5, self.h, self.w-3, self.h, width=1, fill=self.color[self.__color_bd])
def __bind_scroll(self):
def scrollwheel(event: tkinter.Event, setdelta=None):
if (setdelta is None):
delta = event.delta
else:
delta = setdelta
if sys.platform.startswith('win'):
delta //= 120
if delta > 0:
self.__y_move = min(0, self.__y_move+delta)
else:
self.__y_move = max(
-max(0, len(self.__items)*self.ft+self.ht-self.h), self.__y_move+delta)
if sys.platform.startswith('win'):
self.toplevel.bind_all("<MouseWheel>", scrollwheel)
elif sys.platform.startswith('darwin'):
self.toplevel.bind_all("<MouseWheel>", scrollwheel)
else:
self.toplevel.bind_all(
"<Button-4>", lambda event: scrollwheel(event, 8))
self.toplevel.bind_all(
"<Button-5>", lambda event: scrollwheel(event, -8))
def __click(self, event):
click_item = max(
-1, min(len(self.__items), int((event.y-self.ht-self.__y_move)//self.ft)))
if (click_item == -1 or self.__last_highlight >= len(self.__items)):
return
self.close()
self.menuobj.menu_func[click_item](self, click_item)

View File

@ -0,0 +1,26 @@
[
[
-1,
-1,
64,
14
],
[
-1,
34,
155,
245
],
[
64,
155,
255,
255
],
[
14,
245,
255,
255
]
]