muliline text: improve slowdown and line calculation algorithm
This commit is contained in:
parent
cf5cc8ec3f
commit
18a08fbbef
4 changed files with 94 additions and 100 deletions
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2023 - 2024
|
||||
by babaissarkar(Subhraman Sarkar) <suvrax@gmail.com>
|
||||
by Subhraman Sarkar (babaissarkar) <suvrax@gmail.com>
|
||||
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -45,7 +45,6 @@ multiline_text::multiline_text(const implementation::builder_styled_widget& buil
|
|||
, text_y_offset_(0)
|
||||
, text_height_(0)
|
||||
, dragging_(false)
|
||||
, line_num_(0)
|
||||
{
|
||||
set_wants_mouse_left_double_click();
|
||||
|
||||
|
@ -88,17 +87,17 @@ void multiline_text::update_canvas()
|
|||
const unsigned start = get_selection_start();
|
||||
const int length = static_cast<int>(get_selection_length());
|
||||
|
||||
// Set the cursor info.
|
||||
// Set the composition info.
|
||||
const unsigned edit_start = get_composition_start();
|
||||
const int edit_length = get_composition_length();
|
||||
|
||||
set_maximum_length(max_input_length_);
|
||||
|
||||
// Set the composition info
|
||||
unsigned comp_start_offset = 0;
|
||||
unsigned comp_end_offset = 0;
|
||||
|
||||
if(edit_length == 0) {
|
||||
// No nothing.
|
||||
// Do nothing.
|
||||
} else if(edit_length > 0) {
|
||||
comp_start_offset = get_cursor_position(edit_start).x;
|
||||
comp_end_offset = get_cursor_position(edit_start + edit_length).x;
|
||||
|
@ -107,12 +106,25 @@ void multiline_text::update_canvas()
|
|||
comp_end_offset = get_cursor_position(edit_start).x;
|
||||
}
|
||||
|
||||
set_line_num_from_offset();
|
||||
// Set the selection info
|
||||
unsigned start_offset = 0;
|
||||
unsigned end_offset = 0;
|
||||
if(length == 0) {
|
||||
start_offset = start;
|
||||
end_offset = start_offset;
|
||||
} else if(length > 0) {
|
||||
start_offset = start;
|
||||
end_offset = start + length;
|
||||
} else {
|
||||
start_offset = start + length;
|
||||
end_offset = start;
|
||||
}
|
||||
|
||||
/***** Set in all canvases *****/
|
||||
|
||||
const int max_width = get_text_maximum_width();
|
||||
const int max_height = get_text_maximum_height();
|
||||
const point cpos = get_cursor_pos_from_index(start + length);
|
||||
|
||||
for(auto & tmp : get_canvases())
|
||||
{
|
||||
|
@ -126,18 +138,11 @@ void multiline_text::update_canvas()
|
|||
|
||||
tmp.set_variable("editable", wfl::variant(is_editable()));
|
||||
|
||||
if (length < 0) {
|
||||
tmp.set_variable("highlight_start", wfl::variant(get_byte_offset(start+length)));
|
||||
tmp.set_variable("highlight_end", wfl::variant(get_byte_offset(start)));
|
||||
} else {
|
||||
tmp.set_variable("highlight_start", wfl::variant(get_byte_offset(start)));
|
||||
tmp.set_variable("highlight_end", wfl::variant(get_byte_offset(start+length)));
|
||||
}
|
||||
tmp.set_variable("highlight_start", wfl::variant(start_offset));
|
||||
tmp.set_variable("highlight_end", wfl::variant(end_offset));
|
||||
|
||||
tmp.set_variable("cursor_offset_x",
|
||||
wfl::variant(get_cursor_position(start + length).x));
|
||||
tmp.set_variable("cursor_offset_y",
|
||||
wfl::variant(get_cursor_position(start + length).y));
|
||||
tmp.set_variable("cursor_offset_x", wfl::variant(cpos.x));
|
||||
tmp.set_variable("cursor_offset_y", wfl::variant(cpos.y));
|
||||
|
||||
tmp.set_variable("composition_offset", wfl::variant(comp_start_offset));
|
||||
tmp.set_variable("composition_width", wfl::variant(comp_end_offset - comp_start_offset));
|
||||
|
@ -205,8 +210,6 @@ void multiline_text::handle_mouse_selection(point mouse, const bool start_select
|
|||
|
||||
offset += get_line_start_offset(line);
|
||||
|
||||
line_num_ = get_line_num_from_offset(offset);
|
||||
|
||||
set_cursor(offset, !start_selection);
|
||||
|
||||
update_canvas();
|
||||
|
@ -215,37 +218,12 @@ void multiline_text::handle_mouse_selection(point mouse, const bool start_select
|
|||
}
|
||||
|
||||
unsigned multiline_text::get_line_end_offset(unsigned line_no) {
|
||||
// Should be cached if needed
|
||||
std::string line = get_lines().at(line_no);
|
||||
// Get correct number of characters to move for multibyte utf8 string.
|
||||
int line_size = utf8::size(line);
|
||||
return get_line_start_offset(line_no) + line_size;
|
||||
const auto line = get_line(line_no);
|
||||
return (line->start_index + line->length);
|
||||
}
|
||||
|
||||
unsigned multiline_text::get_line_start_offset(unsigned line_no) {
|
||||
if (line_no > 0) {
|
||||
return get_line_end_offset(line_no-1) + 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned multiline_text::get_line_num_from_offset(unsigned offset) {
|
||||
unsigned line_start = 0, line_end = 0, line_no = 0;
|
||||
for(unsigned i = 0; i < get_lines_count(); i++) {
|
||||
line_start = get_line_start_offset(i);
|
||||
line_end = get_line_end_offset(i);
|
||||
if ((offset >= line_start) && (offset <= line_end)) {
|
||||
line_no = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return line_no;
|
||||
}
|
||||
|
||||
void multiline_text::set_line_num_from_offset()
|
||||
{
|
||||
line_num_ = get_line_num_from_offset(get_selection_start());
|
||||
return get_line(line_no)->start_index;
|
||||
}
|
||||
|
||||
void multiline_text::update_offsets()
|
||||
|
@ -341,16 +319,22 @@ void multiline_text::handle_key_down_arrow(SDL_Keymod modifier, bool& handled)
|
|||
|
||||
handled = true;
|
||||
|
||||
set_line_num_from_offset();
|
||||
size_t offset = get_selection_start();
|
||||
const unsigned line_num = get_line_number(offset);
|
||||
|
||||
if (line_num_ < get_lines_count()-1) {
|
||||
offset = offset
|
||||
- get_line_start_offset(line_num_)
|
||||
+ get_line_start_offset(line_num_+1);
|
||||
if (line_num == get_lines_count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (offset > get_line_end_offset(line_num_+1)) {
|
||||
offset = get_line_end_offset(line_num_+1);
|
||||
const unsigned line_start = get_line_start_offset(line_num);
|
||||
const unsigned next_line_start = get_line_start_offset(line_num+1);
|
||||
const unsigned next_line_end = get_line_end_offset(line_num+1);
|
||||
|
||||
if (line_num < get_lines_count()-1) {
|
||||
offset = offset - line_start + next_line_start;
|
||||
|
||||
if (offset > next_line_end) {
|
||||
offset = next_line_end;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,16 +354,22 @@ void multiline_text::handle_key_up_arrow(SDL_Keymod modifier, bool& handled)
|
|||
|
||||
handled = true;
|
||||
|
||||
set_line_num_from_offset();
|
||||
size_t offset = get_selection_start();
|
||||
const unsigned line_num = get_line_number(offset);
|
||||
|
||||
if (line_num_ > 0) {
|
||||
offset = offset
|
||||
- get_line_start_offset(line_num_)
|
||||
+ get_line_start_offset(line_num_-1);
|
||||
if (line_num == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (offset > get_line_end_offset(line_num_-1)) {
|
||||
offset = get_line_end_offset(line_num_-1);
|
||||
const unsigned line_start = get_line_start_offset(line_num);
|
||||
const unsigned prev_line_start = get_line_start_offset(line_num-1);
|
||||
const unsigned prev_line_end = get_line_end_offset(line_num-1);
|
||||
|
||||
if (line_num > 0) {
|
||||
offset = offset - line_start + prev_line_start;
|
||||
|
||||
if (offset > prev_line_end) {
|
||||
offset = prev_line_end;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,10 +402,6 @@ void multiline_text::signal_handler_left_button_down(const event::ui_event event
|
|||
{
|
||||
DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
|
||||
|
||||
/*
|
||||
* Copied from the base class see how we can do inheritance with the new
|
||||
* system...
|
||||
*/
|
||||
get_window()->keyboard_capture(this);
|
||||
get_window()->mouse_capture();
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2023 - 2024
|
||||
by babaissarkar(Subhraman Sarkar) <suvrax@gmail.com>
|
||||
by Subhraman Sarkar (babaissarkar) <suvrax@gmail.com>
|
||||
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -17,6 +17,7 @@
|
|||
#include "gui/widgets/text_box_base.hpp"
|
||||
#include "gui/widgets/text_box.hpp"
|
||||
#include "gui/widgets/window.hpp"
|
||||
#include "serialization/unicode.hpp"
|
||||
|
||||
namespace gui2
|
||||
{
|
||||
|
@ -71,12 +72,6 @@ public:
|
|||
set_value("");
|
||||
}
|
||||
|
||||
unsigned get_line_no()
|
||||
{
|
||||
set_line_num_from_offset();
|
||||
return line_num_;
|
||||
}
|
||||
|
||||
point get_cursor_pos()
|
||||
{
|
||||
return get_cursor_position(get_selection_start());
|
||||
|
@ -84,7 +79,8 @@ public:
|
|||
|
||||
int get_line_end_pos()
|
||||
{
|
||||
return get_cursor_position(get_line_end_offset(line_num_)).x;
|
||||
unsigned line_num = get_line_number(get_selection_start());
|
||||
return get_cursor_position(get_line_end_offset(line_num)).x;
|
||||
}
|
||||
|
||||
point get_text_end_pos()
|
||||
|
@ -114,7 +110,6 @@ protected:
|
|||
void set_cursor(const std::size_t offset, const bool select) override
|
||||
{
|
||||
text_box_base::set_cursor(offset, select);
|
||||
set_line_num_from_offset();
|
||||
// Whenever cursor moves, this tells scroll_text to update the scrollbars
|
||||
update_layout();
|
||||
}
|
||||
|
@ -123,15 +118,15 @@ public:
|
|||
/** Inherited from text_box_base. */
|
||||
void goto_end_of_line(const bool select = false) override
|
||||
{
|
||||
set_line_num_from_offset();
|
||||
set_cursor(get_line_end_offset(line_num_), select);
|
||||
unsigned line_num = get_line_number(get_selection_start());
|
||||
set_cursor(get_line_end_offset(line_num), select);
|
||||
}
|
||||
|
||||
/** Inherited from text_box_base. */
|
||||
void goto_start_of_line(const bool select = false) override
|
||||
{
|
||||
set_line_num_from_offset();
|
||||
set_cursor(get_line_start_offset(line_num_), select);
|
||||
unsigned line_num = get_line_number(get_selection_start());
|
||||
set_cursor(get_line_start_offset(line_num), select);
|
||||
}
|
||||
|
||||
/** Inherited from text_box_base. */
|
||||
|
@ -205,17 +200,13 @@ private:
|
|||
/** Image (such as a magnifying glass) that accompanies the help text. */
|
||||
std::string hint_image_;
|
||||
|
||||
/** Line number of text */
|
||||
unsigned line_num_;
|
||||
|
||||
/** utility function to calculate and set line_num_ from offset */
|
||||
void set_line_num_from_offset();
|
||||
unsigned get_line_num_from_offset(unsigned offset);
|
||||
|
||||
/** Utility function to calculate the offset of the end of the line
|
||||
/**
|
||||
* Utility function to calculate the offset of the end of the line
|
||||
*/
|
||||
unsigned get_line_end_offset(unsigned line_no);
|
||||
/** Utility function to calculate the offset of the end of the line
|
||||
|
||||
/**
|
||||
* Utility function to calculate the offset of the end of the line
|
||||
*/
|
||||
unsigned get_line_start_offset(unsigned line_no);
|
||||
|
||||
|
|
|
@ -363,10 +363,6 @@ void text_box::signal_handler_left_button_down(const event::ui_event event,
|
|||
{
|
||||
DBG_GUI_E << LOG_HEADER << ' ' << event << ".";
|
||||
|
||||
/*
|
||||
* Copied from the base class see how we can do inheritance with the new
|
||||
* system...
|
||||
*/
|
||||
get_window()->keyboard_capture(this);
|
||||
get_window()->mouse_capture();
|
||||
|
||||
|
|
|
@ -79,6 +79,36 @@ public:
|
|||
return text_.get_lines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper function, returns the line corresponding
|
||||
* to index.
|
||||
* See @ref font::pango_text::get_line.
|
||||
*/
|
||||
PangoLayoutLine* get_line(int index)
|
||||
{
|
||||
return text_.get_line(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper function, return the line number
|
||||
* given the byte index.
|
||||
* See @ref font::pango_text::get_line_num_from_offset.
|
||||
*/
|
||||
int get_line_number(const unsigned offset)
|
||||
{
|
||||
return text_.get_line_num_from_offset(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper function, return the cursor position
|
||||
* given the byte index.
|
||||
* See @ref font::pango_text::get_cursor_pos_from_index.
|
||||
*/
|
||||
point get_cursor_pos_from_index(const unsigned offset) const
|
||||
{
|
||||
return text_.get_cursor_pos_from_index(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper function, return number of lines.
|
||||
* See @ref font::pango_text::get_lines_count.
|
||||
|
@ -88,15 +118,6 @@ public:
|
|||
return text_.get_lines_count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper function, returns corrected column offset from pango.
|
||||
* See @ref font::pango_text::get_byte_offset.
|
||||
*/
|
||||
int get_byte_offset(const unsigned column) const
|
||||
{
|
||||
return text_.get_byte_offset(column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper function, sets the area between column start and end
|
||||
* offset to be highlighted in a specific color.
|
||||
|
|
Loading…
Add table
Reference in a new issue