Skip to content

Commit ad26104

Browse files
committed
[fix] refresh cursors inline multiline
1 parent 23bd31f commit ad26104

File tree

4 files changed

+142
-44
lines changed

4 files changed

+142
-44
lines changed

include/ekg/io/utf.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ namespace ekg {
245245
);
246246
public:
247247
void push_back(std::string_view line);
248+
size_t set(size_t index, std::string_view line, ekg::io::chunk_t &split_endings);
248249
size_t set(size_t index, std::string_view line);
249250

250251
std::string read(

include/ekg/ui/textbox/widget.hpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,20 @@
2828
#include "textbox.hpp"
2929

3030
namespace ekg::ui {
31+
enum class textbox_operation {
32+
insert_inline,
33+
insert_multiline,
34+
insert_line,
35+
erase_inline,
36+
erase_multiline
37+
};
38+
3139
void refresh_cursors_pos(
3240
ekg::textbox_t &textbox,
3341
ekg::textbox_t::cursor_t &origin,
3442
const ekg::vec2_t<size_t> &displacement_a,
3543
const ekg::vec2_t<size_t> &displacement_b,
36-
const ekg::vec2_t<size_t> &displacement_delta,
37-
ekg::flags_t direction
44+
const ekg::ui::textbox_operation &operation
3845
);
3946

4047
bool find_cursor(

src/io/utf.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -491,12 +491,16 @@ void ekg::text::swizzle(
491491
}
492492

493493
size_t ekg::text::set(size_t index, std::string_view line) {
494+
ekg::io::chunk_t split_endings {};
495+
return this->set(index, line, split_endings);
496+
}
497+
498+
size_t ekg::text::set(size_t index, std::string_view line, ekg::io::chunk_t &split_endings) {
494499
size_t current_lines {};
495500
size_t previous_lines {};
496501
size_t chunk_size {};
497502

498-
std::vector<std::string> ending_splitted {};
499-
ekg::utf8_split_endings(line, ending_splitted);
503+
ekg::utf8_split_endings(line, split_endings);
500504

501505
bool ok {};
502506
for (size_t it {}; it < this->loaded_chunks.size(); it++) {
@@ -512,15 +516,15 @@ size_t ekg::text::set(size_t index, std::string_view line) {
512516
&&
513517
(index - previous_lines) < chunk_size
514518
) {
515-
this->swizzle(it, (index - previous_lines), ending_splitted, true);
519+
this->swizzle(it, (index - previous_lines), split_endings, true);
516520
this->was_audited = true;
517521
ok = true;
518522
}
519523
}
520524

521525
if (!ok) throw std::out_of_range("ekg::text::set -> lines length: " + std::to_string(current_lines));
522526
this->total_lines = current_lines;
523-
return ending_splitted.size();
527+
return split_endings.size();
524528
}
525529

526530
std::string ekg::text::at(size_t index) {

src/ui/textbox/widget.cpp

Lines changed: 124 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -38,37 +38,89 @@ void ekg::ui::refresh_cursors_pos(
3838
ekg::textbox_t::cursor_t &origin,
3939
const ekg::vec2_t<size_t> &displacement_a,
4040
const ekg::vec2_t<size_t> &displacement_b,
41-
const ekg::vec2_t<size_t> &displacement_delta,
42-
ekg::flags_t direction
41+
const ekg::ui::textbox_operation &operation
4342
) {
44-
bool is_resize {ekg::has<ekg::dock>(direction, ekg::dock::resize)};
45-
for (ekg::textbox_t::cursor_t &cursor : textbox.widget.cursors) {
46-
if (cursor.is_ignored || cursor.a.y < origin.a.y) continue;
43+
switch (operation) {
44+
case ekg::ui::textbox_operation::insert_line:
45+
for (ekg::textbox_t::cursor_t &cursor : textbox.widget.cursors) {
46+
if (cursor.is_ignored || cursor.a.y < origin.a.y) continue;
4747

48-
if (!is_resize) {
49-
if (
50-
cursor.a.y == origin.a.y
51-
&&
52-
cursor.a.x > origin.a.x
53-
) {
54-
cursor.a.x = ekg::has<ekg::dock>(direction, ekg::dock::left)
55-
? (cursor.a.x - displacement_a.x) : (cursor.a.x + displacement_a.x);
48+
if (cursor.a.y == origin.b.y && cursor.a.x > origin.b.x) {
49+
cursor.a.x += displacement_a.x;
5650
}
5751

58-
if (
59-
cursor.b.y == origin.b.y
60-
&&
61-
cursor.b.x > origin.b.x
62-
) {
63-
cursor.b.x = ekg::has<ekg::dock>(direction, ekg::dock::left)
64-
? (cursor.b.x - displacement_b.x) : (cursor.b.x + displacement_b.x);
52+
if (cursor.b.y == origin.b.y && cursor.b.x > origin.b.x) {
53+
cursor.b.x += displacement_b.x;
6554
}
6655

6756
if (cursor.a.y >= origin.b.y) {
68-
cursor.a.y -= displacement_a.y;
69-
cursor.b.y -= displacement_b.y;
57+
cursor.a.y += displacement_a.y;
58+
cursor.b.y += displacement_b.y;
7059
}
71-
} else {
60+
}
61+
break;
62+
case ekg::ui::textbox_operation::insert_inline:
63+
for (ekg::textbox_t::cursor_t &cursor : textbox.widget.cursors) {
64+
if (cursor.is_ignored || cursor.a.y < origin.a.y) continue;
65+
66+
if (cursor.a.y == origin.b.y && cursor.a.x > origin.b.x) {
67+
cursor.a.x += displacement_a.x;
68+
}
69+
70+
if (cursor.b.y == origin.b.y && cursor.b.x > origin.b.x) {
71+
cursor.b.x += displacement_b.x;
72+
}
73+
}
74+
break;
75+
case ekg::ui::textbox_operation::insert_multiline:
76+
for (ekg::textbox_t::cursor_t &cursor : textbox.widget.cursors) {
77+
if (cursor.is_ignored || cursor.a.y < origin.a.y) continue;
78+
79+
if (cursor.a.y == origin.b.y && cursor.a.x > origin.b.x) {
80+
cursor.a.x += displacement_a.x;
81+
cursor.a.y += displacement_a.y;
82+
}
83+
84+
if (cursor.b.y == origin.b.y && cursor.b.x > origin.b.x) {
85+
cursor.b.x += displacement_b.x;
86+
cursor.b.y += displacement_b.y;
87+
}
88+
89+
if (cursor.a.y >= origin.b.y) {
90+
cursor.a.y += displacement_a.y;
91+
cursor.b.y += displacement_b.y;
92+
}
93+
}
94+
break;
95+
case ekg::ui::textbox_operation::erase_inline:
96+
for (ekg::textbox_t::cursor_t &cursor : textbox.widget.cursors) {
97+
if (cursor.is_ignored || cursor.a.y < origin.a.y) continue;
98+
if (
99+
cursor.a.y == origin.a.y
100+
&&
101+
cursor.a.x > origin.a.x
102+
) {
103+
cursor.a.x = cursor.a.x - displacement_a.x;
104+
}
105+
106+
if (
107+
cursor.b.y == origin.b.y
108+
&&
109+
cursor.b.x > origin.b.x
110+
) {
111+
cursor.b.x = cursor.b.x - displacement_b.x;
112+
}
113+
114+
if (cursor.a.y >= origin.b.y) {
115+
cursor.a.y -= displacement_a.y;
116+
cursor.b.y -= displacement_b.y;
117+
}
118+
}
119+
break;
120+
case ekg::ui::textbox_operation::erase_multiline:
121+
for (ekg::textbox_t::cursor_t &cursor : textbox.widget.cursors) {
122+
if (cursor.is_ignored || cursor.a.y < origin.a.y) continue;
123+
72124
if (
73125
cursor.a.y == origin.b.y
74126
&&
@@ -96,6 +148,7 @@ void ekg::ui::refresh_cursors_pos(
96148
cursor.b.y -= displacement_b.y;
97149
}
98150
}
151+
break;
99152
}
100153
}
101154

@@ -407,8 +460,7 @@ void ekg::ui::handle_erase(
407460
origin,
408461
{cursor.b.x - cursor.a.x, 0},
409462
{cursor.b.x - cursor.a.x, 0},
410-
{cursor.b.x - cursor.a.x, 0},
411-
ekg::dock::left
463+
ekg::ui::textbox_operation::erase_inline
412464
);
413465
cursor.is_ignored = false;
414466

@@ -438,8 +490,7 @@ void ekg::ui::handle_erase(
438490
origin,
439491
{cursor.b.x, cursor.b.y - cursor.a.y},
440492
{cursor.b.x, cursor.b.y - cursor.a.y},
441-
{cursor.b.x, cursor.b.y - cursor.a.y},
442-
ekg::dock::left | ekg::dock::resize
493+
ekg::ui::textbox_operation::erase_multiline
443494
);
444495

445496
cursor.is_ignored = false;
@@ -477,24 +528,24 @@ void ekg::ui::handle_insert(
477528

478529
if (typed == EKG_EOF_SYSTEM) {
479530
std::string line {textbox.text.at(cursor.a.y)};
531+
std::string right_cut {ekg::utf8_substr(line, cursor.a.x, UINT32_MAX)};
532+
size_t right_cut_size {ekg::utf8_length(right_cut)};
480533

481534
ekg::textbox_t::cursor_t origin {cursor};
482-
origin.a = origin.delta;
483-
origin.b = origin.delta;
535+
origin.b = origin.a;
484536

485537
cursor.is_ignored = true;
486538
ekg::ui::refresh_cursors_pos(
487539
textbox,
488540
origin,
489-
{cursor.b.x - cursor.a.x, 0},
490-
{cursor.b.x - cursor.a.x, 0},
491-
{cursor.b.x - cursor.a.x, 0},
492-
ekg::dock::left
541+
{right_cut_size, 1},
542+
{right_cut_size, 1},
543+
ekg::ui::textbox_operation::insert_line
493544
);
494545
cursor.is_ignored = false;
495546

496547
textbox.text.set(cursor.a.y, ekg::utf8_substr(line, 0, cursor.a.x));
497-
textbox.text.insert(cursor.a.y, ekg::utf8_substr(line, cursor.a.x, UINT32_MAX));
548+
textbox.text.insert(cursor.a.y, right_cut);
498549

499550
cursor.a.y++;
500551
cursor.a.x = 0;
@@ -513,14 +564,49 @@ void ekg::ui::handle_insert(
513564
typed.end()
514565
);
515566

516-
size_t added {textbox.text.set(cursor.a.y, line)};
567+
ekg::textbox_t::cursor_t origin {cursor};
568+
origin.b = origin.a;
569+
570+
ekg::vec2_t<size_t> displacement_a {};
571+
ekg::vec2_t<size_t> displacement_b {};
572+
573+
ekg::io::chunk_t split_endings {};
574+
size_t added {textbox.text.set(cursor.a.y, line, split_endings)};
575+
517576
if (added == 1) {
518-
cursor.a.x += ekg::utf8_length(typed);
577+
displacement_a = {ekg::utf8_length(typed), 0};
578+
displacement_b = displacement_a;
579+
cursor.a.x += displacement_a.x;
519580
} else {
520-
cursor.a.y += added-1;
521-
cursor.a.x = ekg::utf8_length(textbox.text.at(cursor.a.y));
581+
displacement_a.y = added-1;
582+
cursor.a.y += displacement_a.y;
583+
584+
size_t ending {typed.rfind('\n')};
585+
if (ending != std::string::npos) {
586+
displacement_a.x = ekg::utf8_length(typed.substr(ending, UINT32_MAX));
587+
} else {
588+
displacement_a.x = ekg::utf8_length(typed);
589+
}
590+
591+
displacement_b = displacement_a;
592+
cursor.a.x = displacement_a.x;
522593
}
523594

595+
cursor.is_ignored = true;
596+
ekg::ui::refresh_cursors_pos(
597+
textbox,
598+
origin,
599+
displacement_a,
600+
displacement_b,
601+
(
602+
added == 1 ?
603+
ekg::ui::textbox_operation::insert_inline
604+
:
605+
ekg::ui::textbox_operation::insert_multiline
606+
)
607+
);
608+
cursor.is_ignored = false;
609+
524610
cursor.b = cursor.a;
525611
cursor.highest_char_index = cursor.a.x;
526612
}

0 commit comments

Comments
 (0)