import pyray as rl
from openpilot . system . ui . lib . application import gui_app , FontWeight
from openpilot . system . ui . widgets import DialogResult
from openpilot . system . ui . widgets . button import gui_button , ButtonStyle , Button
from openpilot . system . ui . widgets . label import gui_text_box
from openpilot . system . ui . widgets import Widget
DIALOG_WIDTH = 1520
DIALOG_HEIGHT = 600
BUTTON_HEIGHT = 160
MARGIN = 50
TEXT_AREA_HEIGHT_REDUCTION = 200
BACKGROUND_COLOR = rl . Color ( 27 , 27 , 27 , 255 )
class ConfirmDialog ( Widget ) :
def __init__ ( self , text : str , confirm_text : str , cancel_text : str = " Cancel " ) :
super ( ) . __init__ ( )
self . text = text
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 . _dialog_result = DialogResult . NO_ACTION
self . _cancel_text = cancel_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 = ( gui_app . width - DIALOG_WIDTH ) / 2
dialog_y = ( gui_app . height - DIALOG_HEIGHT ) / 2
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 , dialog_rect . width - 2 * MARGIN , dialog_rect . height - TEXT_AREA_HEIGHT_REDUCTION )
gui_text_box (
text_rect ,
self . text ,
font_size = 70 ,
alignment = rl . GuiTextAlignment . TEXT_ALIGN_CENTER ,
alignment_vertical = rl . GuiTextAlignmentVertical . TEXT_ALIGN_MIDDLE ,
font_weight = FontWeight . BOLD ,
)
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 :
centered_button_x = dialog_rect . x + ( dialog_rect . width - button_width ) / 2
centered_confirm_button = rl . Rectangle ( centered_button_x , button_y , button_width , BUTTON_HEIGHT )
self . _confirm_button . render ( centered_confirm_button )
return self . _dialog_result
def confirm_dialog ( message : str , confirm_text : str , cancel_text : str = " Cancel " ) - > DialogResult :
dialog_x = ( gui_app . width - DIALOG_WIDTH ) / 2
dialog_y = ( gui_app . height - DIALOG_HEIGHT ) / 2
dialog_rect = rl . Rectangle ( dialog_x , dialog_y , DIALOG_WIDTH , DIALOG_HEIGHT )
# Calculate button positions at the bottom of the dialog
bottom = dialog_rect . y + dialog_rect . height
button_width = ( dialog_rect . width - 3 * MARGIN ) / / 2
no_button_x = dialog_rect . x + MARGIN
yes_button_x = dialog_rect . x + dialog_rect . width - button_width - MARGIN
button_y = bottom - BUTTON_HEIGHT - MARGIN
no_button = rl . Rectangle ( no_button_x , button_y , button_width , BUTTON_HEIGHT )
yes_button = rl . Rectangle ( yes_button_x , button_y , button_width , BUTTON_HEIGHT )
# Draw the dialog background
rl . draw_rectangle_rec ( dialog_rect , BACKGROUND_COLOR )
# Draw the message in the dialog, centered
text_rect = rl . Rectangle ( dialog_rect . x + MARGIN , dialog_rect . y , dialog_rect . width - 2 * MARGIN , dialog_rect . height - TEXT_AREA_HEIGHT_REDUCTION )
gui_text_box (
text_rect ,
message ,
font_size = 70 ,
alignment = rl . GuiTextAlignment . TEXT_ALIGN_CENTER ,
alignment_vertical = rl . GuiTextAlignmentVertical . TEXT_ALIGN_MIDDLE ,
font_weight = FontWeight . BOLD ,
)
# Initialize result; -1 means no action taken yet
result = DialogResult . NO_ACTION
# Check for keyboard input for accessibility
if rl . is_key_pressed ( rl . KeyboardKey . KEY_ENTER ) :
result = DialogResult . CONFIRM
elif rl . is_key_pressed ( rl . KeyboardKey . KEY_ESCAPE ) :
result = DialogResult . CANCEL
# Check for button clicks
if cancel_text :
if gui_button ( yes_button , confirm_text , button_style = ButtonStyle . PRIMARY ) :
result = DialogResult . CONFIRM
if gui_button ( no_button , cancel_text ) :
result = DialogResult . CANCEL
else :
centered_button_x = dialog_rect . x + ( dialog_rect . width - button_width ) / 2
centered_yes_button = rl . Rectangle ( centered_button_x , button_y , button_width , BUTTON_HEIGHT )
if gui_button ( centered_yes_button , confirm_text , button_style = ButtonStyle . PRIMARY ) :
result = DialogResult . CONFIRM
return result
def alert_dialog ( message : str , button_text : str = " OK " ) - > DialogResult :
return confirm_dialog ( message , button_text , cancel_text = " " )