2023-01-07 20:26:17 +01:00
|
|
|
extends VBoxContainer
|
|
|
|
@tool
|
|
|
|
|
2023-01-20 23:34:39 +01:00
|
|
|
|
2023-01-07 20:26:17 +01:00
|
|
|
class SearchResults:
|
|
|
|
var L = 0
|
|
|
|
var C = 0
|
|
|
|
|
|
|
|
var positions = []
|
|
|
|
var te = null
|
2023-01-20 23:34:39 +01:00
|
|
|
var _last_term = ""
|
2023-01-07 20:26:17 +01:00
|
|
|
|
2023-01-20 23:34:39 +01:00
|
|
|
func _search_te(text, start_position, flags = 0):
|
2023-01-07 20:26:17 +01:00
|
|
|
var start_pos = start_position
|
2023-01-20 23:34:39 +01:00
|
|
|
if start_pos[L] < 0 or start_pos[L] > te.get_line_count():
|
2023-01-07 20:26:17 +01:00
|
|
|
start_pos[L] = 0
|
2023-01-20 23:34:39 +01:00
|
|
|
if start_pos[C] < 0:
|
2023-01-07 20:26:17 +01:00
|
|
|
start_pos[L] = 0
|
|
|
|
|
|
|
|
var result = te.search(text, flags, start_pos[L], start_pos[C])
|
2023-01-20 23:34:39 +01:00
|
|
|
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:
|
2023-01-07 20:26:17 +01:00
|
|
|
result[C] -= 1
|
|
|
|
else:
|
|
|
|
result[C] += 1
|
|
|
|
result = _search_te(text, result, flags)
|
|
|
|
L = result.y
|
|
|
|
C = result.x
|
2023-01-20 23:34:39 +01:00
|
|
|
elif result.size() == 2:
|
2023-01-07 20:26:17 +01:00
|
|
|
te.scroll_vertical = result[L]
|
|
|
|
te.select(result[L], result[C], result[L], result[C] + text.length())
|
|
|
|
te.set_caret_column(result[C])
|
|
|
|
te.set_caret_line(result[L])
|
|
|
|
te.center_viewport_to_caret()
|
|
|
|
L = result.y
|
|
|
|
C = result.x
|
|
|
|
|
|
|
|
_last_term = text
|
|
|
|
te.center_viewport_to_caret()
|
|
|
|
return result
|
|
|
|
|
|
|
|
func _cursor_to_pos():
|
|
|
|
var to_return = [0, 0]
|
|
|
|
to_return[L] = te.get_caret_line()
|
|
|
|
to_return[C] = te.get_caret_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()
|
|
|
|
|
2023-01-20 23:34:39 +01:00
|
|
|
while found:
|
2023-01-07 20:26:17 +01:00
|
|
|
c_pos = te.search(text, 0, c_pos[L], c_pos[C])
|
|
|
|
|
2023-01-20 23:34:39 +01:00
|
|
|
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]))
|
|
|
|
):
|
2023-01-07 20:26:17 +01:00
|
|
|
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,
|
2023-01-20 23:34:39 +01:00
|
|
|
search_bar =
|
|
|
|
{
|
2023-01-07 20:26:17 +01:00
|
|
|
bar = $Search,
|
|
|
|
search_term = $Search/SearchTerm,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var _sr = SearchResults.new()
|
|
|
|
|
2023-01-20 23:34:39 +01:00
|
|
|
|
2023-01-07 20:26:17 +01:00
|
|
|
func _test_running_setup():
|
2023-01-20 23:34:39 +01:00
|
|
|
_ctrls.use_colors.text = "use colors"
|
|
|
|
_ctrls.show_search.text = "search"
|
|
|
|
_ctrls.word_wrap.text = "ww"
|
2023-01-07 20:26:17 +01:00
|
|
|
|
|
|
|
set_all_fonts("CourierPrime")
|
|
|
|
set_font_size(20)
|
|
|
|
|
2023-01-20 23:34:39 +01:00
|
|
|
load_file("user://.gut_editor.bbcode")
|
2023-01-07 20:26:17 +01:00
|
|
|
|
|
|
|
|
|
|
|
func _ready():
|
|
|
|
_sr.te = _ctrls.output
|
2023-01-20 23:34:39 +01:00
|
|
|
_ctrls.use_colors.icon = get_theme_icon("RichTextEffect", "EditorIcons")
|
|
|
|
_ctrls.show_search.icon = get_theme_icon("Search", "EditorIcons")
|
|
|
|
_ctrls.word_wrap.icon = get_theme_icon("Loop", "EditorIcons")
|
2023-01-07 20:26:17 +01:00
|
|
|
|
|
|
|
_setup_colors()
|
2023-01-20 23:34:39 +01:00
|
|
|
if get_parent() == get_tree().root:
|
2023-01-07 20:26:17 +01:00
|
|
|
_test_running_setup()
|
|
|
|
|
|
|
|
|
|
|
|
# ------------------
|
|
|
|
# Private
|
|
|
|
# ------------------
|
|
|
|
func _setup_colors():
|
|
|
|
_ctrls.output.clear()
|
|
|
|
var keywords = [
|
2023-01-20 23:34:39 +01:00
|
|
|
["Failed", Color.RED],
|
|
|
|
["Passed", Color.GREEN],
|
|
|
|
["Pending", Color.YELLOW],
|
|
|
|
["Orphans", Color.YELLOW],
|
|
|
|
["WARNING", Color.YELLOW],
|
|
|
|
["ERROR", Color.RED]
|
2023-01-07 20:26:17 +01:00
|
|
|
]
|
|
|
|
|
|
|
|
for keyword in keywords:
|
2023-01-20 23:34:39 +01:00
|
|
|
if _ctrls.output.syntax_highlighter == null:
|
2023-01-07 20:26:17 +01:00
|
|
|
_ctrls.output.syntax_highlighter = CodeHighlighter.new()
|
|
|
|
_ctrls.output.syntax_highlighter.add_keyword_color(keyword[0], keyword[1])
|
|
|
|
|
|
|
|
var f_color = null
|
2023-01-20 23:34:39 +01:00
|
|
|
if _ctrls.output.theme == null:
|
2023-01-07 20:26:17 +01:00
|
|
|
f_color = get_theme_color("font_color")
|
2023-01-20 23:34:39 +01:00
|
|
|
else:
|
2023-01-07 20:26:17 +01:00
|
|
|
f_color = _ctrls.output.theme.font_color
|
|
|
|
_ctrls.output.add_theme_color_override("font_color_readonly", f_color)
|
|
|
|
_ctrls.output.add_theme_color_override("function_color", f_color)
|
|
|
|
_ctrls.output.add_theme_color_override("member_variable_color", f_color)
|
|
|
|
_ctrls.output.queue_redraw()
|
|
|
|
|
|
|
|
|
|
|
|
func _set_font(font_name, custom_name):
|
|
|
|
var rtl = _ctrls.output
|
2023-01-20 23:34:39 +01:00
|
|
|
if font_name == null:
|
|
|
|
rtl.set("custom_fonts/" + custom_name, null)
|
2023-01-07 20:26:17 +01:00
|
|
|
else:
|
|
|
|
pass
|
|
|
|
# cuasing issues in 4.0
|
|
|
|
# var dyn_font = FontFile.new()
|
|
|
|
# var font_data = FontFile.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_highlighter = _ctrls.use_colors.button_pressed
|
|
|
|
|
|
|
|
|
|
|
|
func _on_ClearButton_pressed():
|
|
|
|
clear()
|
|
|
|
|
|
|
|
|
|
|
|
func _on_ShowSearch_pressed():
|
|
|
|
show_search(_ctrls.show_search.button_pressed)
|
|
|
|
|
|
|
|
|
|
|
|
func _on_SearchTerm_focus_entered():
|
2023-01-20 23:34:39 +01:00
|
|
|
_ctrls.search_bar.search_term.call_deferred("select_all")
|
|
|
|
|
2023-01-07 20:26:17 +01:00
|
|
|
|
|
|
|
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):
|
2023-01-20 23:34:39 +01:00
|
|
|
if new_text == "":
|
2023-01-07 20:26:17 +01:00
|
|
|
_ctrls.output.deselect()
|
|
|
|
else:
|
|
|
|
_sr.find_next(new_text)
|
|
|
|
|
|
|
|
|
|
|
|
func _on_SearchTerm_text_entered(new_text):
|
2023-01-20 23:34:39 +01:00
|
|
|
if Input.is_physical_key_pressed(KEY_SHIFT):
|
2023-01-07 20:26:17 +01:00
|
|
|
_sr.find_prev(new_text)
|
|
|
|
else:
|
|
|
|
_sr.find_next(new_text)
|
|
|
|
|
|
|
|
|
|
|
|
func _on_SearchTerm_gui_input(event):
|
2023-01-20 23:34:39 +01:00
|
|
|
if event is InputEventKey and !event.pressed and event.scancode == KEY_ESCAPE:
|
2023-01-07 20:26:17 +01:00
|
|
|
show_search(false)
|
|
|
|
|
2023-01-20 23:34:39 +01:00
|
|
|
|
2023-01-07 20:26:17 +01:00
|
|
|
func _on_WordWrap_pressed():
|
|
|
|
_ctrls.output.wrap_enabled = _ctrls.word_wrap.pressed
|
|
|
|
_ctrls.output.queue_redraw()
|
|
|
|
|
2023-01-20 23:34:39 +01:00
|
|
|
|
2023-01-07 20:26:17 +01:00
|
|
|
# ------------------
|
|
|
|
# Public
|
|
|
|
# ------------------
|
|
|
|
func show_search(should):
|
|
|
|
_ctrls.search_bar.bar.visible = should
|
2023-01-20 23:34:39 +01:00
|
|
|
if should:
|
2023-01-07 20:26:17 +01:00
|
|
|
_ctrls.search_bar.search_term.grab_focus()
|
|
|
|
_ctrls.search_bar.search_term.select_all()
|
|
|
|
_ctrls.show_search.button_pressed = should
|
|
|
|
|
|
|
|
|
2023-01-20 23:34:39 +01:00
|
|
|
func search(text, start_pos, highlight = true):
|
2023-01-07 20:26:17 +01:00
|
|
|
return _sr.find_next(text)
|
|
|
|
|
|
|
|
|
|
|
|
func copy_to_clipboard():
|
|
|
|
var selected = _ctrls.output.get_selection_text()
|
2023-01-20 23:34:39 +01:00
|
|
|
if selected != "":
|
2023-01-07 20:26:17 +01:00
|
|
|
OS.clipboard = selected
|
|
|
|
else:
|
|
|
|
OS.clipboard = _ctrls.output.text
|
|
|
|
|
|
|
|
|
|
|
|
func clear():
|
2023-01-20 23:34:39 +01:00
|
|
|
_ctrls.output.text = ""
|
2023-01-07 20:26:17 +01:00
|
|
|
|
|
|
|
|
|
|
|
func set_all_fonts(base_name):
|
2023-01-20 23:34:39 +01:00
|
|
|
if base_name == "Default":
|
|
|
|
_set_font(null, "font")
|
2023-01-07 20:26:17 +01:00
|
|
|
# _set_font(null, 'normal_font')
|
|
|
|
# _set_font(null, 'bold_font')
|
|
|
|
# _set_font(null, 'italics_font')
|
|
|
|
# _set_font(null, 'bold_italics_font')
|
|
|
|
else:
|
2023-01-20 23:34:39 +01:00
|
|
|
_set_font(base_name + "-Regular", "font")
|
|
|
|
|
|
|
|
|
2023-01-07 20:26:17 +01:00
|
|
|
# _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
|
2023-01-20 23:34:39 +01:00
|
|
|
if rtl.get("custom_fonts/font") != null:
|
|
|
|
rtl.get("custom_fonts/font").size = new_size
|
|
|
|
|
|
|
|
|
2023-01-07 20:26:17 +01:00
|
|
|
# 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():
|
2023-01-20 23:34:39 +01:00
|
|
|
return false
|
2023-01-07 20:26:17 +01:00
|
|
|
|
|
|
|
|
|
|
|
func get_rich_text_edit():
|
|
|
|
return _ctrls.output
|
|
|
|
|
|
|
|
|
|
|
|
func load_file(path):
|
|
|
|
var f = FileAccess.open(path, FileAccess.READ)
|
2023-01-20 23:34:39 +01:00
|
|
|
if f == null:
|
2023-01-07 20:26:17 +01:00
|
|
|
return
|
|
|
|
|
|
|
|
var t = f.get_as_text()
|
|
|
|
f.close()
|
|
|
|
_ctrls.output.text = t
|
|
|
|
_ctrls.output.scroll_vertical = _ctrls.output.get_line_count()
|
2023-01-20 23:34:39 +01:00
|
|
|
_ctrls.output.set_deferred("scroll_vertical", _ctrls.output.get_line_count())
|
2023-01-07 20:26:17 +01:00
|
|
|
|
|
|
|
|
|
|
|
func add_text(text):
|
2023-01-20 23:34:39 +01:00
|
|
|
if is_inside_tree():
|
2023-01-07 20:26:17 +01:00
|
|
|
_ctrls.output.text += text
|
|
|
|
|
|
|
|
|
|
|
|
func scroll_to_line(line):
|
|
|
|
_ctrls.output.scroll_vertical = line
|
|
|
|
_ctrls.output.set_caret_line(line)
|