openpilot/system/ui/widgets/confirm_dialog.py
mouxangithub 6f2bd6efa3 feat(ui): 将字体权重统一调整为 CHINA 以支持中文字体渲染
将多个 UI 组件中的字体权重从原有的 `MEDIUM`、`NORMAL`、`BOLD` 等值统一修改为 `CHINA`,
以确保界面文本能够正确使用中文字体进行显示。同时调整了部分字号和标签样式,提升中文环境下的展示效果。
2025-11-20 11:43:26 +08:00

95 lines
3.9 KiB
Python

import pyray as rl
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.multilang import tr
from openpilot.system.ui.widgets import DialogResult
from openpilot.system.ui.widgets.button import ButtonStyle, Button
from openpilot.system.ui.widgets.label import Label
from openpilot.system.ui.widgets.html_render import HtmlRenderer, ElementType
from openpilot.system.ui.widgets import Widget
from openpilot.system.ui.widgets.scroller import Scroller
OUTER_MARGIN = 200
RICH_OUTER_MARGIN = 100
BUTTON_HEIGHT = 160
MARGIN = 50
TEXT_PADDING = 10
BACKGROUND_COLOR = rl.Color(27, 27, 27, 255)
class ConfirmDialog(Widget):
def __init__(self, text: str, confirm_text: str, cancel_text: str | None = None, rich: bool = False):
super().__init__()
if cancel_text is None:
cancel_text = tr("Cancel")
self._label = Label(text, 70, FontWeight.CHINA, text_color=rl.Color(201, 201, 201, 255))
self._html_renderer = HtmlRenderer(text=text, text_size={ElementType.P: 50}, center_text=True)
self._cancel_button = Button(cancel_text, self._cancel_button_callback)
self._confirm_button = Button(confirm_text, self._confirm_button_callback, button_style=ButtonStyle.PRIMARY)
self._rich = rich
self._dialog_result = DialogResult.NO_ACTION
self._cancel_text = cancel_text
self._scroller = Scroller([self._html_renderer], line_separator=False, spacing=0)
def set_text(self, text):
if not self._rich:
self._label.set_text(text)
else:
self._html_renderer.parse_html_content(text)
def reset(self):
self._dialog_result = DialogResult.NO_ACTION
def _cancel_button_callback(self):
self._dialog_result = DialogResult.CANCEL
def _confirm_button_callback(self):
self._dialog_result = DialogResult.CONFIRM
def _render(self, rect: rl.Rectangle):
dialog_x = OUTER_MARGIN if not self._rich else RICH_OUTER_MARGIN
dialog_y = OUTER_MARGIN if not self._rich else RICH_OUTER_MARGIN
dialog_width = gui_app.width - 2 * dialog_x
dialog_height = gui_app.height - 2 * dialog_y
dialog_rect = rl.Rectangle(dialog_x, dialog_y, dialog_width, dialog_height)
bottom = dialog_rect.y + dialog_rect.height
button_width = (dialog_rect.width - 3 * MARGIN) // 2
cancel_button_x = dialog_rect.x + MARGIN
confirm_button_x = dialog_rect.x + dialog_rect.width - button_width - MARGIN
button_y = bottom - BUTTON_HEIGHT - MARGIN
cancel_button = rl.Rectangle(cancel_button_x, button_y, button_width, BUTTON_HEIGHT)
confirm_button = rl.Rectangle(confirm_button_x, button_y, button_width, BUTTON_HEIGHT)
rl.draw_rectangle_rec(dialog_rect, BACKGROUND_COLOR)
text_rect = rl.Rectangle(dialog_rect.x + MARGIN, dialog_rect.y + TEXT_PADDING,
dialog_rect.width - 2 * MARGIN, dialog_rect.height - BUTTON_HEIGHT - MARGIN - TEXT_PADDING * 2)
if not self._rich:
self._label.render(text_rect)
else:
html_rect = rl.Rectangle(text_rect.x, text_rect.y, text_rect.width,
self._html_renderer.get_total_height(int(text_rect.width)))
self._html_renderer.set_rect(html_rect)
self._scroller.render(text_rect)
if rl.is_key_pressed(rl.KeyboardKey.KEY_ENTER):
self._dialog_result = DialogResult.CONFIRM
elif rl.is_key_pressed(rl.KeyboardKey.KEY_ESCAPE):
self._dialog_result = DialogResult.CANCEL
if self._cancel_text:
self._confirm_button.render(confirm_button)
self._cancel_button.render(cancel_button)
else:
full_button_width = dialog_rect.width - 2 * MARGIN
full_confirm_button = rl.Rectangle(dialog_rect.x + MARGIN, button_y, full_button_width, BUTTON_HEIGHT)
self._confirm_button.render(full_confirm_button)
return self._dialog_result
def alert_dialog(message: str, button_text: str | None = None):
if button_text is None:
button_text = tr("OK")
return ConfirmDialog(message, button_text, cancel_text="")