Adds an option to move cursor with right click in TextEdit

Fixes #14832
- Added an option in the editor settings/cursor to make the cursor move with right click.
- If the option is activated (true by default), a right click will move the cursor before displaying context menu.
 - If there is a selection, a right click on it will keep it selected, a right click outside it will unselect it.
 - The option is available in textEdit via an inspector property (or via GDScript): caret_moving_by_right_click
 - The option is available in the script editor and the shader editor via the editor settings
 - The documentation has been updated with the new property, and a few other entries in TextEdit.xml.
This commit is contained in:
MattUV 2017-12-20 02:36:47 +01:00
parent 06dd10b390
commit a55870cd81
6 changed files with 136 additions and 32 deletions

View file

@ -345,18 +345,28 @@
</methods>
<members>
<member name="caret_blink" type="bool" setter="cursor_set_blink_enabled" getter="cursor_get_blink_enabled">
If [code]true[/code] the caret (visual cursor) blinks.
</member>
<member name="caret_blink_speed" type="float" setter="cursor_set_blink_speed" getter="cursor_get_blink_speed">
Duration (in seconds) of a caret's blinking cycle.
</member>
<member name="caret_block_mode" type="bool" setter="cursor_set_block_mode" getter="cursor_is_block_mode">
If [code]true[/code] the caret displays as a rectangle.
If [code]false[/code] the caret displays as a bar.
</member>
<member name="caret_moving_by_right_click" type="bool" setter="set_right_click_moves_caret" getter="is_right_click_moving_caret">
If [code]true[/code] a right click moves the cursor at the mouse position before displaying the context menu.
If [code]false[/code] the context menu disregards mouse location.
</member>
<member name="context_menu_enabled" type="bool" setter="set_context_menu_enabled" getter="is_context_menu_enabled">
If [code]true[/code] a right click displays the context menu.
</member>
<member name="hiding_enabled" type="int" setter="set_hiding_enabled" getter="is_hiding_enabled">
</member>
<member name="highlight_all_occurrences" type="bool" setter="set_highlight_all_occurrences" getter="is_highlight_all_occurrences_enabled">
</member>
<member name="highlight_current_line" type="bool" setter="set_highlight_current_line" getter="is_highlight_current_line_enabled">
If [code]true[/code] the line containing the cursor is highlighted.
</member>
<member name="override_selected_font_color" type="bool" setter="set_override_selected_font_color" getter="is_overriding_selected_font_color">
</member>
@ -364,6 +374,7 @@
If [code]true[/code] read-only mode is enabled. Existing text cannot be modified and new text cannot be added.
</member>
<member name="show_line_numbers" type="bool" setter="set_show_line_numbers" getter="is_show_line_numbers_enabled">
If [code]true[/code] line numbers are displayed to the left of the text.
</member>
<member name="smooth_scrolling" type="bool" setter="set_smooth_scroll_enable" getter="is_smooth_scroll_enabled">
</member>
@ -419,16 +430,22 @@
Search from end to beginning.
</constant>
<constant name="MENU_CUT" value="0" enum="MenuItems">
Cuts (Copies and clears) the selected text.
</constant>
<constant name="MENU_COPY" value="1" enum="MenuItems">
Copies the selected text.
</constant>
<constant name="MENU_PASTE" value="2" enum="MenuItems">
Pastes the clipboard text over the selected text (or at the cursor's position).
</constant>
<constant name="MENU_CLEAR" value="3" enum="MenuItems">
Erases the whole [TextEdit] text.
</constant>
<constant name="MENU_SELECT_ALL" value="4" enum="MenuItems">
Selects the whole [TextEdit] text.
</constant>
<constant name="MENU_UNDO" value="5" enum="MenuItems">
Undoes the previous action.
</constant>
<constant name="MENU_MAX" value="6" enum="MenuItems">
</constant>

View file

@ -351,6 +351,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/cursor/caret_blink", true);
_initial_set("text_editor/cursor/caret_blink_speed", 0.65);
hints["text_editor/cursor/caret_blink_speed"] = PropertyInfo(Variant::REAL, "text_editor/cursor/caret_blink_speed", PROPERTY_HINT_RANGE, "0.1, 10, 0.1");
_initial_set("text_editor/cursor/right_click_moves_caret", true);
_initial_set("text_editor/theme/font", "");
hints["text_editor/theme/font"] = PropertyInfo(Variant::STRING, "text_editor/theme/font", PROPERTY_HINT_GLOBAL_FILE, "*.font,*.tres,*.res");

View file

@ -1396,48 +1396,70 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
if (mb.is_valid()) {
if (mb->get_button_index() == BUTTON_RIGHT && !mb->is_pressed()) {
if (mb->get_button_index() == BUTTON_RIGHT) {
int col, row;
TextEdit *tx = code_editor->get_text_edit();
tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col);
Vector2 mpos = mb->get_global_position() - tx->get_global_position();
bool have_selection = (tx->get_selection_text().length() > 0);
bool have_color = (tx->get_word_at_pos(mpos) == "Color");
tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
bool has_color = (tx->get_word_at_pos(mpos) == "Color");
int fold_state = 0;
bool can_fold = tx->can_fold(row);
bool is_folded = tx->is_folded(row);
if (have_color) {
String line = tx->get_line(row);
color_line = row;
int begin = 0;
int end = 0;
bool valid = false;
for (int i = col; i < line.length(); i++) {
if (line[i] == '(') {
begin = i;
continue;
} else if (line[i] == ')') {
end = i + 1;
valid = true;
break;
if (tx->is_right_click_moving_caret()) {
if (tx->is_selection_active()) {
int from_line = tx->get_selection_from_line();
int to_line = tx->get_selection_to_line();
int from_column = tx->get_selection_from_column();
int to_column = tx->get_selection_to_column();
if (row < from_line || row > to_line || (row == from_line && col < from_column) || (row == to_line && col > to_column)) {
// Right click is outside the seleted text
tx->deselect();
}
}
if (valid) {
color_args = line.substr(begin, end - begin);
String stripped = color_args.replace(" ", "").replace("(", "").replace(")", "");
Vector<float> color = stripped.split_floats(",");
if (color.size() > 2) {
float alpha = color.size() > 3 ? color[3] : 1.0f;
color_picker->set_pick_color(Color(color[0], color[1], color[2], alpha));
}
color_panel->set_position(get_global_transform().xform(get_local_mouse_position()));
} else {
have_color = false;
if (!tx->is_selection_active()) {
tx->cursor_set_line(row, true, false);
tx->cursor_set_column(col);
}
}
_make_context_menu(have_selection, have_color, can_fold, is_folded);
if (!mb->is_pressed()) {
if (has_color) {
String line = tx->get_line(row);
color_line = row;
int begin = 0;
int end = 0;
bool valid = false;
for (int i = col; i < line.length(); i++) {
if (line[i] == '(') {
begin = i;
continue;
} else if (line[i] == ')') {
end = i + 1;
valid = true;
break;
}
}
if (valid) {
color_args = line.substr(begin, end - begin);
String stripped = color_args.replace(" ", "").replace("(", "").replace(")", "");
Vector<float> color = stripped.split_floats(",");
if (color.size() > 2) {
float alpha = color.size() > 3 ? color[3] : 1.0f;
color_picker->set_pick_color(Color(color[0], color[1], color[2], alpha));
}
color_panel->set_position(get_global_transform().xform(get_local_mouse_position()));
} else {
has_color = false;
}
}
_make_context_menu(tx->is_selection_active(), has_color, can_fold, is_folded);
}
}
}
}

View file

@ -620,14 +620,36 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
if (mb.is_valid()) {
if (mb->get_button_index() == BUTTON_RIGHT && !mb->is_pressed()) {
if (mb->get_button_index() == BUTTON_RIGHT) {
int col, row;
TextEdit *tx = shader_editor->get_text_edit();
tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col);
Vector2 mpos = mb->get_global_position() - tx->get_global_position();
bool have_selection = (tx->get_selection_text().length() > 0);
_make_context_menu(have_selection);
tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
if (tx->is_right_click_moving_caret()) {
if (tx->is_selection_active()) {
int from_line = tx->get_selection_from_line();
int to_line = tx->get_selection_to_line();
int from_column = tx->get_selection_from_column();
int to_column = tx->get_selection_to_column();
if (row < from_line || row > to_line || (row == from_line && col < from_column) || (row == to_line && col > to_column)) {
// Right click is outside the seleted text
tx->deselect();
}
}
if (!tx->is_selection_active()) {
tx->cursor_set_line(row, true, false);
tx->cursor_set_column(col);
}
}
if (!mb->is_pressed()) {
_make_context_menu(tx->is_selection_active());
}
}
}
}

View file

@ -1973,6 +1973,31 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb->get_button_index() == BUTTON_RIGHT && context_menu_enabled) {
_reset_caret_blink_timer();
int row, col;
update_line_scroll_pos();
_get_mouse_pos(Point2i(mb->get_position().x, mb->get_position().y), row, col);
if (is_right_click_moving_caret()) {
if (is_selection_active()) {
int from_line = get_selection_from_line();
int to_line = get_selection_to_line();
int from_column = get_selection_from_column();
int to_column = get_selection_to_column();
if (row < from_line || row > to_line || (row == from_line && col < from_column) || (row == to_line && col > to_column)) {
// Right click is outside the seleted text
deselect();
}
}
if (!is_selection_active()) {
cursor_set_line(row, true, false);
cursor_set_column(col);
}
}
menu->set_position(get_global_transform().xform(get_local_mouse_position()));
menu->set_size(Vector2(1, 1));
menu->popup();
@ -3708,6 +3733,14 @@ bool TextEdit::cursor_is_block_mode() const {
return block_caret;
}
void TextEdit::set_right_click_moves_caret(bool p_enable) {
right_click_moves_caret = p_enable;
}
bool TextEdit::is_right_click_moving_caret() const {
return right_click_moves_caret;
}
void TextEdit::_v_scroll_input() {
scrolling = false;
}
@ -5457,6 +5490,9 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("cursor_set_block_mode", "enable"), &TextEdit::cursor_set_block_mode);
ClassDB::bind_method(D_METHOD("cursor_is_block_mode"), &TextEdit::cursor_is_block_mode);
ClassDB::bind_method(D_METHOD("set_right_click_moves_caret", "enable"), &TextEdit::set_right_click_moves_caret);
ClassDB::bind_method(D_METHOD("is_right_click_moving_caret"), &TextEdit::is_right_click_moving_caret);
ClassDB::bind_method(D_METHOD("set_readonly", "enable"), &TextEdit::set_readonly);
ClassDB::bind_method(D_METHOD("is_readonly"), &TextEdit::is_readonly);
@ -5540,6 +5576,7 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_block_mode"), "cursor_set_block_mode", "cursor_is_block_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "cursor_set_blink_enabled", "cursor_get_blink_enabled");
ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.1"), "cursor_set_blink_speed", "cursor_get_blink_speed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_moving_by_right_click"), "set_right_click_moves_caret", "is_right_click_moving_caret");
ADD_SIGNAL(MethodInfo("cursor_changed"));
ADD_SIGNAL(MethodInfo("text_changed"));
@ -5617,6 +5654,7 @@ TextEdit::TextEdit() {
caret_blink_timer->set_wait_time(0.65);
caret_blink_timer->connect("timeout", this, "_toggle_draw_caret");
cursor_set_blink_enabled(false);
right_click_moves_caret = true;
idle_detect = memnew(Timer);
add_child(idle_detect);

View file

@ -246,6 +246,7 @@ class TextEdit : public Control {
bool draw_caret;
bool window_has_focus;
bool block_caret;
bool right_click_moves_caret;
bool setting_row;
bool wrap;
@ -481,6 +482,9 @@ public:
void cursor_set_block_mode(const bool p_enable);
bool cursor_is_block_mode() const;
void set_right_click_moves_caret(bool p_enable);
bool is_right_click_moving_caret() const;
void set_readonly(bool p_readonly);
bool is_readonly() const;