Difficult-Rocket/Difficult_Rocket/client/guis/widgets.py

255 lines
10 KiB
Python
Raw Normal View History

2021-10-01 23:12:01 +08:00
# -------------------------------
# Difficult Rocket
2022-06-27 16:51:14 +08:00
# Copyright © 2021-2022 by shenjackyuanjie 3695888@qq.com
2021-10-01 23:12:01 +08:00
# All rights reserved
# -------------------------------
"""
writen by shenjackyuanjie
mail: 3695888@qq.com
github: @shenjackyuanjie
gitee: @shenjackyuanjie
"""
2022-08-29 00:26:14 +08:00
from Difficult_Rocket.utils import translate
from Difficult_Rocket.client.guis.format import html
2022-08-12 21:07:36 +08:00
from Difficult_Rocket import DR_option
2021-11-06 19:07:32 +08:00
# from libs import pyglet
2021-11-06 14:13:42 +08:00
from libs.pyglet import font
2021-12-26 23:06:03 +08:00
from libs.pyglet.text import Label, HTMLLabel
2021-11-06 19:07:32 +08:00
from libs.pyglet.window import key
2021-10-01 23:12:01 +08:00
from libs.pyglet.gui import widgets
from libs.pyglet.sprite import Sprite
2021-11-06 14:13:42 +08:00
from libs.pyglet.shapes import Rectangle
2022-04-13 19:00:36 +08:00
from libs.pyglet.image import AbstractImage
2021-11-06 19:07:32 +08:00
from libs.pyglet.graphics import Batch, Group
2021-12-15 23:28:08 +08:00
from libs.pyglet.text.document import FormattedDocument
from libs.pyglet.text.layout import IncrementalTextLayout
2021-11-06 19:07:32 +08:00
# from libs import pyperclip
2022-04-26 22:05:58 +08:00
from libs.pyperclip import paste
2021-10-01 23:12:01 +08:00
2022-05-11 11:11:39 +08:00
__all__ = ['Parts', 'InputBox']
2021-10-01 23:12:01 +08:00
class Parts(widgets.WidgetBase):
"""
parts
"""
2021-10-01 23:12:01 +08:00
def __init__(self,
x: int,
y: int,
width: int,
height: int,
2022-04-26 22:05:58 +08:00
textures: AbstractImage,
# textures,
2021-10-01 23:12:01 +08:00
batch: Batch,
parts_data: dict):
super().__init__(x, y, width, height)
self.sprite = Sprite(img=textures, x=x, y=y, batch=batch)
self._value = 0
2021-11-04 22:35:09 +08:00
2022-08-12 21:07:36 +08:00
if not DR_option.InputBox_use_TextEntry:
2022-04-13 19:00:36 +08:00
class InputBox(widgets.WidgetBase):
"""
input box
"""
def __init__(self,
x: int, y: int, width: int, height: int,
message: str = '',
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)
2021-11-06 19:07:32 +08:00
self.enabled = False
2022-04-13 19:00:36 +08:00
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
2022-08-12 21:07:36 +08:00
if DR_option.InputBox_use_TextEntry:
2022-04-13 19:00:36 +08:00
# 基于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='')
"""
输入框的属性
"""
# 本身属性
@property
def text(self) -> str: # 输入框的文本
return self._text
@text.setter
def text(self, value) -> None:
assert type(value) is str, 'Input Box\'s text must be string!'
self._text = value
self._input_box.text = value
self._HTML_box.text = html.decode_text2HTML(value, show_style=True)
@property
def cursor_poi(self) -> int: # 光标位置
return self._cursor_poi
@cursor_poi.setter
def cursor_poi(self, value) -> None:
assert type(value) is int, 'Input Box\'s cursor poi must be int!'
self._cursor_poi = value
self._光标.x = self.x + self.out_bound + self._input_box.content_width
# 渲染时属性
@property
def opacity(self) -> int: # 透明度
return self._input_box.opacity
@opacity.setter
def opacity(self, value: int) -> None:
assert type(value) is int, 'Input Box\'s opacity must be int!'
self._input_box.opacity = value
self._out_box.opacity = value
self._选择的字.opacity = value
self._选择框.opacity = value
self._光标.opacity = value
@property
def visible(self) -> bool: # 是否可见
return self._input_box.visible
@visible.setter
def visible(self, value: bool) -> None:
assert type(value) is bool, 'Input Box\'s visible must be bool!'
self._input_box.visible = value
self._out_box.visible = value
self._选择的字.visible = value
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
2021-11-06 19:07:32 +08:00
2022-04-13 19:00:36 +08:00
def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
pass
2021-11-06 19:07:32 +08:00
2022-04-13 19:00:36 +08:00
def on_mouse_release(self, x, y, buttons, modifiers):
pass
2021-11-06 19:07:32 +08:00
2022-04-13 19:00:36 +08:00
def on_commit(self, text: str):
pass
2021-11-06 19:07:32 +08:00
2022-04-13 19:00:36 +08:00
InputBox.register_event_type('on_commit')
else:
class InputBox(widgets.TextEntry):
pass