diff options
| author | Sophia Pearson <codergal89@gmail.com> | 2022-09-05 20:35:53 +0200 |
|---|---|---|
| committer | Sophia Pearson <codergal89@gmail.com> | 2022-09-05 20:35:53 +0200 |
| commit | f20bd89dc4a7bf14a88b1effcaa1887b29314525 (patch) | |
| tree | d114787f68efd2a7d61d95fa9c84e8e5d69a7c11 /addons/gut/gui | |
| parent | 1b477b62f8be8c546a35dbd1d2688ebf623c496f (diff) | |
| download | texty-f20bd89dc4a7bf14a88b1effcaa1887b29314525.tar.xz texty-f20bd89dc4a7bf14a88b1effcaa1887b29314525.zip | |
gui: split GUI into Terminal components
Diffstat (limited to 'addons/gut/gui')
| -rw-r--r-- | addons/gut/gui/GutBottomPanel.gd | 230 | ||||
| -rw-r--r-- | addons/gut/gui/GutBottomPanel.tscn | 193 | ||||
| -rw-r--r-- | addons/gut/gui/GutRunner.gd | 9 | ||||
| -rw-r--r-- | addons/gut/gui/OutputText.gd | 291 | ||||
| -rw-r--r-- | addons/gut/gui/OutputText.tscn | 123 | ||||
| -rw-r--r-- | addons/gut/gui/RunAtCursor.gd | 63 | ||||
| -rw-r--r-- | addons/gut/gui/RunResults.gd | 509 | ||||
| -rw-r--r-- | addons/gut/gui/RunResults.tscn | 165 | ||||
| -rw-r--r-- | addons/gut/gui/arrow.png | 4 | ||||
| -rw-r--r-- | addons/gut/gui/gut_config_gui.gd | 7 | ||||
| -rw-r--r-- | addons/gut/gui/play.png | 4 |
11 files changed, 1376 insertions, 222 deletions
diff --git a/addons/gut/gui/GutBottomPanel.gd b/addons/gut/gui/GutBottomPanel.gd index 50a32d8..e7b5037 100644 --- a/addons/gut/gui/GutBottomPanel.gd +++ b/addons/gut/gui/GutBottomPanel.gd @@ -8,6 +8,7 @@ const SHORTCUTS_PATH = 'res://.gut_editor_shortcuts.cfg' var TestScript = load('res://addons/gut/test.gd') var GutConfigGui = load('res://addons/gut/gui/gut_config_gui.gd') +var ScriptTextEditors = load('res://addons/gut/gui/script_text_editor_controls.gd') var _interface = null; var _is_running = false; @@ -20,12 +21,20 @@ var _last_selected_path = null onready var _ctrls = { - output = $layout/RSplit/CResults/Output, + output = $layout/RSplit/CResults/Tabs/OutputText.get_rich_text_edit(), + output_ctrl = $layout/RSplit/CResults/Tabs/OutputText, run_button = $layout/ControlBar/RunAll, + shortcuts_button = $layout/ControlBar/Shortcuts, + + settings_button = $layout/ControlBar/Settings, + run_results_button = $layout/ControlBar/RunResultsBtn, + output_button = $layout/ControlBar/OutputBtn, + settings = $layout/RSplit/sc/Settings, shortcut_dialog = $BottomPanelShortcuts, light = $layout/RSplit/CResults/ControlBar/Light, results = { + bar = $layout/RSplit/CResults/ControlBar, passing = $layout/RSplit/CResults/ControlBar/Passing/value, failing = $layout/RSplit/CResults/ControlBar/Failing/value, pending = $layout/RSplit/CResults/ControlBar/Pending/value, @@ -33,7 +42,8 @@ onready var _ctrls = { warnings = $layout/RSplit/CResults/ControlBar/Warnings/value, orphans = $layout/RSplit/CResults/ControlBar/Orphans/value }, - run_at_cursor = $layout/ControlBar/RunAtCursor + run_at_cursor = $layout/ControlBar/RunAtCursor, + run_results = $layout/RSplit/CResults/Tabs/RunResults } @@ -42,17 +52,51 @@ func _init(): func _ready(): + _ctrls.results.bar.connect('draw', self, '_on_results_bar_draw', [_ctrls.results.bar]) + hide_settings(!_ctrls.settings_button.pressed) _gut_config_gui = GutConfigGui.new(_ctrls.settings) _gut_config_gui.set_options(_gut_config.options) - _set_all_fonts_in_ftl(_ctrls.output, _gut_config.options.panel_options.font_name) - _set_font_size_for_rtl(_ctrls.output, _gut_config.options.panel_options.font_size) + + _apply_options_to_controls() + + _ctrls.shortcuts_button.icon = get_icon('ShortCut', 'EditorIcons') + _ctrls.settings_button.icon = get_icon('Tools', 'EditorIcons') + _ctrls.run_results_button.icon = get_icon('AnimationTrackGroup', 'EditorIcons') # Tree + _ctrls.output_button.icon = get_icon('Font', 'EditorIcons') + + _ctrls.run_results.set_output_control(_ctrls.output_ctrl) + _ctrls.run_results.set_font( + _gut_config.options.panel_options.font_name, + _gut_config.options.panel_options.font_size) + + var check_import = load('res://addons/gut/images/red.png') + if(check_import == null): + _ctrls.run_results.add_centered_text("GUT got some new images that are not imported yet. Please restart Godot.") + print('GUT got some new images that are not imported yet. Please restart Godot.') + else: + _ctrls.run_results.add_centered_text("Let's run some tests!") + + +func _apply_options_to_controls(): + hide_settings(_gut_config.options.panel_options.hide_settings) + hide_result_tree(_gut_config.options.panel_options.hide_result_tree) + hide_output_text(_gut_config.options.panel_options.hide_output_text) + + _ctrls.output_ctrl.set_use_colors(_gut_config.options.panel_options.use_colors) + _ctrls.output_ctrl.set_all_fonts(_gut_config.options.panel_options.font_name) + _ctrls.output_ctrl.set_font_size(_gut_config.options.panel_options.font_size) + + _ctrls.run_results.set_font( + _gut_config.options.panel_options.font_name, + _gut_config.options.panel_options.font_size) + _ctrls.run_results.set_show_orphans(!_gut_config.options.hide_orphans) func _process(delta): if(_is_running): if(!_interface.is_playing_scene()): _is_running = false - _ctrls.output.add_text("\ndone") + _ctrls.output_ctrl.add_text("\ndone") load_result_output() _gut_plugin.make_bottom_panel_item_visible(self) @@ -65,41 +109,6 @@ func load_shortcuts(): _apply_shortcuts() -# ----------------------------------- -func _set_font(rtl, font_name, custom_name): - if(font_name == null): - rtl.set('custom_fonts/' + custom_name, null) - else: - var dyn_font = DynamicFont.new() - var font_data = DynamicFontData.new() - font_data.font_path = 'res://addons/gut/fonts/' + font_name + '.ttf' - font_data.antialiased = true - dyn_font.font_data = font_data - 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') - - -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 _is_test_script(script): var from = script.get_base_script() while(from and from.resource_path != 'res://addons/gut/test.gd'): @@ -108,27 +117,28 @@ func _is_test_script(script): return from != null -func _update_last_run_label(): - var text = '' - - if( _gut_config.options.selected == null and - _gut_config.options.inner_class == null and - _gut_config.options.unit_test_name == null): - text = 'All' - else: - text = nvl(_gut_config.options.selected, '') + ' ' - text += nvl(_gut_config.options.inner_class, '') + ' ' - text += nvl(_gut_config.options.unit_test_name, '') - - - func _show_errors(errs): - _ctrls.output.clear() - var text = "Cannot run tests, you have a conrfiguration error:\n" + _ctrls.output_ctrl.clear() + var text = "Cannot run tests, you have a configuration error:\n" for e in errs: text += str('* ', e, "\n") - text += "[right]Check your settings here ----->[/right]" - _ctrls.output.bbcode_text = text + text += "Check your settings ----->" + _ctrls.output_ctrl.add_text(text) + hide_output_text(false) + hide_settings(false) + + +func _save_config(): + _gut_config.options = _gut_config_gui.get_options(_gut_config.options) + _gut_config.options.panel_options.hide_settings = !_ctrls.settings_button.pressed + _gut_config.options.panel_options.hide_result_tree = !_ctrls.run_results_button.pressed + _gut_config.options.panel_options.hide_output_text = !_ctrls.output_button.pressed + _gut_config.options.panel_options.use_colors = _ctrls.output_ctrl.get_use_colors() + + var w_result = _gut_config.write_options(RUNNER_JSON_PATH) + if(w_result != OK): + push_error(str('Could not write options to ', RUNNER_JSON_PATH, ': ', w_result)) + return; func _run_tests(): @@ -138,22 +148,16 @@ func _run_tests(): return write_file(RESULT_FILE, 'Run in progress') - _gut_config.options = _gut_config_gui.get_options(_gut_config.options) - _set_all_fonts_in_ftl(_ctrls.output, _gut_config.options.panel_options.font_name) - _set_font_size_for_rtl(_ctrls.output, _gut_config.options.panel_options.font_size) + _save_config() + _apply_options_to_controls() - var w_result = _gut_config.write_options(RUNNER_JSON_PATH) - if(w_result != OK): - push_error(str('Could not write options to ', RUNNER_JSON_PATH, ': ', w_result)) - return; - - _ctrls.output.clear() + _ctrls.output_ctrl.clear() + _ctrls.run_results.clear() + _ctrls.run_results.add_centered_text('Running...') - _update_last_run_label() _interface.play_custom_scene('res://addons/gut/gui/GutRunner.tscn') - _is_running = true - _ctrls.output.add_text('running...') + _ctrls.output_ctrl.add_text('Running...') func _apply_shortcuts(): @@ -180,27 +184,24 @@ func _run_all(): # --------------- # Events # --------------- +func _on_results_bar_draw(bar): + bar.draw_rect(Rect2(Vector2(0, 0), bar.rect_size), Color(0, 0, 0, .2)) + + +func _on_Light_draw(): + var l = _ctrls.light + l.draw_circle(Vector2(l.rect_size.x / 2, l.rect_size.y / 2), l.rect_size.x / 2, _light_color) + + func _on_editor_script_changed(script): if(script): set_current_script(script) func _on_RunAll_pressed(): - _on_RunTests_pressed() - - -func _on_RunTests_pressed(): _run_all() -func _on_CopyButton_pressed(): - OS.clipboard = _ctrls.output.text - - -func _on_ClearButton_pressed(): - _ctrls.output.clear() - - func _on_Shortcuts_pressed(): _ctrls.shortcut_dialog.popup_centered() @@ -210,11 +211,6 @@ func _on_BottomPanelShortcuts_popup_hide(): _ctrls.shortcut_dialog.save_shortcuts(SHORTCUTS_PATH) -func _on_Light_draw(): - var l = _ctrls.light - l.draw_circle(Vector2(l.rect_size.x / 2, l.rect_size.y / 2), l.rect_size.x / 2, _light_color) - - func _on_RunAtCursor_run_tests(what): _gut_config.options.selected = what.script _gut_config.options.inner_class = what.inner_class @@ -223,19 +219,64 @@ func _on_RunAtCursor_run_tests(what): _run_tests() +func _on_Settings_pressed(): + hide_settings(!_ctrls.settings_button.pressed) + _save_config() + + +func _on_OutputBtn_pressed(): + hide_output_text(!_ctrls.output_button.pressed) + _save_config() + + +func _on_RunResultsBtn_pressed(): + hide_result_tree(! _ctrls.run_results_button.pressed) + _save_config() + + +# Currently not used, but will be when I figure out how to put +# colors into the text results +func _on_UseColors_pressed(): + pass + # --------------- # Public # --------------- +func hide_result_tree(should): + _ctrls.run_results.visible = !should + _ctrls.run_results_button.pressed = !should + + +func hide_settings(should): + var s_scroll = _ctrls.settings.get_parent() + s_scroll.visible = !should + + # collapse only collapses the first control, so we move + # settings around to be the collapsed one + if(should): + s_scroll.get_parent().move_child(s_scroll, 0) + else: + s_scroll.get_parent().move_child(s_scroll, 1) + + $layout/RSplit.collapsed = should + _ctrls.settings_button.pressed = !should + + +func hide_output_text(should): + $layout/RSplit/CResults/Tabs/OutputText.visible = !should + _ctrls.output_button.pressed = !should + func load_result_output(): - _ctrls.output.bbcode_text = get_file_as_text(RESULT_FILE) - _ctrls.output.grab_focus() - _ctrls.output.scroll_to_line(_ctrls.output.get_line_count() -1) + _ctrls.output_ctrl.load_file(RESULT_FILE) var summary = get_file_as_text(RESULT_JSON) var results = JSON.parse(summary) if(results.error != OK): return + + _ctrls.run_results.load_json_results(results.result) + var summary_json = results.result['test_scripts']['props'] _ctrls.results.passing.text = str(summary_json.passing) _ctrls.results.passing.get_parent().visible = true @@ -263,10 +304,10 @@ func load_result_output(): _light_color = Color(1, 1, 0, .75) else: _light_color = Color(0, 1, 0, .75) + _ctrls.light.visible = true _ctrls.light.update() - func set_current_script(script): if(script): if(_is_test_script(script)): @@ -278,7 +319,11 @@ func set_current_script(script): func set_interface(value): _interface = value _interface.get_script_editor().connect("editor_script_changed", self, '_on_editor_script_changed') - _ctrls.run_at_cursor.set_script_editor(_interface.get_script_editor()) + + var ste = ScriptTextEditors.new(_interface.get_script_editor()) + _ctrls.run_results.set_interface(_interface) + _ctrls.run_results.set_script_text_editors(ste) + _ctrls.run_at_cursor.set_script_text_editors(ste) set_current_script(_interface.get_script_editor().get_current_script()) @@ -323,4 +368,3 @@ func nvl(value, if_null): else: return value - diff --git a/addons/gut/gui/GutBottomPanel.tscn b/addons/gut/gui/GutBottomPanel.tscn index 0bb7fc3..7ec6649 100644 --- a/addons/gut/gui/GutBottomPanel.tscn +++ b/addons/gut/gui/GutBottomPanel.tscn @@ -1,9 +1,11 @@ -[gd_scene load_steps=16 format=2] +[gd_scene load_steps=11 format=2] [ext_resource path="res://addons/gut/gui/GutBottomPanel.gd" type="Script" id=1] [ext_resource path="res://addons/gut/gui/BottomPanelShortcuts.tscn" type="PackedScene" id=2] [ext_resource path="res://addons/gut/gui/RunAtCursor.tscn" type="PackedScene" id=3] [ext_resource path="res://addons/gut/gui/play.png" type="Texture" id=4] +[ext_resource path="res://addons/gut/gui/RunResults.tscn" type="PackedScene" id=5] +[ext_resource path="res://addons/gut/gui/OutputText.tscn" type="PackedScene" id=6] [sub_resource type="InputEventKey" id=8] control = true @@ -12,35 +14,20 @@ scancode = 49 [sub_resource type="ShortCut" id=9] shortcut = SubResource( 8 ) -[sub_resource type="StyleBoxEmpty" id=5] - -[sub_resource type="DynamicFontData" id=10] -font_path = "res://addons/gut/fonts/CourierPrime-BoldItalic.ttf" - -[sub_resource type="DynamicFont" id=11] -size = 30 -font_data = SubResource( 10 ) - -[sub_resource type="DynamicFontData" id=12] -font_path = "res://addons/gut/fonts/CourierPrime-Italic.ttf" - -[sub_resource type="DynamicFont" id=13] -size = 30 -font_data = SubResource( 12 ) - -[sub_resource type="DynamicFontData" id=14] -font_path = "res://addons/gut/fonts/CourierPrime-Bold.ttf" - -[sub_resource type="DynamicFont" id=15] -size = 30 -font_data = SubResource( 14 ) - -[sub_resource type="DynamicFontData" id=16] -font_path = "res://addons/gut/fonts/CourierPrime-Regular.ttf" +[sub_resource type="Image" id=10] +data = { +"data": PoolByteArray( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), +"format": "LumAlpha8", +"height": 16, +"mipmaps": false, +"width": 16 +} -[sub_resource type="DynamicFont" id=17] -size = 30 -font_data = SubResource( 16 ) +[sub_resource type="ImageTexture" id=2] +flags = 4 +flags = 4 +image = SubResource( 10 ) +size = Vector2( 16, 16 ) [node name="GutBottomPanel" type="Control"] anchor_left = -0.0025866 @@ -53,9 +40,6 @@ margin_right = 2.64862 margin_bottom = 1.05945 rect_min_size = Vector2( 0, 300 ) script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} [node name="layout" type="VBoxContainer" parent="."] anchor_right = 1.0 @@ -89,16 +73,16 @@ margin_left = 154.0 margin_top = 13.0 margin_right = 213.0 margin_bottom = 27.0 -hint_tooltip = "When a test script is edited, buttons are displayed to -run the opened script or an Inner-Test-Class or a -single test. The buttons change based on the location +hint_tooltip = "When a test script is edited, buttons are displayed to +run the opened script or an Inner-Test-Class or a +single test. The buttons change based on the location of the cursor in the file. -These buttons will remain active when editing other -items so that you can run tests without having to switch +These buttons will remain active when editing other +items so that you can run tests without having to switch back to the test script. -You can assign keyboard shortcuts for these buttons +You can assign keyboard shortcuts for these buttons using the \"shortcuts\" button in the GUT panel." mouse_filter = 1 text = "Current: " @@ -107,39 +91,61 @@ text = "Current: " anchor_right = 0.0 anchor_bottom = 0.0 margin_left = 217.0 -margin_right = 456.0 +margin_right = 548.0 margin_bottom = 40.0 rect_min_size = Vector2( 0, 40 ) [node name="CenterContainer2" type="CenterContainer" parent="layout/ControlBar"] -margin_left = 460.0 -margin_right = 699.0 +margin_left = 552.0 +margin_right = 883.0 margin_bottom = 40.0 size_flags_horizontal = 3 -[node name="FocusButton" type="Button" parent="layout/ControlBar"] -show_behind_parent = true -margin_left = 703.0 -margin_right = 703.0 +[node name="Sep1" type="ColorRect" parent="layout/ControlBar"] +margin_left = 887.0 +margin_right = 889.0 margin_bottom = 40.0 -custom_styles/normal = SubResource( 5 ) -__meta__ = { -"_edit_use_anchors_": false -} +rect_min_size = Vector2( 2, 0 ) -[node name="CenterContainer" type="CenterContainer" parent="layout/ControlBar"] -margin_left = 707.0 -margin_right = 946.0 +[node name="RunResultsBtn" type="ToolButton" parent="layout/ControlBar"] +margin_left = 893.0 +margin_right = 921.0 margin_bottom = 40.0 -size_flags_horizontal = 3 +hint_tooltip = "Show/Hide Results Tree Panel." +toggle_mode = true +pressed = true +icon = SubResource( 2 ) + +[node name="OutputBtn" type="ToolButton" parent="layout/ControlBar"] +margin_left = 925.0 +margin_right = 953.0 +margin_bottom = 40.0 +hint_tooltip = "Show/Hide Output Panel." +toggle_mode = true +pressed = true +icon = SubResource( 2 ) + +[node name="Settings" type="ToolButton" parent="layout/ControlBar"] +margin_left = 957.0 +margin_right = 985.0 +margin_bottom = 40.0 +hint_tooltip = "Show/Hide Settings Panel." +toggle_mode = true +icon = SubResource( 2 ) -[node name="Shortcuts" type="Button" parent="layout/ControlBar"] -margin_left = 950.0 -margin_right = 1022.0 +[node name="Sep2" type="ColorRect" parent="layout/ControlBar"] +margin_left = 989.0 +margin_right = 991.0 +margin_bottom = 40.0 +rect_min_size = Vector2( 2, 0 ) + +[node name="Shortcuts" type="ToolButton" parent="layout/ControlBar"] +margin_left = 995.0 +margin_right = 1023.0 margin_bottom = 40.0 hint_tooltip = "Set shortcuts for GUT buttons. Shortcuts do not work when the GUT panel is not visible." size_flags_vertical = 11 -text = "Shortcuts" +icon = SubResource( 2 ) [node name="RSplit" type="HSplitContainer" parent="layout"] margin_top = 44.0 @@ -147,19 +153,36 @@ margin_right = 1023.0 margin_bottom = 599.0 size_flags_horizontal = 3 size_flags_vertical = 3 +collapsed = true + +[node name="sc" type="ScrollContainer" parent="layout/RSplit"] +visible = false +margin_left = 593.0 +margin_right = 1093.0 +margin_bottom = 555.0 +rect_min_size = Vector2( 500, 0 ) +mouse_filter = 1 +size_flags_vertical = 3 + +[node name="Settings" type="VBoxContainer" parent="layout/RSplit/sc"] +margin_right = 500.0 +margin_bottom = 908.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 [node name="CResults" type="VBoxContainer" parent="layout/RSplit"] -margin_right = 611.0 +margin_right = 1023.0 margin_bottom = 555.0 size_flags_horizontal = 3 size_flags_vertical = 3 [node name="ControlBar" type="HBoxContainer" parent="layout/RSplit/CResults"] -margin_right = 611.0 +margin_right = 1023.0 margin_bottom = 35.0 rect_min_size = Vector2( 0, 35 ) [node name="Light" type="Control" parent="layout/RSplit/CResults/ControlBar"] +visible = false margin_right = 30.0 margin_bottom = 35.0 rect_min_size = Vector2( 30, 30 ) @@ -319,52 +342,28 @@ margin_bottom = 24.0 text = "---" [node name="CenterContainer" type="CenterContainer" parent="layout/RSplit/CResults/ControlBar"] -margin_left = 34.0 -margin_right = 488.0 +margin_right = 1023.0 margin_bottom = 35.0 size_flags_horizontal = 3 -[node name="CopyButton" type="Button" parent="layout/RSplit/CResults/ControlBar"] -margin_left = 492.0 -margin_right = 547.0 -margin_bottom = 35.0 -text = " Copy " - -[node name="ClearButton" type="Button" parent="layout/RSplit/CResults/ControlBar"] -margin_left = 551.0 -margin_right = 611.0 -margin_bottom = 35.0 -text = " Clear " - -[node name="Output" type="RichTextLabel" parent="layout/RSplit/CResults"] +[node name="Tabs" type="HSplitContainer" parent="layout/RSplit/CResults"] margin_top = 39.0 -margin_right = 611.0 -margin_bottom = 555.0 -focus_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -custom_fonts/bold_italics_font = SubResource( 11 ) -custom_fonts/italics_font = SubResource( 13 ) -custom_fonts/bold_font = SubResource( 15 ) -custom_fonts/normal_font = SubResource( 17 ) -bbcode_enabled = true -scroll_following = true -selection_enabled = true - -[node name="sc" type="ScrollContainer" parent="layout/RSplit"] -margin_left = 623.0 margin_right = 1023.0 margin_bottom = 555.0 -rect_min_size = Vector2( 400, 0 ) -mouse_filter = 1 +size_flags_horizontal = 3 size_flags_vertical = 3 -[node name="Settings" type="VBoxContainer" parent="layout/RSplit/sc"] -margin_right = 388.0 -margin_bottom = 862.0 +[node name="RunResults" parent="layout/RSplit/CResults/Tabs" instance=ExtResource( 5 )] +margin_right = 505.0 +margin_bottom = 516.0 size_flags_horizontal = 3 size_flags_vertical = 3 +[node name="OutputText" parent="layout/RSplit/CResults/Tabs" instance=ExtResource( 6 )] +margin_left = 517.0 +margin_right = 1023.0 +margin_bottom = 516.0 + [node name="BottomPanelShortcuts" parent="." instance=ExtResource( 2 )] visible = false anchor_left = -0.000517324 @@ -378,9 +377,9 @@ margin_bottom = -125.552 [connection signal="pressed" from="layout/ControlBar/RunAll" to="." method="_on_RunAll_pressed"] [connection signal="run_tests" from="layout/ControlBar/RunAtCursor" to="." method="_on_RunAtCursor_run_tests"] -[connection signal="pressed" from="layout/ControlBar/FocusButton" to="." method="_on_FocusButton_pressed"] +[connection signal="pressed" from="layout/ControlBar/RunResultsBtn" to="." method="_on_RunResultsBtn_pressed"] +[connection signal="pressed" from="layout/ControlBar/OutputBtn" to="." method="_on_OutputBtn_pressed"] +[connection signal="pressed" from="layout/ControlBar/Settings" to="." method="_on_Settings_pressed"] [connection signal="pressed" from="layout/ControlBar/Shortcuts" to="." method="_on_Shortcuts_pressed"] [connection signal="draw" from="layout/RSplit/CResults/ControlBar/Light" to="." method="_on_Light_draw"] -[connection signal="pressed" from="layout/RSplit/CResults/ControlBar/CopyButton" to="." method="_on_CopyButton_pressed"] -[connection signal="pressed" from="layout/RSplit/CResults/ControlBar/ClearButton" to="." method="_on_ClearButton_pressed"] [connection signal="popup_hide" from="BottomPanelShortcuts" to="." method="_on_BottomPanelShortcuts_popup_hide"] diff --git a/addons/gut/gui/GutRunner.gd b/addons/gut/gui/GutRunner.gd index b2b16f2..608fc26 100644 --- a/addons/gut/gui/GutRunner.gd +++ b/addons/gut/gui/GutRunner.gd @@ -22,8 +22,7 @@ onready var _gut_layer = $GutLayer func _ready(): if(_gut_config == null): _gut_config = GutConfig.new() - _gut_config.load_options(RUNNER_JSON_PATH) - + _gut_config.load_panel_options(RUNNER_JSON_PATH) # The command line will call run_tests on its own. When used from the panel # we have to kick off the tests ourselves b/c there's no way I know of to @@ -55,9 +54,7 @@ func run_tests(): func _write_results(): - # bbcode_text appears to be empty. I'm not 100% sure why. Until that is - # figured out we have to just get the text which stinks. - var content = _gut.get_gui().get_text_box().text + var content = _gut.get_logger().get_gui_bbcode() var f = File.new() var result = f.open(RESULT_FILE, f.WRITE) @@ -68,7 +65,7 @@ func _write_results(): print('ERROR Could not save bbcode, result = ', result) var exporter = ResultExporter.new() - var f_result = exporter.write_summary_file(_gut, RESULT_JSON) + var f_result = exporter.write_json_file(_gut, RESULT_JSON) _wrote_results = true diff --git a/addons/gut/gui/OutputText.gd b/addons/gut/gui/OutputText.gd new file mode 100644 index 0000000..e5cf2b6 --- /dev/null +++ b/addons/gut/gui/OutputText.gd @@ -0,0 +1,291 @@ +extends VBoxContainer +tool + +class SearchResults: + const L = TextEdit.SEARCH_RESULT_LINE + const C = TextEdit.SEARCH_RESULT_COLUMN + + var positions = [] + var te = null + var _last_term = '' + + func _search_te(text, start_position, flags=0): + var start_pos = start_position + if(start_pos[L] < 0 or start_pos[L] > te.get_line_count()): + start_pos[L] = 0 + if(start_pos[C] < 0): + start_pos[L] = 0 + + var result = te.search(text, flags, start_pos[L], start_pos[C]) + if(result.size() == 2 and result[L] == start_position[L] and + result[C] == start_position[C] and text == _last_term): + if(flags == TextEdit.SEARCH_BACKWARDS): + result[C] -= 1 + else: + result[C] += 1 + result = _search_te(text, result, flags) + elif(result.size() == 2): + te.scroll_vertical = result[L] + te.select(result[L], result[C], result[L], result[C] + text.length()) + te.cursor_set_column(result[C]) + te.cursor_set_line(result[L]) + te.center_viewport_to_cursor() + + _last_term = text + te.center_viewport_to_cursor() + return result + + func _cursor_to_pos(): + var to_return = [0, 0] + to_return[L] = te.cursor_get_line() + to_return[C] = te.cursor_get_column() + return to_return + + func find_next(term): + return _search_te(term, _cursor_to_pos()) + + func find_prev(term): + var new_pos = _search_te(term, _cursor_to_pos(), TextEdit.SEARCH_BACKWARDS) + return new_pos + + func get_next_pos(): + pass + + func get_prev_pos(): + pass + + func clear(): + pass + + func find_all(text): + var c_pos = [0, 0] + var found = true + var last_pos = [0, 0] + positions.clear() + + while(found): + c_pos = te.search(text, 0, c_pos[L], c_pos[C]) + + if(c_pos.size() > 0 and + (c_pos[L] > last_pos[L] or + (c_pos[L] == last_pos[L] and c_pos[C] > last_pos[C]))): + positions.append([c_pos[L], c_pos[C]]) + c_pos[C] += 1 + last_pos = c_pos + else: + found = false + + + +onready var _ctrls = { + output = $Output, + + copy_button = $Toolbar/CopyButton, + use_colors = $Toolbar/UseColors, + clear_button = $Toolbar/ClearButton, + word_wrap = $Toolbar/WordWrap, + show_search = $Toolbar/ShowSearch, + + search_bar = { + bar = $Search, + search_term = $Search/SearchTerm, + } +} +var _sr = SearchResults.new() + +func _test_running_setup(): + _ctrls.use_colors.text = 'use colors' + _ctrls.show_search.text = 'search' + _ctrls.word_wrap.text = 'ww' + + set_all_fonts("CourierPrime") + set_font_size(20) + + load_file('user://.gut_editor.bbcode') + + +func _ready(): + _sr.te = _ctrls.output + _ctrls.use_colors.icon = get_icon('RichTextEffect', 'EditorIcons') + _ctrls.show_search.icon = get_icon('Search', 'EditorIcons') + _ctrls.word_wrap.icon = get_icon('Loop', 'EditorIcons') + + _setup_colors() + if(get_parent() == get_tree().root): + _test_running_setup() + + +# ------------------ +# Private +# ------------------ +func _setup_colors(): + _ctrls.output.clear_colors() + var keywords = [ + ['Failed', Color.red], + ['Passed', Color.green], + ['Pending', Color.yellow], + ['Orphans', Color.yellow], + ['WARNING', Color.yellow], + ['ERROR', Color.red] + ] + + for keyword in keywords: + _ctrls.output.add_keyword_color(keyword[0], keyword[1]) + + var f_color = _ctrls.output.get_color("font_color") + _ctrls.output.add_color_override("font_color_readonly", f_color) + _ctrls.output.add_color_override("function_color", f_color) + _ctrls.output.add_color_override("member_variable_color", f_color) + _ctrls.output.update() + + +func _set_font(font_name, custom_name): + var rtl = _ctrls.output + if(font_name == null): + rtl.set('custom_fonts/' + custom_name, null) + else: + var dyn_font = DynamicFont.new() + var font_data = DynamicFontData.new() + font_data.font_path = 'res://addons/gut/fonts/' + font_name + '.ttf' + font_data.antialiased = true + dyn_font.font_data = font_data + rtl.set('custom_fonts/' + custom_name, dyn_font) + + +# ------------------ +# Events +# ------------------ +func _on_CopyButton_pressed(): + copy_to_clipboard() + + +func _on_UseColors_pressed(): + _ctrls.output.syntax_highlighting = _ctrls.use_colors.pressed + + +func _on_ClearButton_pressed(): + clear() + + +func _on_ShowSearch_pressed(): + show_search(_ctrls.show_search.pressed) + + +func _on_SearchTerm_focus_entered(): + _ctrls.search_bar.search_term.call_deferred('select_all') + +func _on_SearchNext_pressed(): + _sr.find_next(_ctrls.search_bar.search_term.text) + + +func _on_SearchPrev_pressed(): + _sr.find_prev(_ctrls.search_bar.search_term.text) + + +func _on_SearchTerm_text_changed(new_text): + if(new_text == ''): + _ctrls.output.deselect() + else: + _sr.find_next(new_text) + + +func _on_SearchTerm_text_entered(new_text): + if(Input.is_physical_key_pressed(KEY_SHIFT)): + _sr.find_prev(new_text) + else: + _sr.find_next(new_text) + + +func _on_SearchTerm_gui_input(event): + if(event is InputEventKey and !event.pressed and event.scancode == KEY_ESCAPE): + show_search(false) + +func _on_WordWrap_pressed(): + _ctrls.output.wrap_enabled = _ctrls.word_wrap.pressed + _ctrls.output.update() + +# ------------------ +# Public +# ------------------ +func show_search(should): + _ctrls.search_bar.bar.visible = should + if(should): + _ctrls.search_bar.search_term.grab_focus() + _ctrls.search_bar.search_term.select_all() + _ctrls.show_search.pressed = should + + +func search(text, start_pos, highlight=true): + return _sr.find_next(text) + + +func copy_to_clipboard(): + var selected = _ctrls.output.get_selection_text() + if(selected != ''): + OS.clipboard = selected + else: + OS.clipboard = _ctrls.output.text + + +func clear(): + _ctrls.output.text = '' + + +func set_all_fonts(base_name): + if(base_name == 'Default'): + _set_font(null, 'font') +# _set_font(null, 'normal_font') +# _set_font(null, 'bold_font') +# _set_font(null, 'italics_font') +# _set_font(null, 'bold_italics_font') + else: + _set_font(base_name + '-Regular', 'font') +# _set_font(base_name + '-Regular', 'normal_font') +# _set_font(base_name + '-Bold', 'bold_font') +# _set_font(base_name + '-Italic', 'italics_font') +# _set_font(base_name + '-BoldItalic', 'bold_italics_font') + + +func set_font_size(new_size): + var rtl = _ctrls.output + if(rtl.get('custom_fonts/font') != null): + rtl.get('custom_fonts/font').size = new_size +# 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_use_colors(value): + pass + + +func get_use_colors(): + return false; + + +func get_rich_text_edit(): + return _ctrls.output + + +func load_file(path): + var f = File.new() + var result = f.open(path, f.READ) + if(result != OK): + return + + var t = f.get_as_text() + f.close() + _ctrls.output.text = t + _ctrls.output.scroll_vertical = _ctrls.output.get_line_count() + _ctrls.output.set_deferred('scroll_vertical', _ctrls.output.get_line_count()) + + +func add_text(text): + if(is_inside_tree()): + _ctrls.output.text += text + + +func scroll_to_line(line): + _ctrls.output.scroll_vertical = line + _ctrls.output.cursor_set_line(line) diff --git a/addons/gut/gui/OutputText.tscn b/addons/gut/gui/OutputText.tscn new file mode 100644 index 0000000..d7c693a --- /dev/null +++ b/addons/gut/gui/OutputText.tscn @@ -0,0 +1,123 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://addons/gut/gui/OutputText.gd" type="Script" id=1] + +[sub_resource type="Image" id=3] +data = { +"data": PoolByteArray( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), +"format": "LumAlpha8", +"height": 16, +"mipmaps": false, +"width": 16 +} + +[sub_resource type="ImageTexture" id=2] +flags = 4 +flags = 4 +image = SubResource( 3 ) +size = Vector2( 16, 16 ) + +[node name="OutputText" type="VBoxContainer"] +margin_right = 862.0 +margin_bottom = 523.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource( 1 ) + +[node name="Toolbar" type="HBoxContainer" parent="."] +margin_right = 862.0 +margin_bottom = 24.0 +size_flags_horizontal = 3 + +[node name="ShowSearch" type="ToolButton" parent="Toolbar"] +margin_right = 28.0 +margin_bottom = 24.0 +toggle_mode = true +icon = SubResource( 2 ) + +[node name="UseColors" type="ToolButton" parent="Toolbar"] +margin_left = 32.0 +margin_right = 60.0 +margin_bottom = 24.0 +hint_tooltip = "Colorize output. + It's not the same as everywhere else (long story), + but it is better than nothing." +toggle_mode = true +pressed = true +icon = SubResource( 2 ) + +[node name="WordWrap" type="ToolButton" parent="Toolbar"] +margin_left = 64.0 +margin_right = 92.0 +margin_bottom = 24.0 +hint_tooltip = "Word wrap" +toggle_mode = true +icon = SubResource( 2 ) + +[node name="CenterContainer" type="CenterContainer" parent="Toolbar"] +margin_left = 96.0 +margin_right = 743.0 +margin_bottom = 24.0 +size_flags_horizontal = 3 + +[node name="CopyButton" type="Button" parent="Toolbar"] +margin_left = 747.0 +margin_right = 798.0 +margin_bottom = 24.0 +hint_tooltip = "Copy to clipboard" +text = " Copy " + +[node name="ClearButton" type="Button" parent="Toolbar"] +margin_left = 802.0 +margin_right = 862.0 +margin_bottom = 24.0 +text = " Clear " + +[node name="Output" type="TextEdit" parent="."] +margin_top = 28.0 +margin_right = 862.0 +margin_bottom = 523.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +readonly = true +highlight_current_line = true +syntax_highlighting = true +show_line_numbers = true +smooth_scrolling = true + +[node name="Search" type="HBoxContainer" parent="."] +visible = false +margin_top = 499.0 +margin_right = 862.0 +margin_bottom = 523.0 + +[node name="SearchTerm" type="LineEdit" parent="Search"] +margin_right = 804.0 +margin_bottom = 24.0 +size_flags_horizontal = 3 + +[node name="SearchNext" type="Button" parent="Search"] +margin_left = 808.0 +margin_right = 862.0 +margin_bottom = 24.0 +hint_tooltip = "Find next (enter)" +text = "Next" + +[node name="SearchPrev" type="Button" parent="Search"] +margin_left = 808.0 +margin_right = 820.0 +margin_bottom = 20.0 +hint_tooltip = "Find previous (shift + enter)" +text = "Prev" + +[connection signal="pressed" from="Toolbar/ShowSearch" to="." method="_on_ShowSearch_pressed"] +[connection signal="pressed" from="Toolbar/UseColors" to="." method="_on_UseColors_pressed"] +[connection signal="pressed" from="Toolbar/WordWrap" to="." method="_on_WordWrap_pressed"] +[connection signal="pressed" from="Toolbar/CopyButton" to="." method="_on_CopyButton_pressed"] +[connection signal="pressed" from="Toolbar/ClearButton" to="." method="_on_ClearButton_pressed"] +[connection signal="focus_entered" from="Search/SearchTerm" to="." method="_on_SearchTerm_focus_entered"] +[connection signal="gui_input" from="Search/SearchTerm" to="." method="_on_SearchTerm_gui_input"] +[connection signal="text_changed" from="Search/SearchTerm" to="." method="_on_SearchTerm_text_changed"] +[connection signal="text_entered" from="Search/SearchTerm" to="." method="_on_SearchTerm_text_entered"] +[connection signal="pressed" from="Search/SearchNext" to="." method="_on_SearchNext_pressed"] +[connection signal="pressed" from="Search/SearchPrev" to="." method="_on_SearchPrev_pressed"] diff --git a/addons/gut/gui/RunAtCursor.gd b/addons/gut/gui/RunAtCursor.gd index 960414e..dc83c3e 100644 --- a/addons/gut/gui/RunAtCursor.gd +++ b/addons/gut/gui/RunAtCursor.gd @@ -14,7 +14,6 @@ onready var _ctrls = { } var _editors = null -var _script_editor = null var _cur_editor = null var _last_line = -1 var _cur_script_path = null @@ -29,7 +28,9 @@ func _ready(): _ctrls.btn_inner.visible = false _ctrls.btn_method.visible = false - +# ---------------- +# Private +# ---------------- func _set_editor(which): _last_line = -1 if(_cur_editor != null and _cur_editor.get_ref()): @@ -44,7 +45,6 @@ func _set_editor(which): _update_buttons(_last_info) - func _update_buttons(info): _ctrls.lbl_none.visible = _cur_script_path == null _ctrls.btn_script.visible = _cur_script_path != null @@ -58,16 +58,19 @@ func _update_buttons(info): _ctrls.arrow_2.visible = info.test_method != null _ctrls.btn_method.text = str(info.test_method) _ctrls.btn_method.hint_tooltip = str("Run test ", info.test_method) - - # The button's new size won't take effect until the next frame. + + # The button's new size won't take effect until the next frame. # This appears to be what was causing the button to not be clickable the # first time. call_deferred("_update_rect_size") - + func _update_rect_size(): rect_min_size.x = _ctrls.btn_method.rect_size.x + _ctrls.btn_method.rect_position.x +# ---------------- +# Events +# ---------------- func _on_cursor_changed(which): if(which.cursor_get_line() != _last_line): _last_line = which.cursor_get_line() @@ -75,20 +78,6 @@ func _on_cursor_changed(which): _update_buttons(_last_info) -func set_script_editor(value): - _script_editor = value - _editors = ScriptTextEditors.new(value) - - -func activate_for_script(path): - _ctrls.btn_script.visible = true - _ctrls.btn_script.text = path.get_file() - _ctrls.btn_script.hint_tooltip = str("Run all tests in script ", path) - _cur_script_path = path - _editors.refresh() - _set_editor(_editors.get_current_text_edit()) - - func _on_BtnRunScript_pressed(): var info = _last_info.duplicate() info.script = _cur_script_path.get_file() @@ -110,6 +99,22 @@ func _on_BtnRunMethod_pressed(): emit_signal("run_tests", info) +# ---------------- +# Public +# ---------------- +func set_script_text_editors(value): + _editors = value + + +func activate_for_script(path): + _ctrls.btn_script.visible = true + _ctrls.btn_script.text = path.get_file() + _ctrls.btn_script.hint_tooltip = str("Run all tests in script ", path) + _cur_script_path = path + _editors.refresh() + _set_editor(_editors.get_current_text_edit()) + + func get_script_button(): return _ctrls.btn_script @@ -121,10 +126,28 @@ func get_inner_button(): func get_test_button(): return _ctrls.btn_method + # not used, thought was configurable but it's just the script prefix func set_method_prefix(value): _editors.set_method_prefix(value) + # not used, thought was configurable but it's just the script prefix func set_inner_class_prefix(value): _editors.set_inner_class_prefix(value) + + +# Mashed this function in here b/c it has _editors. Probably should be +# somewhere else (possibly in script_text_editor_controls). +func search_current_editor_for_text(txt): + var te = _editors.get_current_text_edit() + var result = te.search(txt, 0, 0, 0) + var to_return = -1 + + if result.size() > 0: + to_return = result[TextEdit.SEARCH_RESULT_LINE] + + return to_return + + + diff --git a/addons/gut/gui/RunResults.gd b/addons/gut/gui/RunResults.gd new file mode 100644 index 0000000..a36d10f --- /dev/null +++ b/addons/gut/gui/RunResults.gd @@ -0,0 +1,509 @@ +extends Control +tool + +var _interface = null +var _utils = load('res://addons/gut/utils.gd').new() +var _hide_passing = true +var _font = null +var _font_size = null +var _root = null +var _max_icon_width = 10 +var _editors = null # script_text_editor_controls.gd +var _show_orphans = true +var _output_control = null + +const _col_1_bg_color = Color(0, 0, 0, .1) + +var _icons = { + red = load('res://addons/gut/images/red.png'), + green = load('res://addons/gut/images/green.png'), + yellow = load('res://addons/gut/images/yellow.png'), +} + +signal search_for_text(text) + +onready var _ctrls = { + tree = $VBox/Output/Scroll/Tree, + lbl_overlay = $VBox/Output/OverlayMessage, + chk_hide_passing = $VBox/Toolbar/HidePassing, + toolbar = { + toolbar = $VBox/Toolbar, + collapse = $VBox/Toolbar/Collapse, + collapse_all = $VBox/Toolbar/CollapseAll, + expand = $VBox/Toolbar/Expand, + expand_all = $VBox/Toolbar/ExpandAll, + hide_passing = $VBox/Toolbar/HidePassing, + show_script = $VBox/Toolbar/ShowScript, + scroll_output = $VBox/Toolbar/ScrollOutput + } +} + +func _test_running_setup(): + _hide_passing = true + _show_orphans = true + var _gut_config = load('res://addons/gut/gut_config.gd').new() + _gut_config.load_panel_options('res://.gut_editor_config.json') + set_font( + _gut_config.options.panel_options.font_name, + _gut_config.options.panel_options.font_size) + + _ctrls.toolbar.hide_passing.text = '[hp]' + load_json_file('user://.gut_editor.json') + + +func _set_toolbutton_icon(btn, icon_name, text): + if(Engine.editor_hint): + btn.icon = get_icon(icon_name, 'EditorIcons') + else: + btn.text = str('[', text, ']') + + +func _ready(): + var f = $FontSampler.get_font("font") + var s_size = f.get_string_size("000 of 000 passed") + _root = _ctrls.tree.create_item() + _ctrls.tree.set_hide_root(true) + _ctrls.tree.columns = 2 + _ctrls.tree.set_column_expand(0, true) + _ctrls.tree.set_column_expand(1, false) + _ctrls.tree.set_column_min_width(1, s_size.x) + + _set_toolbutton_icon(_ctrls.toolbar.collapse, 'CollapseTree', 'c') + _set_toolbutton_icon(_ctrls.toolbar.collapse_all, 'CollapseTree', 'c') + _set_toolbutton_icon(_ctrls.toolbar.expand, 'ExpandTree', 'e') + _set_toolbutton_icon(_ctrls.toolbar.expand_all, 'ExpandTree', 'e') + _set_toolbutton_icon(_ctrls.toolbar.show_script, 'Script', 'ss') + _set_toolbutton_icon(_ctrls.toolbar.scroll_output, 'Font', 'so') + + _ctrls.toolbar.hide_passing.set('custom_icons/checked', get_icon('GuiVisibilityHidden', 'EditorIcons')) + _ctrls.toolbar.hide_passing.set('custom_icons/unchecked', get_icon('GuiVisibilityVisible', 'EditorIcons')) + + if(get_parent() == get_tree().root): + _test_running_setup() + + call_deferred('_update_min_width') + +func _update_min_width(): + rect_min_size.x = _ctrls.toolbar.toolbar.rect_size.x + +func _open_file(path, line_number): + if(_interface == null): + print('Too soon, wait a bit and try again.') + return + + var r = load(path) + if(line_number != -1): + _interface.edit_script(r, line_number) + else: + _interface.edit_script(r) + + if(_ctrls.toolbar.show_script.pressed): + _interface.set_main_screen_editor('Script') + + +func _add_script_tree_item(script_path, script_json): + var path_info = _get_path_and_inner_class_name_from_test_path(script_path) + # print('* adding script ', path_info) + var item_text = script_path + var parent = _root + + if(path_info.inner_class != ''): + parent = _find_script_item_with_path(path_info.path) + item_text = path_info.inner_class + if(parent == null): + parent = _add_script_tree_item(path_info.path, {}) + + var item = _ctrls.tree.create_item(parent) + item.set_text(0, item_text) + var meta = { + "type":"script", + "path":path_info.path, + "inner_class":path_info.inner_class, + "json":script_json} + item.set_metadata(0, meta) + item.set_custom_bg_color(1, _col_1_bg_color) + + return item + + +func _add_assert_item(text, icon, parent_item): + # print(' * adding assert') + var assert_item = _ctrls.tree.create_item(parent_item) + assert_item.set_icon_max_width(0, _max_icon_width) + assert_item.set_text(0, text) + assert_item.set_metadata(0, {"type":"assert"}) + assert_item.set_icon(0, icon) + assert_item.set_custom_bg_color(1, _col_1_bg_color) + + return assert_item + + +func _add_test_tree_item(test_name, test_json, script_item): + # print(' * adding test ', test_name) + var no_orphans_to_show = !_show_orphans or (_show_orphans and test_json.orphans == 0) + if(_hide_passing and test_json['status'] == 'pass' and no_orphans_to_show): + return + + var item = _ctrls.tree.create_item(script_item) + var status = test_json['status'] + var meta = {"type":"test", "json":test_json} + + item.set_text(0, test_name) + item.set_text(1, status) + item.set_text_align(1, TreeItem.ALIGN_RIGHT) + item.set_custom_bg_color(1, _col_1_bg_color) + + item.set_metadata(0, meta) + item.set_icon_max_width(0, _max_icon_width) + + var orphan_text = 'orphans' + if(test_json.orphans == 1): + orphan_text = 'orphan' + orphan_text = str(test_json.orphans, ' ', orphan_text) + + + if(status == 'pass' and no_orphans_to_show): + item.set_icon(0, _icons.green) + elif(status == 'pass' and !no_orphans_to_show): + item.set_icon(0, _icons.yellow) + item.set_text(1, orphan_text) + elif(status == 'fail'): + item.set_icon(0, _icons.red) + else: + item.set_icon(0, _icons.yellow) + + if(!_hide_passing): + for passing in test_json.passing: + _add_assert_item('pass: ' + passing, _icons.green, item) + + for failure in test_json.failing: + _add_assert_item("fail: " + failure.replace("\n", ''), _icons.red, item) + + for pending in test_json.pending: + _add_assert_item("pending: " + pending.replace("\n", ''), _icons.yellow, item) + + if(status != 'pass' and !no_orphans_to_show): + _add_assert_item(orphan_text, _icons.yellow, item) + + return item + + +func _load_result_tree(j): + var scripts = j['test_scripts']['scripts'] + var script_keys = scripts.keys() + # if we made it here, the json is valid and we did something, otherwise the + # 'nothing to see here' should be visible. + clear_centered_text() + + var _last_script_item = null + for key in script_keys: + var tests = scripts[key]['tests'] + var test_keys = tests.keys() + var s_item = _add_script_tree_item(key, scripts[key]) + var bad_count = 0 + + for test_key in test_keys: + var t_item = _add_test_tree_item(test_key, tests[test_key], s_item) + if(tests[test_key].status != 'pass'): + bad_count += 1 + elif(t_item != null): + t_item.collapsed = true + + # get_children returns the first child or null. its a dumb name. + if(s_item.get_children() == null): + # var m = s_item.get_metadata(0) + # print('!! Deleting ', m.path, ' ', m.inner_class) + s_item.free() + else: + var total_text = str(test_keys.size(), ' passed') + s_item.set_text_align(1, s_item.ALIGN_LEFT) + if(bad_count == 0): + s_item.collapsed = true + else: + total_text = str(test_keys.size() - bad_count, ' of ', test_keys.size(), ' passed') + s_item.set_text(1, total_text) + + _free_childless_scripts() + _show_all_passed() + + +func _free_childless_scripts(): + var item = _root.get_children() + while(item != null): + var next_item = item.get_next() + if(item.get_children() == null): + item.free() + item = next_item + + +func _find_script_item_with_path(path): + var item = _root.get_children() + var to_return = null + + while(item != null and to_return == null): + if(item.get_metadata(0).path == path): + to_return = item + else: + item = item.get_next() + + return to_return + + +func _get_line_number_from_assert_msg(msg): + var line = -1 + if(msg.find('at line') > 0): + line = int(msg.split("at line")[-1].split(" ")[-1]) + return line + + +func _get_path_and_inner_class_name_from_test_path(path): + var to_return = { + path = '', + inner_class = '' + } + + to_return.path = path + if !path.ends_with('.gd'): + var loc = path.find('.gd') + to_return.inner_class = path.split('.')[-1] + to_return.path = path.substr(0, loc + 3) + return to_return + + +func _handle_tree_item_select(item, force_scroll): + var item_type = item.get_metadata(0).type + + var path = ''; + var line = -1; + var method_name = '' + var inner_class = '' + + if(item_type == 'test'): + var s_item = item.get_parent() + path = s_item.get_metadata(0)['path'] + inner_class = s_item.get_metadata(0)['inner_class'] + line = -1 + method_name = item.get_text(0) + elif(item_type == 'assert'): + var s_item = item.get_parent().get_parent() + path = s_item.get_metadata(0)['path'] + inner_class = s_item.get_metadata(0)['inner_class'] + + line = _get_line_number_from_assert_msg(item.get_text(0)) + method_name = item.get_parent().get_text(0) + elif(item_type == 'script'): + path = item.get_metadata(0)['path'] + if(item.get_parent() != _root): + inner_class = item.get_text(0) + line = -1 + method_name = '' + else: + return + + var path_info = _get_path_and_inner_class_name_from_test_path(path) + if(force_scroll or _ctrls.toolbar.show_script.pressed): + _goto_code(path, line, method_name, inner_class) + if(force_scroll or _ctrls.toolbar.scroll_output.pressed): + _goto_output(path, method_name, inner_class) + + +# starts at beginning of text edit and searches for each search term, moving +# through the text as it goes; ensuring that, when done, it found the first +# occurance of the last srting that happend after the first occurance of +# each string before it. (Generic way of searching for a method name in an +# inner class that may have be a duplicate of a method name in a different +# inner class) +func _get_line_number_for_seq_search(search_strings, te): +# var te = _editors.get_current_text_edit() + var result = null + var to_return = -1 + var start_line = 0 + var start_col = 0 + var s_flags = 0 + + var i = 0 + var string_found = true + while(i < search_strings.size() and string_found): + result = te.search(search_strings[i], s_flags, start_line, start_col) + if(result.size() > 0): + start_line = result[TextEdit.SEARCH_RESULT_LINE] + start_col = result[TextEdit.SEARCH_RESULT_COLUMN] + to_return = start_line + else: + string_found = false + i += 1 + + return to_return + + +func _goto_code(path, line, method_name='', inner_class =''): + if(_interface == null): + print('going to ', [path, line, method_name, inner_class]) + return + + _open_file(path, line) + if(line == -1): + var search_strings = [] + if(inner_class != ''): + search_strings.append(inner_class) + + if(method_name != ''): + search_strings.append(method_name) + + line = _get_line_number_for_seq_search(search_strings, _editors.get_current_text_edit()) + if(line != -1): + _interface.get_script_editor().goto_line(line) + + +func _goto_output(path, method_name, inner_class): + if(_output_control == null): + return + + var search_strings = [path] + + if(inner_class != ''): + search_strings.append(inner_class) + + if(method_name != ''): + search_strings.append(method_name) + + var line = _get_line_number_for_seq_search(search_strings, _output_control.get_rich_text_edit()) + if(line != -1): + _output_control.scroll_to_line(line) + + +func _show_all_passed(): + if(_root.get_children() == null): + add_centered_text('Everything passed!') + + +func _set_collapsed_on_all(item, value): + if(item == _root): + var node = _root.get_children() + while(node != null): + node.call_recursive('set_collapsed', value) + node = node.get_next() + else: + item.call_recursive('set_collapsed', value) + +# -------------- +# Events +# -------------- +func _on_Tree_item_selected(): + # do not force scroll + var item = _ctrls.tree.get_selected() + _handle_tree_item_select(item, false) + # it just looks better if the left is always selected. + if(item.is_selected(1)): + item.deselect(1) + item.select(0) + + +func _on_Tree_item_activated(): + # force scroll + print('double clicked') + _handle_tree_item_select(_ctrls.tree.get_selected(), true) + +func _on_Collapse_pressed(): + collapse_selected() + + +func _on_Expand_pressed(): + expand_selected() + + +func _on_CollapseAll_pressed(): + collapse_all() + + +func _on_ExpandAll_pressed(): + expand_all() + + +func _on_Hide_Passing_pressed(): + _hide_passing = _ctrls.toolbar.hide_passing.pressed + +# -------------- +# Public +# -------------- +func load_json_file(path): + var text = _utils.get_file_as_text(path) + if(text != ''): + var result = JSON.parse(text) + if(result.error != OK): + add_centered_text(str(path, " has invalid json in it \n", + 'Error ', result.error, "@", result.error_line, "\n", + result.error_string)) + return + + load_json_results(result.result) + else: + add_centered_text(str(path, ' was empty or does not exist.')) + + +func load_json_results(j): + clear() + add_centered_text('Nothing Here') + _load_result_tree(j) + + +func add_centered_text(t): + _ctrls.lbl_overlay.text = t + + +func clear_centered_text(): + _ctrls.lbl_overlay.text = '' + + +func clear(): + _ctrls.tree.clear() + _root = _ctrls.tree.create_item() + clear_centered_text() + + +func set_interface(which): + _interface = which + + +func set_script_text_editors(value): + _editors = value + + +func collapse_all(): + _set_collapsed_on_all(_root, true) + + +func expand_all(): + _set_collapsed_on_all(_root, false) + + +func collapse_selected(): + var item = _ctrls.tree.get_selected() + if(item != null): + _set_collapsed_on_all(item, true) + +func expand_selected(): + var item = _ctrls.tree.get_selected() + if(item != null): + _set_collapsed_on_all(item, false) + + +func set_show_orphans(should): + _show_orphans = should + + +func set_font(font_name, size): + pass +# var dyn_font = DynamicFont.new() +# var font_data = DynamicFontData.new() +# font_data.font_path = 'res://addons/gut/fonts/' + font_name + '-Regular.ttf' +# font_data.antialiased = true +# dyn_font.font_data = font_data +# +# _font = dyn_font +# _font.size = size +# _font_size = size + + +func set_output_control(value): + _output_control = value diff --git a/addons/gut/gui/RunResults.tscn b/addons/gut/gui/RunResults.tscn new file mode 100644 index 0000000..be4c1d5 --- /dev/null +++ b/addons/gut/gui/RunResults.tscn @@ -0,0 +1,165 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://addons/gut/gui/RunResults.gd" type="Script" id=1] + +[sub_resource type="Image" id=3] +data = { +"data": PoolByteArray( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), +"format": "LumAlpha8", +"height": 16, +"mipmaps": false, +"width": 16 +} + +[sub_resource type="ImageTexture" id=2] +flags = 4 +flags = 4 +image = SubResource( 3 ) +size = Vector2( 16, 16 ) + +[node name="RunResults" type="Control"] +margin_right = 595.0 +margin_bottom = 459.0 +rect_min_size = Vector2( 302, 0 ) +script = ExtResource( 1 ) + +[node name="VBox" type="VBoxContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 + +[node name="Toolbar" type="HBoxContainer" parent="VBox"] +margin_right = 296.0 +margin_bottom = 24.0 +size_flags_horizontal = 0 + +[node name="Expand" type="ToolButton" parent="VBox/Toolbar"] +margin_right = 28.0 +margin_bottom = 24.0 +hint_tooltip = "Expand selected item and all children." +icon = SubResource( 2 ) + +[node name="Collapse" type="ToolButton" parent="VBox/Toolbar"] +margin_left = 32.0 +margin_right = 60.0 +margin_bottom = 24.0 +hint_tooltip = "Collapse selected item and all children." +icon = SubResource( 2 ) + +[node name="Sep" type="ColorRect" parent="VBox/Toolbar"] +margin_left = 64.0 +margin_right = 66.0 +margin_bottom = 24.0 +rect_min_size = Vector2( 2, 0 ) + +[node name="LblAll" type="Label" parent="VBox/Toolbar"] +margin_left = 70.0 +margin_top = 5.0 +margin_right = 91.0 +margin_bottom = 19.0 +text = "All:" +align = 1 + +[node name="ExpandAll" type="ToolButton" parent="VBox/Toolbar"] +margin_left = 95.0 +margin_right = 123.0 +margin_bottom = 24.0 +hint_tooltip = "Expand All." +icon = SubResource( 2 ) + +[node name="CollapseAll" type="ToolButton" parent="VBox/Toolbar"] +margin_left = 127.0 +margin_right = 155.0 +margin_bottom = 24.0 +hint_tooltip = "Collapse all." +icon = SubResource( 2 ) + +[node name="Sep2" type="ColorRect" parent="VBox/Toolbar"] +margin_left = 159.0 +margin_right = 161.0 +margin_bottom = 24.0 +rect_min_size = Vector2( 2, 0 ) + +[node name="HidePassing" type="CheckBox" parent="VBox/Toolbar"] +margin_left = 165.0 +margin_right = 189.0 +margin_bottom = 24.0 +hint_tooltip = "Show/Hide passing tests. Takes effect on next run." +size_flags_horizontal = 4 +custom_icons/checked = SubResource( 2 ) +custom_icons/unchecked = SubResource( 2 ) +pressed = true +__meta__ = { +"_editor_description_": "" +} + +[node name="Sep3" type="ColorRect" parent="VBox/Toolbar"] +margin_left = 193.0 +margin_right = 195.0 +margin_bottom = 24.0 +rect_min_size = Vector2( 2, 0 ) + +[node name="LblSync" type="Label" parent="VBox/Toolbar"] +margin_left = 199.0 +margin_top = 5.0 +margin_right = 232.0 +margin_bottom = 19.0 +text = "Sync:" +align = 1 + +[node name="ShowScript" type="ToolButton" parent="VBox/Toolbar"] +margin_left = 236.0 +margin_right = 264.0 +margin_bottom = 24.0 +hint_tooltip = "Open script and scroll to line when a tree item is clicked." +toggle_mode = true +pressed = true +icon = SubResource( 2 ) + +[node name="ScrollOutput" type="ToolButton" parent="VBox/Toolbar"] +margin_left = 268.0 +margin_right = 296.0 +margin_bottom = 24.0 +hint_tooltip = "Scroll to related line in the output panel when tree item clicked." +toggle_mode = true +pressed = true +icon = SubResource( 2 ) + +[node name="Output" type="Panel" parent="VBox"] +self_modulate = Color( 1, 1, 1, 0.541176 ) +margin_top = 28.0 +margin_right = 595.0 +margin_bottom = 459.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Scroll" type="ScrollContainer" parent="VBox/Output"] +anchor_right = 1.0 +anchor_bottom = 1.0 + +[node name="Tree" type="Tree" parent="VBox/Output/Scroll"] +margin_right = 595.0 +margin_bottom = 431.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +columns = 2 +hide_root = true + +[node name="OverlayMessage" type="Label" parent="VBox/Output"] +anchor_right = 1.0 +anchor_bottom = 1.0 +align = 1 +valign = 1 + +[node name="FontSampler" type="Label" parent="."] +visible = false +margin_right = 40.0 +margin_bottom = 14.0 +text = "000 of 000 passed" + +[connection signal="pressed" from="VBox/Toolbar/Expand" to="." method="_on_Expand_pressed"] +[connection signal="pressed" from="VBox/Toolbar/Collapse" to="." method="_on_Collapse_pressed"] +[connection signal="pressed" from="VBox/Toolbar/ExpandAll" to="." method="_on_ExpandAll_pressed"] +[connection signal="pressed" from="VBox/Toolbar/CollapseAll" to="." method="_on_CollapseAll_pressed"] +[connection signal="pressed" from="VBox/Toolbar/HidePassing" to="." method="_on_Hide_Passing_pressed"] +[connection signal="item_activated" from="VBox/Output/Scroll/Tree" to="." method="_on_Tree_item_activated"] +[connection signal="item_selected" from="VBox/Output/Scroll/Tree" to="." method="_on_Tree_item_selected"] diff --git a/addons/gut/gui/arrow.png b/addons/gut/gui/arrow.png index 09d8323..26a7dc4 100644 --- a/addons/gut/gui/arrow.png +++ b/addons/gut/gui/arrow.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9918e125593427685252d339f9c49d2ce8ce0b0fff9d28089164d78fccd80e2 -size 645 +oid sha256:7f5a2f25d0cc68b8281bda24cdcd1d816e718d11fa0d050ede6cbad9033d17ed +size 122 diff --git a/addons/gut/gui/gut_config_gui.gd b/addons/gut/gui/gut_config_gui.gd index dc58be4..4f056ff 100644 --- a/addons/gut/gui/gut_config_gui.gd +++ b/addons/gut/gui/gut_config_gui.gd @@ -272,8 +272,8 @@ func get_config_issues(): if(!has_directory): to_return.append('You do not have any directories set.') - if(_cfg_ctrls['prefix'].text == ''): - to_return.append("You must set a Script prefix or GUT won't find any scripts") + if(!_cfg_ctrls['suffix'].text.ends_with('.gd')): + to_return.append("Script suffix must end in '.gd'") return to_return @@ -354,6 +354,8 @@ func set_options(options): _add_title('Misc') _add_value('prefix', options.prefix, 'Script Prefix', "The filename prefix for all test scripts.") + _add_value('suffix', options.suffix, 'Script Suffix', + "Script suffix, including .gd extension. For example '_foo.gd'.") func get_options(base_opts): @@ -404,5 +406,6 @@ func get_options(base_opts): # Misc to_return.prefix = _cfg_ctrls.prefix.text + to_return.suffix = _cfg_ctrls.suffix.text return to_return diff --git a/addons/gut/gui/play.png b/addons/gut/gui/play.png index 697f319..2be1d4d 100644 --- a/addons/gut/gui/play.png +++ b/addons/gut/gui/play.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90041b369445e15dfaa4ec011cb4f1c0536a8d63295a574e0f8743f772dc418e -size 676 +oid sha256:d4280462a7940ebaf184e2b92bd01a69cf09ae1c97b175ac92e1410d16ecf278 +size 143 |
