Map highlights to selected text near cursor
This commit is contained in:
@@ -12,6 +12,8 @@ var question_highlights := {}
|
||||
var stem_plain_text := ""
|
||||
var highlight_mode_enabled := false
|
||||
var highlight_drag_started_in_stem := false
|
||||
var highlight_drag_start_position := Vector2.ZERO
|
||||
var highlight_drag_end_position := Vector2.ZERO
|
||||
|
||||
var progress_label: Label
|
||||
var timer_label: Label
|
||||
@@ -160,8 +162,10 @@ func _input(event: InputEvent) -> void:
|
||||
|
||||
if mouse_event.pressed:
|
||||
highlight_drag_started_in_stem = stem_label.get_global_rect().has_point(mouse_event.global_position)
|
||||
highlight_drag_start_position = mouse_event.global_position
|
||||
elif highlight_drag_started_in_stem:
|
||||
highlight_drag_started_in_stem = false
|
||||
highlight_drag_end_position = mouse_event.global_position
|
||||
call_deferred("_commit_current_text_selection")
|
||||
|
||||
|
||||
@@ -311,16 +315,10 @@ func _commit_current_text_selection() -> void:
|
||||
if selected_text == "":
|
||||
return
|
||||
|
||||
var selection_start := stem_label.get_selection_from()
|
||||
var selection_end := stem_label.get_selection_to()
|
||||
if selection_start == selection_end:
|
||||
var selected_range := _find_selected_text_range_near_drag(selected_text)
|
||||
if selected_range.is_empty():
|
||||
return
|
||||
if selection_start > selection_end:
|
||||
var previous_start := selection_start
|
||||
selection_start = selection_end
|
||||
selection_end = previous_start
|
||||
|
||||
_highlight_range(selection_start, selection_end)
|
||||
_highlight_range(int(selected_range["start"]), int(selected_range["end"]))
|
||||
|
||||
|
||||
func _highlight_range(start: int, end: int) -> void:
|
||||
@@ -375,6 +373,35 @@ func _escape_bbcode(value: String) -> String:
|
||||
return value.replace("[", "[lb]").replace("]", "[rb]")
|
||||
|
||||
|
||||
func _find_selected_text_range_near_drag(selected_text: String) -> Dictionary:
|
||||
var matches: Array[Dictionary] = []
|
||||
var search_from := 0
|
||||
while search_from < stem_plain_text.length():
|
||||
var start := stem_plain_text.find(selected_text, search_from)
|
||||
if start == -1:
|
||||
break
|
||||
matches.append({"start": start, "end": start + selected_text.length()})
|
||||
search_from = start + max(1, selected_text.length())
|
||||
|
||||
if matches.is_empty():
|
||||
return {}
|
||||
if matches.size() == 1:
|
||||
return matches[0]
|
||||
|
||||
var local_midpoint := stem_label.get_global_transform().affine_inverse() * ((highlight_drag_start_position + highlight_drag_end_position) * 0.5)
|
||||
var line: int = stem_label.get_line_at_pos(int(local_midpoint.y))
|
||||
var clicked_character: int = stem_label.get_character_line(line)
|
||||
var best_match: Dictionary = matches[0]
|
||||
var best_distance: int = abs(int(best_match["start"]) - clicked_character)
|
||||
for index in range(1, matches.size()):
|
||||
var candidate: Dictionary = matches[index]
|
||||
var distance: int = abs(int(candidate["start"]) - clicked_character)
|
||||
if distance < best_distance:
|
||||
best_distance = distance
|
||||
best_match = candidate
|
||||
return best_match
|
||||
|
||||
|
||||
func _remove_overlapping_highlights(highlights: Array, start: int, end: int) -> bool:
|
||||
var removed := false
|
||||
for index in range(highlights.size() - 1, -1, -1):
|
||||
|
||||
Reference in New Issue
Block a user