mirror of
https://github.com/godotengine/godot.git
synced 2025-12-08 06:09:55 +00:00
Merge pull request #106919 from kitbdev/fix-codeedit-hover-word-lookup
Fix CodeEdit hover word lookup
This commit is contained in:
commit
d4fa7e15ed
7 changed files with 59 additions and 79 deletions
|
|
@ -59,34 +59,6 @@ static _FORCE_INLINE_ char32_t lower_case(char32_t c) {
|
|||
return (is_ascii_upper_case(c) ? (c + ('a' - 'A')) : c);
|
||||
}
|
||||
|
||||
bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end) {
|
||||
const String &s = p_s;
|
||||
int beg = CLAMP(p_col, 0, s.length());
|
||||
int end = beg;
|
||||
|
||||
if (s[beg] > 32 || beg == s.length()) {
|
||||
bool symbol = beg < s.length() && is_symbol(s[beg]);
|
||||
|
||||
while (beg > 0 && s[beg - 1] > 32 && (symbol == is_symbol(s[beg - 1]))) {
|
||||
beg--;
|
||||
}
|
||||
while (end < s.length() && s[end + 1] > 32 && (symbol == is_symbol(s[end + 1]))) {
|
||||
end++;
|
||||
}
|
||||
|
||||
if (end < s.length()) {
|
||||
end += 1;
|
||||
}
|
||||
|
||||
r_beg = beg;
|
||||
r_end = end;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r_path, String &r_fragment) const {
|
||||
// Splits the URL into scheme, host, port, path, fragment. Strip credentials when present.
|
||||
String base = *this;
|
||||
|
|
|
|||
|
|
@ -787,8 +787,6 @@ _FORCE_INLINE_ String ETRN(const String &p_text, const String &p_text_plural, in
|
|||
return p_text_plural;
|
||||
}
|
||||
|
||||
bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end);
|
||||
|
||||
template <typename... P>
|
||||
_FORCE_INLINE_ Vector<String> sarray(P... p_args) {
|
||||
return Vector<String>({ String(p_args)... });
|
||||
|
|
|
|||
|
|
@ -2410,7 +2410,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
|
|||
}
|
||||
}
|
||||
|
||||
String word_at_pos = tx->get_word_at_pos(local_pos);
|
||||
String word_at_pos = tx->get_lookup_word(mouse_line, mouse_column);
|
||||
if (word_at_pos.is_empty()) {
|
||||
word_at_pos = tx->get_word_under_caret(selection_clicked);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
|
|||
if (symbol_lookup_on_click_enabled) {
|
||||
if (mm->is_command_or_control_pressed() && mm->get_button_mask().is_empty()) {
|
||||
symbol_lookup_pos = get_line_column_at_pos(mpos, false, false);
|
||||
symbol_lookup_new_word = get_word_at_pos(mpos);
|
||||
symbol_lookup_new_word = get_lookup_word(symbol_lookup_pos.y, symbol_lookup_pos.x);
|
||||
if (symbol_lookup_new_word != symbol_lookup_word) {
|
||||
emit_signal(SNAME("symbol_validate"), symbol_lookup_new_word);
|
||||
}
|
||||
|
|
@ -454,7 +454,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
|
|||
|
||||
if (symbol_tooltip_on_hover_enabled) {
|
||||
symbol_tooltip_pos = get_line_column_at_pos(mpos, false, false);
|
||||
symbol_tooltip_word = get_word_at_pos(mpos);
|
||||
symbol_tooltip_word = get_lookup_word(symbol_tooltip_pos.y, symbol_tooltip_pos.x);
|
||||
symbol_tooltip_timer->start();
|
||||
}
|
||||
|
||||
|
|
@ -499,7 +499,8 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
|
|||
if ((mac_keys && k->get_keycode() == Key::META) || (!mac_keys && k->get_keycode() == Key::CTRL)) {
|
||||
if (symbol_lookup_on_click_enabled) {
|
||||
if (k->is_pressed() && !is_dragging_cursor()) {
|
||||
symbol_lookup_new_word = get_word_at_pos(get_local_mouse_pos());
|
||||
Point2i lookup_pos = get_line_column_at_pos(get_local_mouse_pos(), false, false);
|
||||
symbol_lookup_new_word = get_lookup_word(lookup_pos.y, lookup_pos.x);
|
||||
if (symbol_lookup_new_word != symbol_lookup_word) {
|
||||
emit_signal(SNAME("symbol_validate"), symbol_lookup_new_word);
|
||||
}
|
||||
|
|
@ -2483,6 +2484,25 @@ String CodeEdit::get_text_with_cursor_char(int p_line, int p_column) const {
|
|||
return result.as_string();
|
||||
}
|
||||
|
||||
String CodeEdit::get_lookup_word(int p_line, int p_column) const {
|
||||
if (p_line < 0 || p_column < 0) {
|
||||
return String();
|
||||
}
|
||||
if (is_in_string(p_line, p_column) != -1) {
|
||||
// Return the string in case it is a path.
|
||||
Point2 start_pos = get_delimiter_start_position(p_line, p_column);
|
||||
Point2 end_pos = get_delimiter_end_position(p_line, p_column);
|
||||
int start_line = start_pos.y;
|
||||
int start_column = start_pos.x;
|
||||
int end_line = end_pos.y;
|
||||
int end_column = end_pos.x;
|
||||
if (start_line == end_line && start_column >= 0 && end_column >= 0) {
|
||||
return get_line(start_line).substr(start_column, end_column - start_column - 1);
|
||||
}
|
||||
}
|
||||
return get_word(p_line, p_column);
|
||||
}
|
||||
|
||||
void CodeEdit::set_symbol_lookup_word_as_valid(bool p_valid) {
|
||||
symbol_lookup_word = p_valid ? symbol_lookup_new_word : "";
|
||||
symbol_lookup_new_word = "";
|
||||
|
|
@ -2506,7 +2526,7 @@ bool CodeEdit::is_symbol_tooltip_on_hover_enabled() const {
|
|||
void CodeEdit::_on_symbol_tooltip_timer_timeout() {
|
||||
const int line = symbol_tooltip_pos.y;
|
||||
const int column = symbol_tooltip_pos.x;
|
||||
if (line >= 0 && column >= 0 && !symbol_tooltip_word.is_empty() && !has_selection() && !Input::get_singleton()->is_anything_pressed()) {
|
||||
if (line >= 0 && column >= 0 && !symbol_tooltip_word.is_empty() && !Input::get_singleton()->is_anything_pressed()) {
|
||||
emit_signal(SNAME("symbol_hovered"), symbol_tooltip_word, line, column);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -504,6 +504,7 @@ public:
|
|||
|
||||
String get_text_for_symbol_lookup() const;
|
||||
String get_text_with_cursor_char(int p_line, int p_column) const;
|
||||
String get_lookup_word(int p_line, int p_column) const;
|
||||
|
||||
void set_symbol_lookup_word_as_valid(bool p_valid);
|
||||
|
||||
|
|
|
|||
|
|
@ -3633,22 +3633,24 @@ String TextEdit::get_tooltip(const Point2 &p_pos) const {
|
|||
return Control::get_tooltip(p_pos);
|
||||
}
|
||||
Point2i pos = get_line_column_at_pos(p_pos);
|
||||
int row = pos.y;
|
||||
int line = pos.y;
|
||||
int col = pos.x;
|
||||
|
||||
String s = text[row];
|
||||
if (s.length() == 0) {
|
||||
const String &text_line = text[line];
|
||||
if (text_line.is_empty()) {
|
||||
return Control::get_tooltip(p_pos);
|
||||
}
|
||||
int beg, end;
|
||||
if (select_word(s, col, beg, end)) {
|
||||
Variant args[1] = { s.substr(beg, end - beg) };
|
||||
const Variant *argp[] = { &args[0] };
|
||||
Callable::CallError ce;
|
||||
Variant ret;
|
||||
tooltip_callback.callp(argp, 1, ret, ce);
|
||||
ERR_FAIL_COND_V_MSG(ce.error != Callable::CallError::CALL_OK, "", "Failed to call custom tooltip.");
|
||||
return ret;
|
||||
const PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
|
||||
for (int i = 0; i < words.size(); i = i + 2) {
|
||||
if (words[i] <= col && words[i + 1] >= col) {
|
||||
Variant args[1] = { text_line.substr(words[i], words[i + 1] - words[i]) };
|
||||
const Variant *argp[] = { &args[0] };
|
||||
Callable::CallError ce;
|
||||
Variant ret;
|
||||
tooltip_callback.callp(argp, 1, ret, ce);
|
||||
ERR_FAIL_COND_V_MSG(ce.error != Callable::CallError::CALL_OK, "", "Failed to call custom tooltip.");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return Control::get_tooltip(p_pos);
|
||||
|
|
@ -4924,43 +4926,29 @@ Point2 TextEdit::get_local_mouse_pos() const {
|
|||
|
||||
String TextEdit::get_word_at_pos(const Vector2 &p_pos) const {
|
||||
Point2i pos = get_line_column_at_pos(p_pos, false, false);
|
||||
int row = pos.y;
|
||||
int line = pos.y;
|
||||
int col = pos.x;
|
||||
if (row < 0 || col < 0) {
|
||||
return "";
|
||||
}
|
||||
return get_word(line, col);
|
||||
}
|
||||
|
||||
String s = text[row];
|
||||
if (s.length() == 0) {
|
||||
return "";
|
||||
String TextEdit::get_word(int p_line, int p_column) const {
|
||||
if (p_line < 0 || p_column < 0) {
|
||||
return String();
|
||||
}
|
||||
int beg, end;
|
||||
if (select_word(s, col, beg, end)) {
|
||||
bool inside_quotes = false;
|
||||
char32_t selected_quote = '\0';
|
||||
int qbegin = 0, qend = 0;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
if (s[i] == '"' || s[i] == '\'') {
|
||||
if (i == 0 || s[i - 1] != '\\') {
|
||||
if (inside_quotes && selected_quote == s[i]) {
|
||||
qend = i;
|
||||
inside_quotes = false;
|
||||
selected_quote = '\0';
|
||||
if (col >= qbegin && col <= qend) {
|
||||
return s.substr(qbegin, qend - qbegin);
|
||||
}
|
||||
} else if (!inside_quotes) {
|
||||
qbegin = i + 1;
|
||||
inside_quotes = true;
|
||||
selected_quote = s[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
ERR_FAIL_INDEX_V(p_line, text.size(), String());
|
||||
|
||||
const String &text_line = text[p_line];
|
||||
if (text_line.is_empty()) {
|
||||
return String();
|
||||
}
|
||||
ERR_FAIL_INDEX_V(p_column, text_line.size() + 1, String());
|
||||
|
||||
const PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(p_line)->get_rid());
|
||||
for (int i = 0; i < words.size(); i = i + 2) {
|
||||
if (words[i] <= p_column && words[i + 1] >= p_column) {
|
||||
return text_line.substr(words[i], words[i + 1] - words[i]);
|
||||
}
|
||||
|
||||
return s.substr(beg, end - beg);
|
||||
}
|
||||
|
||||
return String();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -919,6 +919,7 @@ public:
|
|||
Point2 get_local_mouse_pos() const;
|
||||
|
||||
String get_word_at_pos(const Vector2 &p_pos) const;
|
||||
String get_word(int p_line, int p_column) const;
|
||||
|
||||
Point2i get_line_column_at_pos(const Point2i &p_pos, bool p_clamp_line = true, bool p_clamp_column = true) const;
|
||||
Point2i get_pos_at_line_column(int p_line, int p_column) const;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue