From c140b9a96c254b135af2a4336a7584e169347dfc Mon Sep 17 00:00:00 2001 From: hz Date: Tue, 4 Aug 2026 07:10:36 -0500 Subject: [PATCH] Fix CCS popup lifecycle and contrast --- scripts/ui/ccs_player.gd | 66 ++++++++++++++++++++++++++++++++++++++++ tests/ccs_player_test.gd | 9 ++++++ 2 files changed, 75 insertions(+) diff --git a/scripts/ui/ccs_player.gd b/scripts/ui/ccs_player.gd index 7855bff..7adfc14 100644 --- a/scripts/ui/ccs_player.gd +++ b/scripts/ui/ccs_player.gd @@ -435,6 +435,26 @@ func on_show(payload: Variant = null) -> void: func on_hide() -> void: timer.stop() + _dismiss_dialogs() + + +func _dismiss_dialogs() -> void: + # Dialogs are Window nodes, so hiding their parent Control does not dismiss + # them. Always close every CCS overlay when navigation or logout hides the + # player to prevent case content from appearing over another screen. + for dialog in _ccs_dialogs(): + if dialog != null: + dialog.hide() + if report_dialog != null and report_dialog.has_method("hide_dialog"): + report_dialog.hide_dialog() + + +func _ccs_dialogs() -> Array[Window]: + var dialogs: Array[Window] = [] + for dialog in [intro_dialog, exam_dialog, exam_summary_dialog, findings_dialog, time_dialog, location_dialog, end_dialog, final_instructions, abandon_dialog]: + if dialog is Window: + dialogs.append(dialog) + return dialogs func _render() -> void: @@ -1084,6 +1104,52 @@ func _apply_theme() -> void: button.add_theme_stylebox_override("hover", Brand.content_card_box(dark, true)) for label in clinical_labels: label.add_theme_color_override("default_color", Brand.text_color(dark)) + _apply_dialog_theme(dark) Brand.set_theme_toggle_icon(theme_button, dark) theme_button.tooltip_text = "Switch to light mode" if dark else "Switch to dark mode" _apply_text_scale() + + +func _apply_dialog_theme(dark: bool) -> void: + var popup_theme := Theme.new() + var text := Brand.text_color(dark) + var muted := Brand.muted_color(dark) + var panel := Brand.content_card_box(dark, false) + panel.content_margin_left = 18 + panel.content_margin_right = 18 + panel.content_margin_top = 16 + panel.content_margin_bottom = 16 + + for type_name in ["Label", "Button", "CheckBox", "OptionButton", "LineEdit", "PopupMenu"]: + popup_theme.set_font("font", type_name, Brand.font) + popup_theme.set_color("font_color", type_name, text) + popup_theme.set_font("normal_font", "RichTextLabel", Brand.font) + popup_theme.set_font("bold_font", "RichTextLabel", Brand.font) + popup_theme.set_color("default_color", "RichTextLabel", text) + popup_theme.set_color("font_selected_color", "RichTextLabel", text) + popup_theme.set_color("font_hover_color", "Button", text) + popup_theme.set_color("font_pressed_color", "Button", text) + popup_theme.set_color("font_disabled_color", "Button", muted) + popup_theme.set_color("font_hover_color", "OptionButton", text) + popup_theme.set_color("font_pressed_color", "OptionButton", text) + popup_theme.set_color("font_hover_color", "CheckBox", text) + popup_theme.set_color("font_pressed_color", "CheckBox", text) + popup_theme.set_color("font_hover_color", "PopupMenu", text) + popup_theme.set_color("font_accelerator_color", "PopupMenu", muted) + popup_theme.set_color("font_placeholder_color", "LineEdit", muted) + popup_theme.set_color("title_color", "Window", text) + popup_theme.set_font("title_font", "Window", Brand.font) + + for type_name in ["Button", "OptionButton"]: + popup_theme.set_stylebox("normal", type_name, Brand.secondary_button_box(dark)) + popup_theme.set_stylebox("hover", type_name, Brand.secondary_button_box(dark, true)) + popup_theme.set_stylebox("pressed", type_name, Brand.secondary_button_box(dark, true)) + popup_theme.set_stylebox("normal", "LineEdit", Brand.field_box(dark)) + popup_theme.set_stylebox("focus", "LineEdit", Brand.field_box(dark, true)) + for type_name in ["Window", "AcceptDialog", "ConfirmationDialog"]: + popup_theme.set_stylebox("panel", type_name, panel) + popup_theme.set_stylebox("panel", "PopupMenu", panel) + popup_theme.set_stylebox("hover", "PopupMenu", Brand.secondary_button_box(dark, true)) + + for dialog in _ccs_dialogs(): + dialog.theme = popup_theme diff --git a/tests/ccs_player_test.gd b/tests/ccs_player_test.gd index 6ec725e..03a4bdc 100644 --- a/tests/ccs_player_test.gd +++ b/tests/ccs_player_test.gd @@ -1,5 +1,7 @@ extends SceneTree +const Brand := preload("res://scripts/ui/medmind_style.gd") + var failures := 0 var ccs_service @@ -57,6 +59,13 @@ func _run() -> void: player.size = Vector2(800, 900) player._update_responsive_layout() _assert(player.action_grid.columns == 2, "narrow CCS screens should use a two-column action workspace") + _assert(player.intro_dialog.theme != null, "CCS dialogs should receive an explicit readable theme") + _assert(player.intro_dialog.theme.get_color("font_color", "Label") == Brand.text_color(player.theme_service.is_dark_mode()), "CCS dialog text should contrast with the active theme") + player.time_dialog.popup_centered(Vector2i(600, 350)) + await process_frame + _assert(player.time_dialog.visible, "CCS dialog lifecycle test should begin with an open popup") + player.on_hide() + _assert(not player.time_dialog.visible, "hiding the CCS screen should dismiss popup windows") ccs_service.attempt.state = "final_orders" player._render()