message_box.gd 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. # MessageBox.gd
  2. extends Window
  3. class_name MessageBox
  4. signal accepted()
  5. signal rejected()
  6. enum ButtonRole {
  7. ACCEPT,
  8. REJECT,
  9. DESTRUCTIVE,
  10. ACTION
  11. }
  12. enum StandardButton {
  13. OK = 1,
  14. CANCEL = 2,
  15. YES = 4,
  16. NO = 8,
  17. ABORT = 16,
  18. RETRY = 32,
  19. IGNORE = 64,
  20. YES_ALL = 128,
  21. NO_ALL = 256,
  22. SAVE = 512,
  23. DISCARD = 1024
  24. }
  25. var _main_panel: PanelContainer
  26. var _buttons: HBoxContainer
  27. var label: Label
  28. var _icon: TextureRect
  29. var _theme = preload("res://Resources/Theme/basic_theme.tres")
  30. static var _node: Node
  31. # 静态方法
  32. static func normal(parent: Control, _title: String, text: String, buttons: int = StandardButton.OK) -> MessageBox:
  33. var msgbox = _create_message_box(parent, _title, text, buttons, "")
  34. msgbox.label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
  35. return msgbox
  36. static func information(parent: Control, _title: String, text: String, buttons: int = StandardButton.OK) -> MessageBox:
  37. return _create_message_box(parent, _title, text, buttons, "information")
  38. static func warning(parent: Control, _title: String, text: String, buttons: int = StandardButton.OK) -> MessageBox:
  39. return _create_message_box(parent, _title, text, buttons, "warning")
  40. static func error(parent: Control, _title: String, text: String, buttons: int = StandardButton.OK) -> MessageBox:
  41. return _create_message_box(parent, _title, text, buttons, "error")
  42. static func question(parent: Control, _title: String, text: String, buttons: int = StandardButton.YES | StandardButton.NO) -> MessageBox:
  43. return _create_message_box(parent, _title, text, buttons, "question")
  44. static func _create_message_box(parent: Node, _title: String, text: String, buttons: int, icon_type: String) -> MessageBox:
  45. var msg_box = MessageBox.new()
  46. if parent == null:
  47. parent = _node.get_tree().get_root()
  48. parent.add_child(msg_box)
  49. msg_box.title = _title
  50. msg_box.setup(text, buttons, icon_type)
  51. msg_box.popup_centered()
  52. return msg_box
  53. func _ready():
  54. size = Vector2(300, 150)
  55. exclusive = true
  56. #unresizable = true
  57. _main_panel = PanelContainer.new()
  58. #_main_panel.size = size
  59. #_main_panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
  60. #_main_panel.size_flags_vertical = Control.SIZE_EXPAND_FILL
  61. _main_panel.anchor_right = 1.0
  62. _main_panel.anchor_bottom = 1.0
  63. _main_panel.offset_right = 0
  64. _main_panel.offset_bottom = 0
  65. _main_panel.theme = _theme
  66. add_child(_main_panel)
  67. # 创建主容器
  68. var main_vbox = VBoxContainer.new()
  69. #main_vbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
  70. #main_vbox.size_flags_vertical = Control.SIZE_EXPAND_FILL
  71. main_vbox.anchor_right = 1.0
  72. main_vbox.anchor_bottom = 1.0
  73. main_vbox.offset_right = 0
  74. main_vbox.offset_bottom = 0
  75. _main_panel.add_child(main_vbox)
  76. # 创建内容容器
  77. var content_hbox = HBoxContainer.new()
  78. content_hbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
  79. content_hbox.size_flags_vertical = Control.SIZE_EXPAND_FILL
  80. #content_hbox.add_theme_constant_override("separation", 20)
  81. main_vbox.add_child(content_hbox)
  82. # 图标
  83. _icon = TextureRect.new()
  84. _icon.size_flags_horizontal = Control.SIZE_FILL
  85. _icon.size_flags_vertical = Control.SIZE_SHRINK_CENTER
  86. _icon.expand_mode = TextureRect.EXPAND_FIT_WIDTH_PROPORTIONAL
  87. _icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
  88. _icon.custom_minimum_size = Vector2(80, 64)
  89. content_hbox.add_child(_icon)
  90. # 文本标签
  91. label = Label.new()
  92. label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
  93. #label.size_flags_vertical = Control.SIZE_EXPAND_FILL
  94. #label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
  95. label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
  96. content_hbox.add_child(label)
  97. # 按钮容器
  98. _buttons = HBoxContainer.new()
  99. _buttons.size_flags_horizontal = Control.SIZE_EXPAND_FILL
  100. _buttons.size_flags_vertical = Control.SIZE_SHRINK_CENTER
  101. _buttons.alignment = BoxContainer.ALIGNMENT_CENTER
  102. _buttons.add_theme_constant_override("separation", 20)
  103. main_vbox.add_child(_buttons)
  104. close_requested.connect(_on_close_requested)
  105. size_changed.connect(func(): _main_panel.size = size)
  106. func setup(text: String, buttons: int, icon_type: String = ""):
  107. label.text = text
  108. _setup_icon(icon_type)
  109. _setup_buttons(buttons)
  110. func resize(new_size: Vector2, center_window:bool = true):
  111. size = new_size
  112. await get_tree().process_frame
  113. _main_panel.custom_minimum_size = new_size
  114. _main_panel.reset_size()
  115. if center_window:
  116. var viewport_size = get_tree().root.get_viewport().get_visible_rect().size
  117. position = (viewport_size - new_size) / 2
  118. func _setup_icon(icon_type: String):
  119. var icon_texture: Texture2D
  120. match icon_type:
  121. "information": icon_texture = preload("res://Resources/UI/msgbox_infomation.png") # 需要提供图标
  122. "warning": icon_texture = preload("res://Resources/UI/msgbox_warning.png")
  123. "error": icon_texture = preload("res://Resources/UI/msgbox_error.png")
  124. "question": icon_texture = preload("res://Resources/UI/msgbox_question.png")
  125. if icon_texture:
  126. _icon.texture = icon_texture
  127. _icon.show()
  128. else:
  129. _icon.hide()
  130. func _setup_buttons(buttons_mask: int):
  131. # 清空现有按钮
  132. for child in _buttons.get_children():
  133. child.queue_free()
  134. var button_definitions = [
  135. [StandardButton.OK, "OK", ButtonRole.ACCEPT],
  136. [StandardButton.CANCEL, "Cancel", ButtonRole.REJECT],
  137. [StandardButton.YES, "Yes", ButtonRole.ACCEPT],
  138. [StandardButton.NO, "No", ButtonRole.REJECT],
  139. [StandardButton.ABORT, "Abort", ButtonRole.REJECT],
  140. [StandardButton.RETRY, "Retry", ButtonRole.ACTION],
  141. [StandardButton.IGNORE, "Ignore", ButtonRole.ACTION],
  142. [StandardButton.SAVE, "Save", ButtonRole.ACCEPT],
  143. [StandardButton.DISCARD, "Discard", ButtonRole.DESTRUCTIVE]
  144. ]
  145. for definition in button_definitions:
  146. var button_flag = definition[0]
  147. var button_text = definition[1]
  148. var button_role = definition[2]
  149. if buttons_mask & button_flag:
  150. var button = Button.new()
  151. button.text = button_text
  152. button.custom_minimum_size = Vector2(80.0, 30)
  153. button.theme = _theme
  154. button.pressed.connect(_on_button_pressed.bind(button_role))
  155. _buttons.add_child(button)
  156. func _on_button_pressed(role: ButtonRole):
  157. match role:
  158. ButtonRole.ACCEPT: accepted.emit()
  159. ButtonRole.REJECT: rejected.emit()
  160. ButtonRole.DESTRUCTIVE: rejected.emit()
  161. hide()
  162. queue_free()
  163. func _on_close_requested():
  164. rejected.emit()
  165. hide()
  166. queue_free()
  167. # 阻塞式调用(模拟)
  168. static func information_blocking(parent: Control, _title: String, text: String, buttons: int = StandardButton.OK) -> int:
  169. var result = -1
  170. var msg_box = information(parent, _title, text, buttons)
  171. # 连接信号来设置结果
  172. msg_box.accepted.connect(func(): result = StandardButton.OK)
  173. msg_box.rejected.connect(func(): result = StandardButton.CANCEL)
  174. # 等待对话框关闭
  175. await msg_box.tree_exited
  176. return result