mirror of
https://github.com/lihop/godot-xterm.git
synced 2024-11-10 04:40:25 +01:00
556 lines
13 KiB
GDScript
556 lines
13 KiB
GDScript
extends Panel
|
|
|
|
@onready var _script_list = $ScriptsList
|
|
@onready var _nav_container = $VBox/BottomPanel/VBox/HBox/Node3D
|
|
@onready var _nav = {
|
|
container = _nav_container,
|
|
prev = _nav_container.get_node("VBox/HBox/Previous"),
|
|
next = _nav_container.get_node("VBox/HBox/Next"),
|
|
run = _nav_container.get_node("VBox/HBox/Run"),
|
|
current_script = _nav_container.get_node("VBox/CurrentScript"),
|
|
run_single = _nav_container.get_node("VBox/HBox/RunSingleScript")
|
|
}
|
|
|
|
@onready var _progress_container = $VBox/BottomPanel/VBox/HBox/Progress
|
|
@onready var _progress = {
|
|
script = _progress_container.get_node("ScriptProgress"),
|
|
script_xy = _progress_container.get_node("ScriptProgress/xy"),
|
|
test = _progress_container.get_node("TestProgress"),
|
|
test_xy = _progress_container.get_node("TestProgress/xy")
|
|
}
|
|
@onready var _summary = {
|
|
control = $VBox/TitleBar/HBox/Summary,
|
|
failing = $VBox/TitleBar/HBox/Summary/Failing,
|
|
passing = $VBox/TitleBar/HBox/Summary/Passing,
|
|
asserts = $VBox/TitleBar/HBox/Summary/AssertCount,
|
|
fail_count = 0,
|
|
pass_count = 0
|
|
}
|
|
|
|
@onready var _extras = $ExtraOptions
|
|
@onready var _ignore_pauses = $ExtraOptions/IgnorePause
|
|
@onready var _continue_button = $VBox/BottomPanel/VBox/HBox/Continue/Continue
|
|
@onready var _text_box = $VBox/TextDisplay/RichTextLabel
|
|
@onready var _text_box_container = $VBox/TextDisplay
|
|
@onready var _log_level_slider = $VBox/BottomPanel/VBox/HBox2/LogLevelSlider
|
|
@onready var _resize_handle = $ResizeHandle
|
|
@onready var _current_script = $VBox/BottomPanel/VBox/HBox2/CurrentScriptLabel
|
|
@onready var _title_replacement = $VBox/TitleBar/HBox/TitleReplacement
|
|
|
|
@onready var _titlebar = {
|
|
bar = $VBox/TitleBar, time = $VBox/TitleBar/HBox/Time, label = $VBox/TitleBar/HBox/Title
|
|
}
|
|
|
|
@onready var _user_files = $UserFileViewer
|
|
|
|
var _mouse = {down = false, in_title = false, down_pos = null, in_handle = false}
|
|
|
|
var _is_running = false
|
|
var _start_time = 0.0
|
|
var _time = 0.0
|
|
|
|
const DEFAULT_TITLE = "GUT"
|
|
var _pre_maximize_rect = null
|
|
var _font_size = 20
|
|
var _compact_mode = false
|
|
|
|
var min_sizes = {
|
|
compact = Vector2(330, 100),
|
|
full = Vector2(740, 300),
|
|
}
|
|
|
|
signal end_pause
|
|
signal ignore_pause
|
|
signal log_level_changed
|
|
signal run_script
|
|
signal run_single_script
|
|
|
|
|
|
func _ready():
|
|
if Engine.editor_hint:
|
|
return
|
|
|
|
_current_script.text = ""
|
|
_pre_maximize_rect = get_rect()
|
|
_hide_scripts()
|
|
_update_controls()
|
|
_nav.current_script.set_text("No scripts available")
|
|
set_title()
|
|
clear_summary()
|
|
_titlebar.time.set_text("t: 0.0")
|
|
|
|
_extras.visible = false
|
|
update()
|
|
|
|
set_font_size(_font_size)
|
|
set_font("CourierPrime")
|
|
|
|
_user_files.set_position(Vector2(10, 30))
|
|
|
|
|
|
func elapsed_time_as_str():
|
|
return str("%.1f" % (_time / 1000.0), "s")
|
|
|
|
|
|
func _process(_delta):
|
|
if _is_running:
|
|
_time = Time.get_ticks_msec() - _start_time
|
|
_titlebar.time.set_text(str("t: ", elapsed_time_as_str()))
|
|
|
|
|
|
func _draw(): # needs get_size()
|
|
# Draw the lines in the corner to show where you can
|
|
# drag to resize the dialog
|
|
var grab_margin = 3
|
|
var line_space = 3
|
|
var grab_line_color = Color(.4, .4, .4)
|
|
if _resize_handle.visible:
|
|
for i in range(1, 10):
|
|
var x = size - Vector2(i * line_space, grab_margin)
|
|
var y = size - Vector2(grab_margin, i * line_space)
|
|
draw_line(x,y,grab_line_color,1)
|
|
|
|
|
|
func _on_Maximize_draw():
|
|
# draw the maximize square thing.
|
|
var btn = $VBox/TitleBar/HBox/Maximize
|
|
btn.set_text("")
|
|
var w = btn.get_size().x
|
|
var h = btn.get_size().y
|
|
btn.draw_rect(Rect2(0, 2, w, h - 2), Color(0, 0, 0, 1))
|
|
btn.draw_rect(Rect2(2, 6, w - 4, h - 8), Color(1, 1, 1, 1))
|
|
|
|
|
|
func _on_ShowExtras_draw():
|
|
var btn = $VBox/BottomPanel/VBox/HBox/Continue/ShowExtras
|
|
btn.set_text("")
|
|
var start_x = 20
|
|
var start_y = 15
|
|
var pad = 5
|
|
var color = Color(.1, .1, .1, 1)
|
|
var width = 2
|
|
for i in range(3):
|
|
var y = start_y + pad * i
|
|
btn.draw_line(
|
|
Vector2(start_x, y), Vector2(btn.get_size().x - start_x, y), color, width, true
|
|
)
|
|
|
|
|
|
# ####################
|
|
# GUI Events
|
|
# ####################
|
|
func _on_Run_pressed():
|
|
_run_mode()
|
|
emit_signal("run_script", get_selected_index())
|
|
|
|
|
|
func _on_CurrentScript_pressed():
|
|
_toggle_scripts()
|
|
|
|
|
|
func _on_Previous_pressed():
|
|
_select_script(get_selected_index() - 1)
|
|
|
|
|
|
func _on_Next_pressed():
|
|
_select_script(get_selected_index() + 1)
|
|
|
|
|
|
func _on_LogLevelSlider_value_changed(_value):
|
|
emit_signal("log_level_changed", _log_level_slider.value)
|
|
|
|
|
|
func _on_Continue_pressed():
|
|
_continue_button.disabled = true
|
|
emit_signal("end_pause")
|
|
|
|
|
|
func _on_IgnorePause_pressed():
|
|
var checked = _ignore_pauses.is_pressed()
|
|
emit_signal("ignore_pause", checked)
|
|
if checked:
|
|
emit_signal("end_pause")
|
|
_continue_button.disabled = true
|
|
|
|
|
|
func _on_RunSingleScript_pressed():
|
|
_run_mode()
|
|
emit_signal("run_single_script", get_selected_index())
|
|
|
|
|
|
func _on_ScriptsList_item_selected(index):
|
|
var tmr = $ScriptsList/DoubleClickTimer
|
|
if !tmr.is_stopped():
|
|
_run_mode()
|
|
emit_signal("run_single_script", get_selected_index())
|
|
tmr.stop()
|
|
else:
|
|
tmr.start()
|
|
|
|
_select_script(index)
|
|
|
|
|
|
func _on_TitleBar_mouse_entered():
|
|
_mouse.in_title = true
|
|
|
|
|
|
func _on_TitleBar_mouse_exited():
|
|
_mouse.in_title = false
|
|
|
|
|
|
func _input(event):
|
|
if event is InputEventMouseButton:
|
|
if event.button_index == 1:
|
|
_mouse.down = event.pressed
|
|
if _mouse.down:
|
|
_mouse.down_pos = event.position
|
|
|
|
if _mouse.in_title:
|
|
if event is InputEventMouseMotion and _mouse.down:
|
|
set_position(get_position() + (event.position - _mouse.down_pos))
|
|
_mouse.down_pos = event.position
|
|
_pre_maximize_rect = get_rect()
|
|
|
|
if _mouse.in_handle:
|
|
if event is InputEventMouseMotion and _mouse.down:
|
|
var new_size = size + event.position - _mouse.down_pos
|
|
var new_mouse_down_pos = event.position
|
|
size = new_size
|
|
_mouse.down_pos = new_mouse_down_pos
|
|
_pre_maximize_rect = get_rect()
|
|
|
|
|
|
func _on_ResizeHandle_mouse_entered():
|
|
_mouse.in_handle = true
|
|
|
|
|
|
func _on_ResizeHandle_mouse_exited():
|
|
_mouse.in_handle = false
|
|
|
|
|
|
func _on_RichTextLabel_gui_input(ev):
|
|
pass
|
|
# leaving this b/c it is wired up and might have to send
|
|
# more signals through
|
|
|
|
|
|
func _on_Copy_pressed():
|
|
OS.clipboard = _text_box.text
|
|
|
|
|
|
func _on_ShowExtras_toggled(button_pressed):
|
|
_extras.visible = button_pressed
|
|
|
|
|
|
func _on_Maximize_pressed():
|
|
if get_rect() == _pre_maximize_rect:
|
|
compact_mode(false)
|
|
maximize()
|
|
else:
|
|
compact_mode(false)
|
|
size = _pre_maximize_rect.size
|
|
position = _pre_maximize_rect.position
|
|
|
|
|
|
func _on_Minimize_pressed():
|
|
compact_mode(!_compact_mode)
|
|
|
|
|
|
func _on_Minimize_draw():
|
|
# draw the maximize square thing.
|
|
var btn = $VBox/TitleBar/HBox/Minimize
|
|
btn.set_text("")
|
|
var w = btn.get_size().x
|
|
var h = btn.get_size().y
|
|
btn.draw_rect(Rect2(0, h - 3, w, 3), Color(0, 0, 0, 1))
|
|
|
|
|
|
func _on_UserFiles_pressed():
|
|
_user_files.show_open()
|
|
|
|
|
|
# ####################
|
|
# Private
|
|
# ####################
|
|
func _run_mode(is_running = true):
|
|
if is_running:
|
|
_start_time = Time.get_ticks_msec()
|
|
_time = 0.0
|
|
clear_summary()
|
|
_is_running = is_running
|
|
|
|
_hide_scripts()
|
|
_nav.prev.disabled = is_running
|
|
_nav.next.disabled = is_running
|
|
_nav.run.disabled = is_running
|
|
_nav.current_script.disabled = is_running
|
|
_nav.run_single.disabled = is_running
|
|
|
|
|
|
func _select_script(index):
|
|
var text = _script_list.get_item_text(index)
|
|
var max_len = 50
|
|
if text.length() > max_len:
|
|
text = "..." + text.right(text.length() - (max_len - 5))
|
|
_nav.current_script.set_text(text)
|
|
_script_list.select(index)
|
|
_update_controls()
|
|
|
|
|
|
func _toggle_scripts():
|
|
if _script_list.visible:
|
|
_hide_scripts()
|
|
else:
|
|
_show_scripts()
|
|
|
|
|
|
func _show_scripts():
|
|
_script_list.show()
|
|
|
|
|
|
func _hide_scripts():
|
|
_script_list.hide()
|
|
|
|
|
|
func _update_controls():
|
|
var is_empty = _script_list.get_selected_items().size() == 0
|
|
if is_empty:
|
|
_nav.next.disabled = true
|
|
_nav.prev.disabled = true
|
|
else:
|
|
var index = get_selected_index()
|
|
_nav.prev.disabled = index <= 0
|
|
_nav.next.disabled = index >= _script_list.get_item_count() - 1
|
|
|
|
_nav.run.disabled = is_empty
|
|
_nav.current_script.disabled = is_empty
|
|
_nav.run_single.disabled = is_empty
|
|
|
|
|
|
func _update_summary():
|
|
if !_summary:
|
|
return
|
|
|
|
var total = _summary.fail_count + _summary.pass_count
|
|
_summary.control.visible = !total == 0
|
|
_summary.asserts.text = str("Failures ", _summary.fail_count, "/", total)
|
|
|
|
|
|
# ####################
|
|
# Public
|
|
# ####################
|
|
func run_mode(is_running = true):
|
|
_run_mode(is_running)
|
|
|
|
|
|
func set_scripts(scripts):
|
|
_script_list.clear()
|
|
for i in range(scripts.size()):
|
|
_script_list.add_item(scripts[i])
|
|
_select_script(0)
|
|
_update_controls()
|
|
|
|
|
|
func select_script(index):
|
|
_select_script(index)
|
|
|
|
|
|
func get_selected_index():
|
|
return _script_list.get_selected_items()[0]
|
|
|
|
|
|
func get_log_level():
|
|
return _log_level_slider.value
|
|
|
|
|
|
func set_log_level(value):
|
|
var new_value = value
|
|
if new_value == null:
|
|
new_value = 0
|
|
# !! For some reason, _log_level_slider was null, but this wasn't, so
|
|
# here's another hardcoded node path.
|
|
$VBox/BottomPanel/VBox/HBox2/LogLevelSlider.value = new_value
|
|
|
|
|
|
func set_ignore_pause(should):
|
|
_ignore_pauses.button_pressed = should
|
|
|
|
|
|
func get_ignore_pause():
|
|
return _ignore_pauses.pressed
|
|
|
|
|
|
func get_text_box():
|
|
# due to some timing issue, this cannot return _text_box but can return
|
|
# this.
|
|
return $VBox/TextDisplay/RichTextLabel
|
|
|
|
|
|
func end_run():
|
|
_run_mode(false)
|
|
_update_controls()
|
|
|
|
|
|
func set_progress_script_max(value):
|
|
var max_val = max(value, 1)
|
|
_progress.script.set_max(max_val)
|
|
_progress.script_xy.set_text(str("0/", max_val))
|
|
|
|
|
|
func set_progress_script_value(value):
|
|
_progress.script.set_value(value)
|
|
var txt = str(value, "/", _progress.test.get_max())
|
|
_progress.script_xy.set_text(txt)
|
|
|
|
|
|
func set_progress_test_max(value):
|
|
var max_val = max(value, 1)
|
|
_progress.test.set_max(max_val)
|
|
_progress.test_xy.set_text(str("0/", max_val))
|
|
|
|
|
|
func set_progress_test_value(value):
|
|
_progress.test.set_value(value)
|
|
var txt = str(value, "/", _progress.test.get_max())
|
|
_progress.test_xy.set_text(txt)
|
|
|
|
|
|
func clear_progress():
|
|
_progress.test.set_value(0)
|
|
_progress.script.set_value(0)
|
|
|
|
|
|
func pause():
|
|
_continue_button.disabled = false
|
|
|
|
|
|
func set_title(title = null):
|
|
if title == null:
|
|
_titlebar.label.set_text(DEFAULT_TITLE)
|
|
else:
|
|
_titlebar.label.set_text(title)
|
|
|
|
|
|
func add_passing(amount = 1):
|
|
if !_summary:
|
|
return
|
|
_summary.pass_count += amount
|
|
_update_summary()
|
|
|
|
|
|
func add_failing(amount = 1):
|
|
if !_summary:
|
|
return
|
|
_summary.fail_count += amount
|
|
_update_summary()
|
|
|
|
|
|
func clear_summary():
|
|
_summary.fail_count = 0
|
|
_summary.pass_count = 0
|
|
_update_summary()
|
|
|
|
|
|
func maximize():
|
|
if is_inside_tree():
|
|
var vp_size_offset = get_tree().root.get_viewport().get_visible_rect().size
|
|
size = vp_size_offset / get_scale()
|
|
set_position(Vector2(0, 0))
|
|
|
|
|
|
func clear_text():
|
|
_text_box.text = ""
|
|
|
|
|
|
func scroll_to_bottom():
|
|
pass
|
|
#_text_box.set_caret_line(_gui.get_text_box().get_line_count())
|
|
|
|
|
|
func _set_font_size_for_rtl(rtl, new_size):
|
|
if rtl.get("custom_fonts/normal_font") != null:
|
|
rtl.get("custom_fonts/bold_italics_font").size = new_size
|
|
rtl.get("custom_fonts/bold_font").size = new_size
|
|
rtl.get("custom_fonts/italics_font").size = new_size
|
|
rtl.get("custom_fonts/normal_font").size = new_size
|
|
|
|
|
|
func _set_fonts_for_rtl(rtl, base_font_name):
|
|
pass
|
|
|
|
|
|
func set_font_size(new_size):
|
|
_font_size = new_size
|
|
_set_font_size_for_rtl(_text_box, new_size)
|
|
_set_font_size_for_rtl(_user_files.get_rich_text_label(), new_size)
|
|
|
|
|
|
func _set_font(rtl, font_name, custom_name):
|
|
if font_name == null:
|
|
rtl.set("custom_fonts/" + custom_name, null)
|
|
else:
|
|
var dyn_font = preload("res://addons/godot_xterm/themes/fonts/regular.tres").duplicate()
|
|
rtl.set("custom_fonts/" + custom_name, dyn_font)
|
|
|
|
|
|
func _set_all_fonts_in_ftl(ftl, base_name):
|
|
if base_name == "Default":
|
|
_set_font(ftl, null, "normal_font")
|
|
_set_font(ftl, null, "bold_font")
|
|
_set_font(ftl, null, "italics_font")
|
|
_set_font(ftl, null, "bold_italics_font")
|
|
else:
|
|
_set_font(ftl, base_name + "-Regular", "normal_font")
|
|
_set_font(ftl, base_name + "-Bold", "bold_font")
|
|
_set_font(ftl, base_name + "-Italic", "italics_font")
|
|
_set_font(ftl, base_name + "-BoldItalic", "bold_italics_font")
|
|
set_font_size(_font_size)
|
|
|
|
|
|
func set_font(base_name):
|
|
_set_all_fonts_in_ftl(_text_box, base_name)
|
|
_set_all_fonts_in_ftl(_user_files.get_rich_text_label(), base_name)
|
|
|
|
|
|
func set_default_font_color(color):
|
|
_text_box.set("custom_colors/default_color", color)
|
|
|
|
|
|
func set_background_color(color):
|
|
_text_box_container.color = color
|
|
|
|
|
|
func get_waiting_label():
|
|
return $VBox/TextDisplay/WaitingLabel
|
|
|
|
|
|
func compact_mode(should):
|
|
if _compact_mode == should:
|
|
return
|
|
|
|
_compact_mode = should
|
|
_text_box_container.visible = !should
|
|
_nav.container.visible = !should
|
|
_log_level_slider.visible = !should
|
|
$VBox/BottomPanel/VBox/HBox/Continue/ShowExtras.visible = !should
|
|
_titlebar.label.visible = !should
|
|
_resize_handle.visible = !should
|
|
_current_script.visible = !should
|
|
_title_replacement.visible = should
|
|
|
|
if should:
|
|
minimum_size = min_sizes.compact
|
|
size = minimum_size
|
|
else:
|
|
minimum_size = min_sizes.full
|
|
size = min_sizes.full
|
|
|
|
goto_bottom_right_corner()
|
|
|
|
|
|
func set_script_path(text):
|
|
_current_script.text = text
|
|
|
|
|
|
func goto_bottom_right_corner():
|
|
position = get_tree().root.get_viewport().get_visible_rect().size - size
|