Added smooth scrolling to TextEdit

This commit is contained in:
Paulb23 2017-08-19 15:23:45 +01:00
parent bacfe7a557
commit a142c9a2f0
6 changed files with 149 additions and 8 deletions

View file

@ -1087,6 +1087,7 @@ void CodeTextEditor::update_editor_settings() {
text_editor->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed"));
text_editor->set_draw_breakpoint_gutter(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_breakpoint_gutter"));
text_editor->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret"));
text_editor->set_smooth_scroll_enabled(EditorSettings::get_singleton()->get("text_editor/open_scripts/smooth_scrolling"));
}
void CodeTextEditor::set_error(const String &p_error) {

View file

@ -615,6 +615,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
set("text_editor/line_numbers/line_length_guideline_column", 80);
hints["text_editor/line_numbers/line_length_guideline_column"] = PropertyInfo(Variant::INT, "text_editor/line_numbers/line_length_guideline_column", PROPERTY_HINT_RANGE, "20, 160, 10");
set("text_editor/open_scripts/smooth_scrolling", true);
set("text_editor/open_scripts/show_members_overview", true);
set("text_editor/files/trim_trailing_whitespace_on_save", false);

View file

@ -98,7 +98,18 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) {
if (ofs < grabber_ofs) {
set_value(get_value() - get_page());
if (scrolling) {
target_scroll = target_scroll - get_page();
} else {
target_scroll = get_value() - get_page();
}
if (smooth_scroll_enabled) {
scrolling = true;
set_fixed_process(true);
} else {
set_value(target_scroll);
}
return;
}
@ -111,8 +122,18 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) {
drag.value_at_click = get_as_ratio();
update();
} else {
if (scrolling) {
target_scroll = target_scroll + get_page();
} else {
target_scroll = get_value() + get_page();
}
set_value(get_value() + get_page());
if (smooth_scroll_enabled) {
scrolling = true;
set_fixed_process(true);
} else {
set_value(target_scroll);
}
}
} else {
@ -311,7 +332,22 @@ void ScrollBar::_notification(int p_what) {
if (p_what == NOTIFICATION_FIXED_PROCESS) {
if (drag_slave_touching) {
if (scrolling) {
if (get_value() != target_scroll) {
double target = target_scroll - get_value();
double dist = sqrt(target * target);
double vel = ((target / dist) * 500) * get_fixed_process_delta_time();
if (vel >= dist) {
set_value(target_scroll);
} else {
set_value(get_value() + vel);
}
} else {
scrolling = false;
set_fixed_process(false);
}
} else if (drag_slave_touching) {
if (drag_slave_touching_deaccel) {
@ -639,6 +675,14 @@ NodePath ScrollBar::get_drag_slave() const {
return drag_slave_path;
}
void ScrollBar::set_smooth_scroll_enabled(bool p_enable) {
smooth_scroll_enabled = p_enable;
}
bool ScrollBar::is_smooth_scroll_enabled() const {
return smooth_scroll_enabled;
}
#if 0
void ScrollBar::mouse_button(const Point2& p_pos, int b->get_button_index(),bool b->is_pressed(),int p_modifier_mask) {
@ -795,6 +839,10 @@ ScrollBar::ScrollBar(Orientation p_orientation) {
drag_slave_touching = false;
drag_slave_touching_deaccel = false;
scrolling = false;
target_scroll = 0;
smooth_scroll_enabled = false;
if (focus_by_default)
set_focus_mode(FOCUS_ALL);
set_step(0);

View file

@ -83,6 +83,10 @@ class ScrollBar : public Range {
bool drag_slave_touching_deaccel;
bool click_handled;
bool scrolling;
double target_scroll;
bool smooth_scroll_enabled;
void _drag_slave_exit();
void _drag_slave_input(const Ref<InputEvent> &p_input);
@ -100,6 +104,9 @@ public:
void set_drag_slave(const NodePath &p_path);
NodePath get_drag_slave() const;
void set_smooth_scroll_enabled(bool p_enable);
bool is_smooth_scroll_enabled() const;
virtual Size2 get_minimum_size() const;
ScrollBar(Orientation p_orientation = VERTICAL);
~ScrollBar();

View file

@ -338,6 +338,11 @@ void TextEdit::_update_scrollbars() {
v_scroll->show();
v_scroll->set_max(total_rows);
v_scroll->set_page(visible_rows);
if (smooth_scroll_enabled) {
v_scroll->set_step(0.25);
} else {
v_scroll->set_step(1);
}
if (fabs(v_scroll->get_value() - (double)cursor.line_ofs) >= 1) {
v_scroll->set_value(cursor.line_ofs);
@ -420,6 +425,24 @@ void TextEdit::_notification(int p_what) {
draw_caret = false;
update();
} break;
case NOTIFICATION_FIXED_PROCESS: {
if (scrolling && v_scroll->get_value() != target_v_scroll) {
double target_y = target_v_scroll - v_scroll->get_value();
double dist = sqrt(target_y * target_y);
double vel = ((target_y / dist) * 50) * get_fixed_process_delta_time();
if (vel >= dist) {
v_scroll->set_value(target_v_scroll);
scrolling = false;
set_fixed_process(false);
} else {
v_scroll->set_value(v_scroll->get_value() + vel);
}
} else {
scrolling = false;
set_fixed_process(false);
}
} break;
case NOTIFICATION_DRAW: {
if ((!has_focus() && !menu->has_focus()) || !window_has_focus) {
@ -454,6 +477,7 @@ void TextEdit::_notification(int p_what) {
_update_scrollbars();
RID ci = get_canvas_item();
VisualServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), true);
int xmargin_beg = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width;
int xmargin_end = cache.size.width - cache.style_normal->get_margin(MARGIN_RIGHT);
//let's do it easy for now:
@ -674,7 +698,11 @@ void TextEdit::_notification(int p_what) {
int char_margin = xmargin_beg - cursor.x_ofs;
int char_ofs = 0;
int ofs_y = i * get_row_height() + cache.line_spacing / 2;
int ofs_y = (i * get_row_height() + cache.line_spacing / 2);
if (smooth_scroll_enabled) {
ofs_y -= (v_scroll->get_value() - cursor.line_ofs) * get_row_height();
}
bool prev_is_char = false;
bool prev_is_number = false;
bool in_keyword = false;
@ -1500,7 +1528,7 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co
float rows = p_mouse.y;
rows -= cache.style_normal->get_margin(MARGIN_TOP);
rows /= get_row_height();
int row = cursor.line_ofs + rows;
int row = cursor.line_ofs + (rows + (v_scroll->get_value() - cursor.line_ofs));
if (row < 0)
row = 0;
@ -1566,10 +1594,43 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb->is_pressed()) {
if (mb->get_button_index() == BUTTON_WHEEL_UP && !mb->get_command()) {
v_scroll->set_value(v_scroll->get_value() - (3 * mb->get_factor()));
if (scrolling) {
target_v_scroll = (target_v_scroll - (3 * mb->get_factor()));
} else {
target_v_scroll = (v_scroll->get_value() - (3 * mb->get_factor()));
}
if (smooth_scroll_enabled) {
if (target_v_scroll <= 0) {
target_v_scroll = 0;
}
scrolling = true;
set_fixed_process(true);
} else {
v_scroll->set_value(target_v_scroll);
}
}
if (mb->get_button_index() == BUTTON_WHEEL_DOWN && !mb->get_command()) {
v_scroll->set_value(v_scroll->get_value() + (3 * mb->get_factor()));
if (scrolling) {
target_v_scroll = (target_v_scroll + (3 * mb->get_factor()));
} else {
target_v_scroll = (v_scroll->get_value() + (3 * mb->get_factor()));
}
if (smooth_scroll_enabled) {
int max_v_scroll = get_line_count() - 1;
if (!scroll_past_end_of_file_enabled) {
max_v_scroll -= get_visible_rows() - 1;
}
if (target_v_scroll > max_v_scroll) {
target_v_scroll = max_v_scroll;
}
scrolling = true;
set_fixed_process(true);
} else {
v_scroll->set_value(target_v_scroll);
}
}
if (mb->get_button_index() == BUTTON_WHEEL_LEFT) {
h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor()));
@ -3092,7 +3153,7 @@ int TextEdit::get_visible_rows() const {
int total = cache.size.height;
total -= cache.style_normal->get_minimum_size().height;
total /= get_row_height();
return total;
return total + 1;
}
void TextEdit::adjust_viewport_to_cursor() {
@ -4194,6 +4255,15 @@ void TextEdit::set_h_scroll(int p_scroll) {
h_scroll->set_value(p_scroll);
}
void TextEdit::set_smooth_scroll_enabled(bool p_enable) {
v_scroll->set_smooth_scroll_enabled(p_enable);
smooth_scroll_enabled = p_enable;
}
bool TextEdit::is_smooth_scroll_enabled() const {
return smooth_scroll_enabled;
}
void TextEdit::set_completion(bool p_enabled, const Vector<String> &p_prefixes) {
completion_prefixes.clear();
@ -4694,6 +4764,9 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_syntax_coloring", "enable"), &TextEdit::set_syntax_coloring);
ClassDB::bind_method(D_METHOD("is_syntax_coloring_enabled"), &TextEdit::is_syntax_coloring_enabled);
ClassDB::bind_method(D_METHOD("set_smooth_scroll_enable", "enable"), &TextEdit::set_smooth_scroll_enabled);
ClassDB::bind_method(D_METHOD("is_smooth_scroll_enabled"), &TextEdit::is_smooth_scroll_enabled);
ClassDB::bind_method(D_METHOD("add_keyword_color", "keyword", "color"), &TextEdit::add_keyword_color);
ClassDB::bind_method(D_METHOD("add_color_region", "begin_key", "end_key", "color", "line_only"), &TextEdit::add_color_region, DEFVAL(false));
ClassDB::bind_method(D_METHOD("clear_colors"), &TextEdit::clear_colors);
@ -4703,6 +4776,7 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), "set_syntax_coloring", "is_syntax_coloring_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), "set_show_line_numbers", "is_show_line_numbers_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), "set_highlight_all_occurrences", "is_highlight_all_occurrences_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_scrolling"), "set_smooth_scroll_enable", "is_smooth_scroll_enabled");
ADD_GROUP("Caret", "caret_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_block_mode"), "cursor_set_block_mode", "cursor_is_block_mode");
@ -4839,6 +4913,9 @@ TextEdit::TextEdit() {
insert_mode = false;
window_has_focus = true;
select_identifiers_enabled = false;
smooth_scroll_enabled = false;
scrolling = false;
target_v_scroll = 0;
raised_from_completion = false;

View file

@ -256,6 +256,10 @@ class TextEdit : public Control {
bool insert_mode;
bool select_identifiers_enabled;
bool smooth_scroll_enabled;
bool scrolling;
float target_v_scroll;
bool raised_from_completion;
String highlighted_word;
@ -487,6 +491,9 @@ public:
int get_h_scroll() const;
void set_h_scroll(int p_scroll);
void set_smooth_scroll_enabled(bool p_enable);
bool is_smooth_scroll_enabled() const;
uint32_t get_version() const;
uint32_t get_saved_version() const;
void tag_saved_version();