| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- # MessageBox.gd
- extends Window
- class_name MessageBox
- signal accepted()
- signal rejected()
- enum ButtonRole {
- ACCEPT,
- REJECT,
- DESTRUCTIVE,
- ACTION
- }
- enum StandardButton {
- OK = 1,
- CANCEL = 2,
- YES = 4,
- NO = 8,
- ABORT = 16,
- RETRY = 32,
- IGNORE = 64,
- YES_ALL = 128,
- NO_ALL = 256,
- SAVE = 512,
- DISCARD = 1024
- }
- var _main_panel: PanelContainer
- var _buttons: HBoxContainer
- var label: Label
- var _icon: TextureRect
- var _theme = preload("res://Resources/Theme/basic_theme.tres")
- static var _node: Node
- # 静态方法
- static func normal(parent: Control, _title: String, text: String, buttons: int = StandardButton.OK) -> MessageBox:
- var msgbox = _create_message_box(parent, _title, text, buttons, "")
- msgbox.label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
- return msgbox
- static func information(parent: Control, _title: String, text: String, buttons: int = StandardButton.OK) -> MessageBox:
- return _create_message_box(parent, _title, text, buttons, "information")
- static func warning(parent: Control, _title: String, text: String, buttons: int = StandardButton.OK) -> MessageBox:
- return _create_message_box(parent, _title, text, buttons, "warning")
- static func error(parent: Control, _title: String, text: String, buttons: int = StandardButton.OK) -> MessageBox:
- return _create_message_box(parent, _title, text, buttons, "error")
- static func question(parent: Control, _title: String, text: String, buttons: int = StandardButton.YES | StandardButton.NO) -> MessageBox:
- return _create_message_box(parent, _title, text, buttons, "question")
- static func _create_message_box(parent: Node, _title: String, text: String, buttons: int, icon_type: String) -> MessageBox:
- var msg_box = MessageBox.new()
- if parent == null:
- parent = _node.get_tree().get_root()
- parent.add_child(msg_box)
- msg_box.title = _title
- msg_box.setup(text, buttons, icon_type)
- msg_box.popup_centered()
- return msg_box
- func _ready():
- size = Vector2(300, 150)
- exclusive = true
- #unresizable = true
-
- _main_panel = PanelContainer.new()
- #_main_panel.size = size
- #_main_panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
- #_main_panel.size_flags_vertical = Control.SIZE_EXPAND_FILL
- _main_panel.anchor_right = 1.0
- _main_panel.anchor_bottom = 1.0
- _main_panel.offset_right = 0
- _main_panel.offset_bottom = 0
- _main_panel.theme = _theme
- add_child(_main_panel)
-
- # 创建主容器
- var main_vbox = VBoxContainer.new()
- #main_vbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
- #main_vbox.size_flags_vertical = Control.SIZE_EXPAND_FILL
- main_vbox.anchor_right = 1.0
- main_vbox.anchor_bottom = 1.0
- main_vbox.offset_right = 0
- main_vbox.offset_bottom = 0
- _main_panel.add_child(main_vbox)
-
- # 创建内容容器
- var content_hbox = HBoxContainer.new()
- content_hbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
- content_hbox.size_flags_vertical = Control.SIZE_EXPAND_FILL
- #content_hbox.add_theme_constant_override("separation", 20)
- main_vbox.add_child(content_hbox)
-
- # 图标
- _icon = TextureRect.new()
- _icon.size_flags_horizontal = Control.SIZE_FILL
- _icon.size_flags_vertical = Control.SIZE_SHRINK_CENTER
- _icon.expand_mode = TextureRect.EXPAND_FIT_WIDTH_PROPORTIONAL
- _icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
- _icon.custom_minimum_size = Vector2(80, 64)
- content_hbox.add_child(_icon)
-
- # 文本标签
- label = Label.new()
- label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
- #label.size_flags_vertical = Control.SIZE_EXPAND_FILL
- #label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
- label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
- content_hbox.add_child(label)
-
- # 按钮容器
- _buttons = HBoxContainer.new()
- _buttons.size_flags_horizontal = Control.SIZE_EXPAND_FILL
- _buttons.size_flags_vertical = Control.SIZE_SHRINK_CENTER
- _buttons.alignment = BoxContainer.ALIGNMENT_CENTER
- _buttons.add_theme_constant_override("separation", 20)
- main_vbox.add_child(_buttons)
-
- close_requested.connect(_on_close_requested)
- size_changed.connect(func(): _main_panel.size = size)
- func setup(text: String, buttons: int, icon_type: String = ""):
- label.text = text
- _setup_icon(icon_type)
- _setup_buttons(buttons)
- func resize(new_size: Vector2, center_window:bool = true):
- size = new_size
- await get_tree().process_frame
- _main_panel.custom_minimum_size = new_size
- _main_panel.reset_size()
-
- if center_window:
- var viewport_size = get_tree().root.get_viewport().get_visible_rect().size
- position = (viewport_size - new_size) / 2
- func _setup_icon(icon_type: String):
- var icon_texture: Texture2D
- match icon_type:
- "information": icon_texture = preload("res://Resources/UI/msgbox_infomation.png") # 需要提供图标
- "warning": icon_texture = preload("res://Resources/UI/msgbox_warning.png")
- "error": icon_texture = preload("res://Resources/UI/msgbox_error.png")
- "question": icon_texture = preload("res://Resources/UI/msgbox_question.png")
-
- if icon_texture:
- _icon.texture = icon_texture
- _icon.show()
- else:
- _icon.hide()
- func _setup_buttons(buttons_mask: int):
- # 清空现有按钮
- for child in _buttons.get_children():
- child.queue_free()
-
- var button_definitions = [
- [StandardButton.OK, "OK", ButtonRole.ACCEPT],
- [StandardButton.CANCEL, "Cancel", ButtonRole.REJECT],
- [StandardButton.YES, "Yes", ButtonRole.ACCEPT],
- [StandardButton.NO, "No", ButtonRole.REJECT],
- [StandardButton.ABORT, "Abort", ButtonRole.REJECT],
- [StandardButton.RETRY, "Retry", ButtonRole.ACTION],
- [StandardButton.IGNORE, "Ignore", ButtonRole.ACTION],
- [StandardButton.SAVE, "Save", ButtonRole.ACCEPT],
- [StandardButton.DISCARD, "Discard", ButtonRole.DESTRUCTIVE]
- ]
-
- for definition in button_definitions:
- var button_flag = definition[0]
- var button_text = definition[1]
- var button_role = definition[2]
-
- if buttons_mask & button_flag:
- var button = Button.new()
- button.text = button_text
- button.custom_minimum_size = Vector2(80.0, 30)
- button.theme = _theme
- button.pressed.connect(_on_button_pressed.bind(button_role))
- _buttons.add_child(button)
- func _on_button_pressed(role: ButtonRole):
- match role:
- ButtonRole.ACCEPT: accepted.emit()
- ButtonRole.REJECT: rejected.emit()
- ButtonRole.DESTRUCTIVE: rejected.emit()
-
- hide()
- queue_free()
- func _on_close_requested():
- rejected.emit()
- hide()
- queue_free()
- # 阻塞式调用(模拟)
- static func information_blocking(parent: Control, _title: String, text: String, buttons: int = StandardButton.OK) -> int:
- var result = -1
- var msg_box = information(parent, _title, text, buttons)
-
- # 连接信号来设置结果
- msg_box.accepted.connect(func(): result = StandardButton.OK)
- msg_box.rejected.connect(func(): result = StandardButton.CANCEL)
-
- # 等待对话框关闭
- await msg_box.tree_exited
- return result
|