Merge pull request #115767 from DexterFstone/Add-a-script-editor-keyboard-shortcut-to-show-the-documentation-tooltip-for-the-word-the-caret-is-on
Add a script editor keyboard shortcut to show the documentation tooltip for the word the caret is on
This commit is contained in:
commit
b6b7f5a9de
4 changed files with 52 additions and 21 deletions
|
|
@ -4640,6 +4640,20 @@ void EditorHelpBitTooltip::_target_gui_input(const Ref<InputEvent> &p_event) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const Ref<InputEventKey> k = p_event;
|
||||
if (k.is_valid() && k->is_pressed()) {
|
||||
queue_free();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorHelpBitTooltip::_shortcut_pressed(Control *p_target) {
|
||||
TextEdit *tx = Object::cast_to<TextEdit>(p_target);
|
||||
if (tx) {
|
||||
popup_under_position(
|
||||
tx->get_global_position() + tx->get_caret_draw_pos() +
|
||||
Point2(0, tx->get_line_height()) + tx->get_window()->get_position_with_decorations());
|
||||
}
|
||||
}
|
||||
|
||||
void EditorHelpBitTooltip::_notification(int p_what) {
|
||||
|
|
@ -4659,7 +4673,7 @@ void EditorHelpBitTooltip::_notification(int p_what) {
|
|||
_is_mouse_inside_tooltip = false;
|
||||
_start_timer();
|
||||
break;
|
||||
case NOTIFICATION_INTERNAL_PROCESS:
|
||||
case NOTIFICATION_INTERNAL_PROCESS: {
|
||||
// A workaround to hide the tooltip since the window does not receive keyboard events
|
||||
// with `FLAG_POPUP` and `FLAG_NO_FOCUS` flags, so we can't use `_input_from_window()`.
|
||||
if (is_inside_tree()) {
|
||||
|
|
@ -4667,9 +4681,11 @@ void EditorHelpBitTooltip::_notification(int p_what) {
|
|||
queue_free();
|
||||
get_parent_viewport()->set_input_as_handled();
|
||||
} else if (Input::get_singleton()->is_any_key_pressed()) {
|
||||
queue_free();
|
||||
if (!_is_shortcut_pressed) {
|
||||
queue_free();
|
||||
}
|
||||
} else if (!Input::get_singleton()->get_mouse_button_mask().is_empty()) {
|
||||
if (!_is_mouse_inside_tooltip) {
|
||||
if (!_is_mouse_inside_tooltip && !_is_shortcut_pressed) {
|
||||
queue_free();
|
||||
}
|
||||
} else if (!Input::get_singleton()->get_last_mouse_velocity().is_zero_approx()) {
|
||||
|
|
@ -4678,38 +4694,41 @@ void EditorHelpBitTooltip::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
Control *EditorHelpBitTooltip::make_tooltip(Control *p_target, const String &p_symbol, const String &p_prologue, bool p_use_class_prefix) {
|
||||
Control *EditorHelpBitTooltip::make_tooltip(Control *p_target, const String &p_symbol, const String &p_prologue, bool p_use_class_prefix, bool p_shortcut) {
|
||||
ERR_FAIL_NULL_V(p_target, _make_invisible_control());
|
||||
|
||||
// Show the custom tooltip only if it is not already visible.
|
||||
// The viewport will retrigger `make_custom_tooltip()` every few seconds
|
||||
// because the return control is not visible even if the custom tooltip is displayed.
|
||||
if (_is_tooltip_visible || Input::get_singleton()->is_anything_pressed()) {
|
||||
if (_is_tooltip_visible || (!p_shortcut && Input::get_singleton()->is_anything_pressed())) {
|
||||
return _make_invisible_control();
|
||||
}
|
||||
|
||||
EditorHelpBit *help_bit = memnew(EditorHelpBit(p_symbol, p_prologue, p_use_class_prefix, false, true));
|
||||
|
||||
EditorHelpBitTooltip *tooltip = memnew(EditorHelpBitTooltip(p_target));
|
||||
EditorHelpBitTooltip *tooltip = memnew(EditorHelpBitTooltip(p_target, p_shortcut));
|
||||
help_bit->connect("request_hide", callable_mp(static_cast<Node *>(tooltip), &Node::queue_free));
|
||||
tooltip->add_child(help_bit);
|
||||
p_target->add_child(tooltip);
|
||||
|
||||
help_bit->update_content_height();
|
||||
tooltip->popup_under_cursor();
|
||||
if (tooltip->is_shortcut_pressed()) {
|
||||
tooltip->_shortcut_pressed(p_target);
|
||||
} else {
|
||||
tooltip->popup_under_position(tooltip->get_mouse_position());
|
||||
}
|
||||
|
||||
return _make_invisible_control();
|
||||
}
|
||||
|
||||
// Copy-paste from `Viewport::_gui_show_tooltip()`.
|
||||
void EditorHelpBitTooltip::popup_under_cursor() {
|
||||
Point2 mouse_pos = get_mouse_position();
|
||||
void EditorHelpBitTooltip::popup_under_position(const Point2 &p_point) {
|
||||
Point2 tooltip_offset = GLOBAL_GET_CACHED(Point2, "display/mouse_cursor/tooltip_position_offset");
|
||||
Rect2 r(mouse_pos + tooltip_offset, get_contents_minimum_size());
|
||||
Rect2 r(p_point + tooltip_offset, get_contents_minimum_size());
|
||||
r.size = r.size.min(get_max_size());
|
||||
|
||||
Window *window = get_parent_visible_window();
|
||||
|
|
@ -4723,7 +4742,7 @@ void EditorHelpBitTooltip::popup_under_cursor() {
|
|||
if (!DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_SELF_FITTING_WINDOWS) || is_embedded()) {
|
||||
if (r.size.x + r.position.x > vr.size.x + vr.position.x) {
|
||||
// Place it in the opposite direction. If it fails, just hug the border.
|
||||
r.position.x = mouse_pos.x - r.size.x - tooltip_offset.x;
|
||||
r.position.x = p_point.x - r.size.x - tooltip_offset.x;
|
||||
|
||||
if (r.position.x < vr.position.x) {
|
||||
r.position.x = vr.position.x + vr.size.x - r.size.x;
|
||||
|
|
@ -4734,7 +4753,7 @@ void EditorHelpBitTooltip::popup_under_cursor() {
|
|||
|
||||
if (r.size.y + r.position.y > vr.size.y + vr.position.y) {
|
||||
// Same as above.
|
||||
r.position.y = mouse_pos.y - r.size.y - tooltip_offset.y;
|
||||
r.position.y = p_point.y - r.size.y - tooltip_offset.y;
|
||||
|
||||
if (r.position.y < vr.position.y) {
|
||||
r.position.y = vr.position.y + vr.size.y - r.size.y;
|
||||
|
|
@ -4751,9 +4770,11 @@ void EditorHelpBitTooltip::popup_under_cursor() {
|
|||
popup(r);
|
||||
}
|
||||
|
||||
EditorHelpBitTooltip::EditorHelpBitTooltip(Control *p_target) {
|
||||
EditorHelpBitTooltip::EditorHelpBitTooltip(Control *p_target, bool p_shortcut) {
|
||||
ERR_FAIL_NULL(p_target);
|
||||
|
||||
_is_shortcut_pressed = p_shortcut;
|
||||
|
||||
set_theme_type_variation("TooltipPanel");
|
||||
|
||||
timer = memnew(Timer);
|
||||
|
|
|
|||
|
|
@ -369,22 +369,26 @@ class EditorHelpBitTooltip : public PopupPanel {
|
|||
Timer *timer = nullptr;
|
||||
uint64_t _enter_tree_time = 0;
|
||||
bool _is_mouse_inside_tooltip = false;
|
||||
bool _is_shortcut_pressed = false;
|
||||
|
||||
static Control *_make_invisible_control();
|
||||
|
||||
void _start_timer();
|
||||
void _target_gui_input(const Ref<InputEvent> &p_event);
|
||||
void _shortcut_pressed(Control *p_target);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
// The returned control is an orphan node, which is to make the standard tooltip invisible.
|
||||
[[nodiscard]] static Control *make_tooltip(Control *p_target, const String &p_symbol, const String &p_prologue = String(), bool p_use_class_prefix = false);
|
||||
[[nodiscard]] static Control *make_tooltip(Control *p_target, const String &p_symbol, const String &p_prologue = String(), bool p_use_class_prefix = false, bool p_shortcut = false);
|
||||
|
||||
void popup_under_cursor();
|
||||
void popup_under_position(const Point2 &p_point);
|
||||
|
||||
EditorHelpBitTooltip(Control *p_target);
|
||||
bool is_shortcut_pressed() const { return _is_shortcut_pressed; }
|
||||
|
||||
EditorHelpBitTooltip(Control *p_target, bool p_shortcut = false);
|
||||
};
|
||||
|
||||
class EditorSyntaxHighlighter;
|
||||
|
|
|
|||
|
|
@ -184,6 +184,7 @@ ScriptTextEditor::EditMenusSTE::EditMenusSTE() {
|
|||
edit_menu_convert_indent->add_shortcut(ED_GET_SHORTCUT("script_text_editor/auto_indent"), EDIT_AUTO_INDENT);
|
||||
|
||||
search_menu->get_popup()->add_separator();
|
||||
search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/show_tooltip"), SHOW_TOOLTIP_AT_CARET);
|
||||
search_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/contextual_help"), HELP_CONTEXTUAL);
|
||||
|
||||
breakpoints_menu = memnew(PopupMenu);
|
||||
|
|
@ -1300,7 +1301,7 @@ void ScriptTextEditor::_validate_symbol(const String &p_symbol) {
|
|||
}
|
||||
}
|
||||
|
||||
void ScriptTextEditor::_show_symbol_tooltip(const String &p_symbol, int p_row, int p_column) {
|
||||
void ScriptTextEditor::_show_symbol_tooltip(const String &p_symbol, int p_row, int p_column, bool p_shortcut) {
|
||||
if (!EDITOR_GET("text_editor/behavior/documentation/enable_tooltips").booleanize()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -1418,7 +1419,7 @@ void ScriptTextEditor::_show_symbol_tooltip(const String &p_symbol, int p_row, i
|
|||
}
|
||||
|
||||
if (!doc_symbol.is_empty() || !debug_value.is_empty()) {
|
||||
Control *tmp = EditorHelpBitTooltip::make_tooltip(code_editor->get_text_editor(), doc_symbol, debug_value, true);
|
||||
Control *tmp = EditorHelpBitTooltip::make_tooltip(code_editor->get_text_editor(), doc_symbol, debug_value, true, p_shortcut);
|
||||
memdelete(tmp);
|
||||
}
|
||||
}
|
||||
|
|
@ -1793,6 +1794,9 @@ bool ScriptTextEditor::_edit_option(int p_op) {
|
|||
}
|
||||
code_editor->goto_line_centered(bpoints[bpoint_idx]);
|
||||
} break;
|
||||
case SHOW_TOOLTIP_AT_CARET: {
|
||||
_show_symbol_tooltip(tx->get_word_under_caret(), tx->get_caret_line(), tx->get_caret_column(), true);
|
||||
} break;
|
||||
case HELP_CONTEXTUAL: {
|
||||
String text = tx->get_selected_text(0);
|
||||
if (text.is_empty()) {
|
||||
|
|
@ -2565,6 +2569,7 @@ void ScriptTextEditor::register_editor() {
|
|||
|
||||
ED_SHORTCUT("script_text_editor/replace_in_files", TTRC("Replace in Files..."), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::R);
|
||||
|
||||
ED_SHORTCUT("script_text_editor/show_tooltip", TTRC("Show Tooltip"), KeyModifierMask::ALT | Key::SLASH, true);
|
||||
ED_SHORTCUT("script_text_editor/contextual_help", TTRC("Contextual Help"), KeyModifierMask::ALT | Key::F1);
|
||||
ED_SHORTCUT_OVERRIDE("script_text_editor/contextual_help", "macos", KeyModifierMask::ALT | KeyModifierMask::SHIFT | Key::SPACE);
|
||||
|
||||
|
|
@ -2598,7 +2603,7 @@ void ScriptTextEditor::_enable_code_editor() {
|
|||
code_editor->connect("show_errors_panel", callable_mp(this, &ScriptTextEditor::_show_errors_panel));
|
||||
code_editor->connect("show_warnings_panel", callable_mp(this, &ScriptTextEditor::_show_warnings_panel));
|
||||
code_editor->get_text_editor()->connect("symbol_lookup", callable_mp(this, &ScriptTextEditor::_lookup_symbol));
|
||||
code_editor->get_text_editor()->connect("symbol_hovered", callable_mp(this, &ScriptTextEditor::_show_symbol_tooltip));
|
||||
code_editor->get_text_editor()->connect("symbol_hovered", callable_mp(this, &ScriptTextEditor::_show_symbol_tooltip).bind(false));
|
||||
code_editor->get_text_editor()->connect("symbol_validate", callable_mp(this, &ScriptTextEditor::_validate_symbol));
|
||||
code_editor->get_text_editor()->connect("gutter_added", callable_mp(this, &ScriptTextEditor::_update_gutter_indexes));
|
||||
code_editor->get_text_editor()->connect("gutter_removed", callable_mp(this, &ScriptTextEditor::_update_gutter_indexes));
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ class ScriptTextEditor : public CodeEditorBase {
|
|||
DEBUG_GOTO_NEXT_BREAKPOINT,
|
||||
DEBUG_GOTO_PREV_BREAKPOINT,
|
||||
|
||||
SHOW_TOOLTIP_AT_CARET,
|
||||
HELP_CONTEXTUAL,
|
||||
LOOKUP_SYMBOL,
|
||||
};
|
||||
|
|
@ -191,7 +192,7 @@ protected:
|
|||
void _lookup_symbol(const String &p_symbol, int p_row, int p_column);
|
||||
void _validate_symbol(const String &p_symbol);
|
||||
|
||||
void _show_symbol_tooltip(const String &p_symbol, int p_row, int p_column);
|
||||
void _show_symbol_tooltip(const String &p_symbol, int p_row, int p_column, bool p_shortcut = false);
|
||||
|
||||
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
|
||||
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue