feat: update widget

This commit is contained in:
shenjack 2023-01-01 17:58:40 +08:00
parent 43828b97d8
commit 0a14f4a44d
2 changed files with 242 additions and 220 deletions

View File

@ -11,45 +11,47 @@ github: @shenjackyuanjie
gitee: @shenjackyuanjie gitee: @shenjackyuanjie
""" """
from typing import Optional, Union, Tuple
# from libs import pyglet # from libs import pyglet
from pyglet import font from pyglet import font
from pyglet.text import Label, HTMLLabel from pyglet.text import Label, HTMLLabel
from pyglet.window import key # from pyglet.window import key
from pyglet.gui import widgets from pyglet.gui import widgets
from pyglet.sprite import Sprite # from pyglet.sprite import Sprite
from pyglet.shapes import Rectangle from pyglet.shapes import Rectangle
from pyglet.image import AbstractImage # from pyglet.image import AbstractImage
from pyglet.graphics import Batch, Group from pyglet.graphics import Batch, Group
from pyglet.text.document import FormattedDocument from pyglet.text.document import FormattedDocument
from pyglet.text.layout import IncrementalTextLayout from pyglet.text.layout import IncrementalTextLayout
# from libs import pyperclip # from libs import pyperclip
from libs.pyperclip import paste # from libs.pyperclip import paste
from Difficult_Rocket.utils import translate from Difficult_Rocket.utils import translate
from Difficult_Rocket.client.guis.format import html from Difficult_Rocket.client.guis.format import html
from Difficult_Rocket import DR_option from Difficult_Rocket import DR_option
__all__ = ['Parts', 'InputBox'] __all__ = ['InputBox']
class Parts(widgets.WidgetBase): # class Parts(widgets.WidgetBase):
""" # """
parts # parts
""" # """
#
def __init__(self, # def __init__(self,
x: int, # x: int,
y: int, # y: int,
width: int, # width: int,
height: int, # height: int,
textures: AbstractImage, # textures: AbstractImage,
# textures, # # textures,
batch: Batch, # batch: Batch,
parts_data: dict): # parts_data: dict):
super().__init__(x, y, width, height) # super().__init__(x, y, width, height)
self.sprite = Sprite(img=textures, x=x, y=y, batch=batch) # self.sprite = Sprite(img=textures, x=x, y=y, batch=batch)
self._value = 0 # self._value = 0
class TextButton(widgets.WidgetBase): class TextButton(widgets.WidgetBase):
@ -60,10 +62,11 @@ class TextButton(widgets.WidgetBase):
def __init__(self, def __init__(self,
x: int, y: int, width: int, height: int, x: int, y: int, width: int, height: int,
text: str, text: str,
font: str): font: str = translate.鸿蒙简体, font_size: int = 13):
super().__init__(x, y, width, height) super().__init__(x, y, width, height)
self.text = text self.text = text
self.text_label = Label() self.text_label = Label(
font_name=font, font_size=font_size)
@property @property
def value(self): def value(self):
@ -76,200 +79,209 @@ class TextButton(widgets.WidgetBase):
if not DR_option.InputBox_use_TextEntry: if not DR_option.InputBox_use_TextEntry:
class InputBox(widgets.WidgetBase): class InputBox(widgets.WidgetBase):
""" """ 自定义的输入框 """
input box
"""
def __init__(self, def __init__(self, x: int, y: int, width: int,
x: int, y: int, width: int, height: int, message: str,
message: str = '', batch: Optional[Batch], group: Optional[Group]):
font_name: str = translate.微软等宽,
font_size: int = 15,
font_bold: bool = False,
font_italic: bool = False,
font_stretch: bool = False,
font_dpi: int = 100,
text_color: [int, int, int] = (187, 187, 187, 255),
out_line_color: [int, int, int] = (37, 116, 176),
cursor_color: [int, int, int] = (187, 187, 187),
select_color: [int, int, int] = (63, 115, 255),
out_line: int = 2,
batch: Batch = None,
group: Group = None):
if batch is None:
batch = Batch()
if group is None:
group = Group()
super().__init__(x, y, width, height)
self.enabled = False
self._text = message
self._cursor_poi = 0
self.font = font.load(name=font_name, size=font_size,
bold=font_bold, italic=font_italic, stretch=font_stretch,
dpi=font_dpi)
self.font_height = self.font.ascent - self.font.descent
self.out_bound = out_line
if DR_option.InputBox_use_TextEntry:
# 基于IncrementalTextLayout的处理系统
self._doc = FormattedDocument(message)
# self._doc.set_style()
self._layout = IncrementalTextLayout(self._doc, self.font, width, height,
batch=batch, group=group)
self._input_box = widgets.TextEntry(x, y, width, height,
self._doc, self._layout,
batch=batch, group=group)
else:
# 基于Label的处理系统
self._input_box = Label(x=x + out_line, y=y + out_line,
width=width, height=self.font_height + self.out_bound * 2,
color=text_color,
font_name=font_name, font_size=font_size,
batch=batch, group=group,
text=message)
self._HTML_box = HTMLLabel(x=x + out_line, y=y + out_line + 30,
width=width, height=self.font_height + self.out_bound * 2,
batch=batch, group=group,
text=message)
self._out_box = Rectangle(x=x - out_line, y=y - out_line,
color=out_line_color,
width=width + (out_line * 2), height=height + (out_line * 2),
batch=batch, group=group)
self._光标 = Rectangle(x=x + out_line, y=y + out_line,
color=cursor_color,
width=1, height=self.font_height,
batch=batch, group=group)
self._选择框 = Rectangle(x=x, y=y, width=0, height=self.font_height,
color=select_color)
self._选择的字 = Label(x=x, y=y, width=0, height=self.font_height,
color=text_color,
font_name=font_name, font_size=font_size,
batch=batch, group=group,
text='')
""" super().__init__(x=x, y=y, width=width)
输入框的属性 ...
""" # class InputBox(widgets.WidgetBase):
# """
# 本身属性 # input box
@property # """
def text(self) -> str: # 输入框的文本 #
return self._text # def __init__(self,
# x: int, y: int, width: int, height: int,
@text.setter # message: str = '',
def text(self, value) -> None: # font_name: str = translate.微软等宽,
assert type(value) is str, 'Input Box\'s text must be string!' # font_size: int = 15,
self._text = value # font_bold: bool = False,
self._input_box.text = value # font_italic: bool = False,
self._HTML_box.text = html.decode_text2HTML(value, show_style=True) # font_stretch: bool = False,
# font_dpi: int = 100,
@property # text_color: [int, int, int] = (187, 187, 187, 255),
def cursor_poi(self) -> int: # 光标位置 # out_line_color: [int, int, int] = (37, 116, 176),
return self._cursor_poi # cursor_color: [int, int, int] = (187, 187, 187),
# select_color: [int, int, int] = (63, 115, 255),
@cursor_poi.setter # out_line: int = 2,
def cursor_poi(self, value) -> None: # batch: Batch = None,
assert type(value) is int, 'Input Box\'s cursor poi must be int!' # group: Group = None):
self._cursor_poi = value # if batch is None:
self._光标.x = self.x + self.out_bound + self._input_box.content_width # batch = Batch()
# if group is None:
# 渲染时属性 # group = Group()
@property # super().__init__(x, y, width, height)
def opacity(self) -> int: # 透明度 # self.enabled = False
return self._input_box.opacity # self._text = message
# self._cursor_poi = 0
@opacity.setter # self.font = font.load(name=font_name, size=font_size,
def opacity(self, value: int) -> None: # bold=font_bold, italic=font_italic, stretch=font_stretch,
assert type(value) is int, 'Input Box\'s opacity must be int!' # dpi=font_dpi)
self._input_box.opacity = value # self.font_height = self.font.ascent - self.font.descent
self._out_box.opacity = value # self.out_bound = out_line
self._选择的字.opacity = value # if DR_option.InputBox_use_TextEntry:
self._选择框.opacity = value # # 基于IncrementalTextLayout的处理系统
self._光标.opacity = value # self._doc = FormattedDocument(message)
# # self._doc.set_style()
@property # self._layout = IncrementalTextLayout(self._doc, self.font, width, height,
def visible(self) -> bool: # 是否可见 # batch=batch, group=group)
return self._input_box.visible # self._input_box = widgets.TextEntry(x, y, width, height,
# self._doc, self._layout,
@visible.setter # batch=batch, group=group)
def visible(self, value: bool) -> None: # else:
assert type(value) is bool, 'Input Box\'s visible must be bool!' # # 基于Label的处理系统
self._input_box.visible = value # self._input_box = Label(x=x + out_line, y=y + out_line,
self._out_box.visible = value # width=width, height=self.font_height + self.out_bound * 2,
self._选择的字.visible = value # color=text_color,
self._选择框.visible = value # font_name=font_name, font_size=font_size,
self._光标.visible = value # batch=batch, group=group,
# text=message)
@property # self._HTML_box = HTMLLabel(x=x + out_line, y=y + out_line + 30,
def value(self) -> str: # width=width, height=self.font_height + self.out_bound * 2,
return self._text # batch=batch, group=group,
# text=message)
""" # self._out_box = Rectangle(x=x - out_line, y=y - out_line,
事件调用 # color=out_line_color,
""" # width=width + (out_line * 2), height=height + (out_line * 2),
# batch=batch, group=group)
def _update_position(self): # self._光标 = Rectangle(x=x + out_line, y=y + out_line,
self._input_box.position = self._x + self.out_bound, self._y + self.out_bound # color=cursor_color,
self._out_box.position = self._x - self.out_bound, self._y - self.out_bound # width=1, height=self.font_height,
self._光标.position = self._x + self.out_bound, self._y + self.out_bound # batch=batch, group=group)
# self._选择框 = Rectangle(x=x, y=y, width=0, height=self.font_height,
# 输入东西 # color=select_color)
def on_text(self, text: str): # self._选择的字 = Label(x=x, y=y, width=0, height=self.font_height,
if self.enabled: # color=text_color,
if text in ('\r', '\n'): # font_name=font_name, font_size=font_size,
if self.text: # batch=batch, group=group,
self.dispatch_event('on_commit', self.text) # text='')
else: #
self.text = f'{self.text[:self.cursor_poi]}{text}{self.text[self.cursor_poi:]}' # """
self.cursor_poi += len(text) # 输入框的属性
# """
# 移动光标 #
def on_text_motion(self, motion): # # 本身属性
if self.enabled: # @property
# 根据按键处理 # def text(self) -> str: # 输入框的文本
# 单格移动光标(上下左右) # return self._text
if motion in (key.MOTION_UP, key.MOTION_LEFT): # 往上一个移动 #
self.cursor_poi = max(0, self._cursor_poi - 1) # @text.setter
elif motion in (key.MOTION_DOWN, key.MOTION_RIGHT): # 往下一个移动 # def text(self, value) -> None:
self.cursor_poi = min(len(self.text), self._cursor_poi + 1) # assert type(value) is str, 'Input Box\'s text must be string!'
# 大前后移动(开头或结尾) # self._text = value
elif motion in ( # self._input_box.text = value
key.MOTION_BEGINNING_OF_LINE, key.MOTION_BEGINNING_OF_FILE, key.MOTION_PREVIOUS_PAGE): # 开头 # self._HTML_box.text = html.decode_text2HTML(value, show_style=True)
self.cursor_poi = 0 #
elif motion in (key.MOTION_END_OF_LINE, key.MOTION_END_OF_FILE, key.MOTION_NEXT_PAGE): # 结尾 # @property
self.cursor_poi = len(self.text) # def cursor_poi(self) -> int: # 光标位置
# 删除操作 # return self._cursor_poi
elif motion == key.MOTION_BACKSPACE: #
if self.text: # 如果有文字 # @cursor_poi.setter
self.text = f'{self.text[:self.cursor_poi - 1]}{self.text[self.cursor_poi:]}' # def cursor_poi(self, value) -> None:
self.cursor_poi = max(0, self._cursor_poi - 1) # assert type(value) is int, 'Input Box\'s cursor poi must be int!'
elif motion == key.MOTION_DELETE: # self._cursor_poi = value
if self.text and self.cursor_poi != len(self.text) - 1: # 如果有文字,并且光标不在最后 # self._光标.x = self.x + self.out_bound + self._input_box.content_width
self.text = f'{self.text[:self.cursor_poi]}{self.text[self.cursor_poi + 1:]}' #
# 剪贴板操作 # # 渲染时属性
elif motion == key.MOTION_COPY: # @property
pass # def opacity(self) -> int: # 透明度
elif motion == key.MOTION_PASTE: # return self._input_box.opacity
paste_text = paste() #
self.text = f'{self.text[:self.cursor_poi]}{paste_text}{self.text[self.cursor_poi:]}' # @opacity.setter
self.cursor_poi += len(paste_text) # def opacity(self, value: int) -> None:
# assert type(value) is int, 'Input Box\'s opacity must be int!'
def on_text_motion_select(self, motion): # self._input_box.opacity = value
pass # self._out_box.opacity = value
# self._选择的字.opacity = value
def on_mouse_press(self, x, y, buttons, modifiers): # self._选择框.opacity = value
if self._check_hit(x, y) and self._input_box.visible: # self._光标.opacity = value
self.enabled = True #
else: # @property
self.enabled = False # def visible(self) -> bool: # 是否可见
# return self._input_box.visible
def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers): #
pass # @visible.setter
# def visible(self, value: bool) -> None:
def on_mouse_release(self, x, y, buttons, modifiers): # assert type(value) is bool, 'Input Box\'s visible must be bool!'
pass # self._input_box.visible = value
# self._out_box.visible = value
def on_commit(self, text: str): # self._选择的字.visible = value
pass # self._选择框.visible = value
# self._光标.visible = value
#
# @property
# def value(self) -> str:
# return self._text
#
# """
# 事件调用
# """
#
# def _update_position(self):
# self._input_box.position = self._x + self.out_bound, self._y + self.out_bound
# self._out_box.position = self._x - self.out_bound, self._y - self.out_bound
# self._光标.position = self._x + self.out_bound, self._y + self.out_bound
#
# # 输入东西
# def on_text(self, text: str):
# if self.enabled:
# if text in ('\r', '\n'):
# if self.text:
# self.dispatch_event('on_commit', self.text)
# else:
# self.text = f'{self.text[:self.cursor_poi]}{text}{self.text[self.cursor_poi:]}'
# self.cursor_poi += len(text)
#
# # 移动光标
# def on_text_motion(self, motion):
# if self.enabled:
# # 根据按键处理
# # 单格移动光标(上下左右)
# if motion in (key.MOTION_UP, key.MOTION_LEFT): # 往上一个移动
# self.cursor_poi = max(0, self._cursor_poi - 1)
# elif motion in (key.MOTION_DOWN, key.MOTION_RIGHT): # 往下一个移动
# self.cursor_poi = min(len(self.text), self._cursor_poi + 1)
# # 大前后移动(开头或结尾)
# elif motion in (
# key.MOTION_BEGINNING_OF_LINE, key.MOTION_BEGINNING_OF_FILE, key.MOTION_PREVIOUS_PAGE): # 开头
# self.cursor_poi = 0
# elif motion in (key.MOTION_END_OF_LINE, key.MOTION_END_OF_FILE, key.MOTION_NEXT_PAGE): # 结尾
# self.cursor_poi = len(self.text)
# # 删除操作
# elif motion == key.MOTION_BACKSPACE:
# if self.text: # 如果有文字
# self.text = f'{self.text[:self.cursor_poi - 1]}{self.text[self.cursor_poi:]}'
# self.cursor_poi = max(0, self._cursor_poi - 1)
# elif motion == key.MOTION_DELETE:
# if self.text and self.cursor_poi != len(self.text) - 1: # 如果有文字,并且光标不在最后
# self.text = f'{self.text[:self.cursor_poi]}{self.text[self.cursor_poi + 1:]}'
# # 剪贴板操作
# elif motion == key.MOTION_COPY:
# pass
# elif motion == key.MOTION_PASTE:
# paste_text = paste()
# self.text = f'{self.text[:self.cursor_poi]}{paste_text}{self.text[self.cursor_poi:]}'
# self.cursor_poi += len(paste_text)
#
# def on_text_motion_select(self, motion):
# pass
#
# def on_mouse_press(self, x, y, buttons, modifiers):
# if self._check_hit(x, y) and self._input_box.visible:
# self.enabled = True
# else:
# self.enabled = False
#
# def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
# pass
#
# def on_mouse_release(self, x, y, buttons, modifiers):
# pass
#
# def on_commit(self, text: str):
# pass
InputBox.register_event_type('on_commit') InputBox.register_event_type('on_commit')

View File

@ -14,7 +14,7 @@ gitee: @shenjackyuanjie
# system function # system function
import time import time
from typing import Union from typing import Union, Optional, Tuple
from decimal import Decimal from decimal import Decimal
# from pyglet # from pyglet
@ -30,12 +30,21 @@ from Difficult_Rocket.command.api import CommandText
from Difficult_Rocket.utils.new_thread import new_thread from Difficult_Rocket.utils.new_thread import new_thread
class CommandLineTextEntry(widgets.TextEntry): class CommandLineTextEntry(widgets.TextEntry):
""" """
基于 Text Entry 重写的 Command Line 基于 Text Entry 重写的 Command Line
""" """
def __init__(self, x: int, y: int, width: int,
color: Optional[Tuple[int, int, int, int]] = (255, 255, 255, 255),
text_color: Optional[Tuple[int, int, int, int]] = (0, 0, 0, 255),
caret_color: Optional[Tuple[int, int, int, int]] = (0, 0, 0),
batch: Optional[Batch] = None, group: Optional[Group] = None):
super().__init__(x=x, y=y, width=width,
color=color, text_color=text_color, caret_color=caret_color,
batch=batch, group=group, text='')
class CommandLine(widgets.WidgetBase): class CommandLine(widgets.WidgetBase):
""" """
@ -172,7 +181,8 @@ class CommandLine(widgets.WidgetBase):
self._label[0].visible = True self._label[0].visible = True
time.sleep(wait) time.sleep(wait)
if self._label[0].visible and not self.editing: if self._label[0].visible and not self.editing:
while (self._label[0].opacity >= 30) and self._label[0].visible and (self._label[0] is this) and not self.editing: while (self._label[0].opacity >= 30) and self._label[0].visible and (
self._label[0] is this) and not self.editing:
# (label 的透明度不是 0) and (label 还在显示) and (label 还是载入线程时候的那个label) and (现在不在输入新行) # (label 的透明度不是 0) and (label 还在显示) and (label 还是载入线程时候的那个label) and (现在不在输入新行)
self._label[0].opacity -= 2 self._label[0].opacity -= 2
time.sleep(0.01) time.sleep(0.01)