more fixes for text buffer, add scrolling
This commit is contained in:
parent
6503dae769
commit
c9617b701b
@ -13,12 +13,22 @@ struct FlatBuffer
|
||||
u64 length;
|
||||
u64 lf_count;
|
||||
i64 buf_pos;
|
||||
i64 offset;
|
||||
i64 rows;
|
||||
}
|
||||
|
||||
struct LineBuffers
|
||||
{
|
||||
Arena arena;
|
||||
u8[][] lines;
|
||||
LineBuffer* first;
|
||||
LineBuffer* last;
|
||||
u64 count;
|
||||
}
|
||||
|
||||
struct LineBuffer
|
||||
{
|
||||
u8[] text;
|
||||
LineBuffer* next;
|
||||
}
|
||||
|
||||
enum WalkDir
|
||||
@ -102,6 +112,8 @@ Insert(FlatBuffer* buffer, u8[] insert, u64 length, u64 pos)
|
||||
buffer.length += length;
|
||||
|
||||
Reset(&buffer.arena);
|
||||
|
||||
AdjustOffset(buffer);
|
||||
}
|
||||
|
||||
void
|
||||
@ -118,22 +130,34 @@ Insert(FlatBuffer* buffer, u8[] insert, u64 length, I64Vec2 pos)
|
||||
Insert(buffer, insert, length, VecToPos(buffer, pos));
|
||||
}
|
||||
|
||||
void
|
||||
GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 length)
|
||||
{
|
||||
GetLines(buffer, linebufs, buffer.offset, length);
|
||||
}
|
||||
|
||||
void
|
||||
GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 start_line, u64 length)
|
||||
{
|
||||
assert(linebufs != null, "GetLines failure: linebufs is null");
|
||||
u64 line_count = buffer.lf_count + 1;
|
||||
length = length > line_count ? line_count : length;
|
||||
|
||||
Reset(&linebufs.arena);
|
||||
linebufs.lines = AllocArray!(u8[])(&linebufs.arena, length);
|
||||
linebufs.first = Alloc!(LineBuffer)(&linebufs.arena);
|
||||
linebufs.count = 0;
|
||||
|
||||
i64 start = -1;
|
||||
u64 line = 0;
|
||||
u64 current_line = 0;
|
||||
if(buffer.length == 0)
|
||||
{
|
||||
linebufs.first.text = AllocArray!(u8)(&linebufs.arena, 1);
|
||||
linebufs.first.text[0] = 0;
|
||||
}
|
||||
else with(linebufs)
|
||||
{
|
||||
LineBuffer* current = first;
|
||||
for(u64 i = 0; i < buffer.length; i += 1)
|
||||
{
|
||||
if(current_line == length)
|
||||
if(count == length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -145,11 +169,19 @@ GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 start_line, u64 length)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(line < start_line)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(start < 0 && new_line)
|
||||
{
|
||||
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, 1);
|
||||
linebufs.lines[current_line][0] = '\n';
|
||||
current_line += 1;
|
||||
current.text = AllocArray!(u8)(&arena, 1);
|
||||
current.text[0] = '\n';
|
||||
count += 1;
|
||||
|
||||
current.next = Alloc!(LineBuffer)(&arena);
|
||||
current = current.next;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -160,17 +192,34 @@ GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 start_line, u64 length)
|
||||
|
||||
if(new_line)
|
||||
{
|
||||
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, (i-start));
|
||||
linebufs.lines[current_line][0 .. i-start] = buffer.data[start .. i];
|
||||
current_line += 1;
|
||||
current.text = AllocArray!(u8)(&arena, i-start);
|
||||
current.text[0 .. i-start] = buffer.data[start .. i];
|
||||
count += 1;
|
||||
start = -1;
|
||||
|
||||
current.next = Alloc!(LineBuffer)(&arena);
|
||||
current = current.next;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(i == buffer.length-1)
|
||||
{
|
||||
linebufs.lines[current_line] = AllocArray!(u8)(&linebufs.arena, (buffer.length-start));
|
||||
linebufs.lines[current_line][0 .. buffer.length-start] = buffer.data[start .. buffer.length];
|
||||
current.text = AllocArray!(u8)(&arena, (buffer.length-start));
|
||||
current.text[0 .. buffer.length-start] = buffer.data[start .. buffer.length];
|
||||
|
||||
current.next = Alloc!(LineBuffer)(&arena);
|
||||
current = current.next;
|
||||
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(buffer.length > 0 && buffer.data[buffer.length-1] == '\n')
|
||||
{
|
||||
current.text = AllocArray!(u8)(&linebufs.arena, 1);
|
||||
current.text[0] = 0;
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,6 +227,7 @@ GetLines(FlatBuffer* buffer, LineBuffers* linebufs, u64 start_line, u64 length)
|
||||
void
|
||||
Move(FlatBuffer* buffer, Input key, Modifier md)
|
||||
{
|
||||
Logf("key: %s", key);
|
||||
if(md & (MD.LeftShift | MD.RightShift))
|
||||
{
|
||||
switch(key)
|
||||
@ -254,6 +304,11 @@ Move(FlatBuffer* buffer, Input key, Modifier md)
|
||||
break;
|
||||
}
|
||||
|
||||
if(buffer.buf_pos == buffer.length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Walk!(WalkDir.Forward)(buffer);
|
||||
}
|
||||
}
|
||||
@ -275,11 +330,9 @@ Move(FlatBuffer* buffer, Input key, Modifier md)
|
||||
|
||||
if(buffer.data[buffer.buf_pos] == '\n')
|
||||
{
|
||||
Logf("1");
|
||||
new_l += 1;
|
||||
if(new_l == 2)
|
||||
{
|
||||
Logf("2");
|
||||
Walk!(WalkDir.Forward)(buffer);
|
||||
break;
|
||||
}
|
||||
@ -300,6 +353,11 @@ Move(FlatBuffer* buffer, Input key, Modifier md)
|
||||
break;
|
||||
}
|
||||
|
||||
if(buffer.buf_pos == buffer.length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Walk!(WalkDir.Forward)(buffer);
|
||||
}
|
||||
}
|
||||
@ -322,10 +380,33 @@ Move(FlatBuffer* buffer, Input key, Modifier md)
|
||||
}
|
||||
}
|
||||
|
||||
Logf("%s %s", buffer.buf_pos, buffer.pos.v);
|
||||
AdjustOffset(buffer);
|
||||
Logf("buf_pos %s pos %s", buffer.buf_pos, buffer.pos.v);
|
||||
|
||||
//VerifyPosition(buffer, key, md);
|
||||
}
|
||||
|
||||
void
|
||||
AdjustOffset(FlatBuffer* buffer)
|
||||
{
|
||||
with(buffer)
|
||||
{
|
||||
i64 screen_pos = pos.y - offset;
|
||||
i64 start = 1;
|
||||
i64 end = rows-1;
|
||||
if(offset > 0 && screen_pos < start)
|
||||
{
|
||||
Logf("rows %s offset %s adjusting by %s - %s", rows, offset, screen_pos, start);
|
||||
offset += screen_pos - start;
|
||||
}
|
||||
else if(screen_pos > end)
|
||||
{
|
||||
Logf("rows %s offset %s adjusting by %s - %s", rows, offset, screen_pos, end);
|
||||
offset += screen_pos - end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u64
|
||||
VecToPos(FlatBuffer* buffer, I64Vec2 vec)
|
||||
{
|
||||
@ -428,79 +509,9 @@ AdjustLinePos(FlatBuffer* buffer, i64 adj)
|
||||
}
|
||||
}
|
||||
|
||||
pragma(inline) i64
|
||||
MoveToPrevLine(FlatBuffer* buffer)
|
||||
{
|
||||
i64 adj = 0;
|
||||
|
||||
with(buffer)
|
||||
{
|
||||
if(pos.y == 0)
|
||||
{
|
||||
adj = -pos.x;
|
||||
pos.x = 0;
|
||||
buf_pos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
i64 p = buf_pos;
|
||||
if(buffer.data[p] == '\n')
|
||||
{
|
||||
p -= 1;
|
||||
}
|
||||
|
||||
for(; p > 0 && data[p] != '\n'; p -= 1) {}
|
||||
|
||||
buf_pos = p;
|
||||
pos.y -= 1;
|
||||
Logf("pos in line %s", PosInLine(buffer, p));
|
||||
pos.x = PosInLine(buffer, p);
|
||||
}
|
||||
}
|
||||
|
||||
return adj;
|
||||
}
|
||||
|
||||
pragma(inline) i64
|
||||
MoveToNextLine(FlatBuffer* buffer)
|
||||
{
|
||||
i64 adj = 0;
|
||||
|
||||
with(buffer)
|
||||
{
|
||||
if(pos.y == lf_count)
|
||||
{
|
||||
Logf("upper");
|
||||
adj = length - buf_pos;
|
||||
pos.x += adj;
|
||||
buf_pos += adj;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logf("lower");
|
||||
i64 p = buf_pos;
|
||||
u8 prev = 0;
|
||||
for(; p < length; p += 1)
|
||||
{
|
||||
if(p > 0 && data[p-1] == '\n')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pos.x = 0;
|
||||
pos.y += 1;
|
||||
buf_pos = p;
|
||||
}
|
||||
}
|
||||
|
||||
return adj;
|
||||
}
|
||||
|
||||
pragma(inline) void
|
||||
Walk(alias dir)(FlatBuffer* buffer)
|
||||
{
|
||||
Logf("%s", buffer.pos.v);
|
||||
static if(dir == WalkDir.Backward)
|
||||
{
|
||||
buffer.buf_pos -= 1;
|
||||
@ -514,8 +525,11 @@ Walk(alias dir)(FlatBuffer* buffer)
|
||||
buffer.pos.x -= 1;
|
||||
}
|
||||
|
||||
assert(buffer.pos.y >= 0);
|
||||
assert(buffer.pos.x >= 0);
|
||||
if(buffer.pos.x < 0 || buffer.pos.y < 0)
|
||||
{
|
||||
Logf("walked %s buf_pos %s pos %s", dir, buffer.buf_pos, buffer.pos.v);
|
||||
assert(pos.x >= 0 && pos.y >= 0);
|
||||
}
|
||||
}
|
||||
else static if(dir == WalkDir.Forward)
|
||||
{
|
||||
@ -530,7 +544,6 @@ Walk(alias dir)(FlatBuffer* buffer)
|
||||
buffer.pos.x += 1;
|
||||
}
|
||||
}
|
||||
Logf("%s", buffer.pos.v);
|
||||
}
|
||||
|
||||
pragma(inline) void
|
||||
@ -554,8 +567,6 @@ VerifyPosition(FlatBuffer* buffer, Input input, Modifier md)
|
||||
p.x += 1;
|
||||
}
|
||||
|
||||
Logf("%s %s", p.v, pos.v);
|
||||
|
||||
assert(p.y <= pos.y);
|
||||
}
|
||||
|
||||
@ -576,16 +587,25 @@ PosInLine(FlatBuffer* buffer, i64 pos)
|
||||
|
||||
i64 p = pos;
|
||||
i64 line_pos = 0;
|
||||
i64 skip_lf = buffer.data[pos] == '\n';
|
||||
|
||||
i64 lf_count = 0;
|
||||
for(; p > 0; p -= 1, line_pos += 1)
|
||||
{
|
||||
if(buffer.data[p] == '\n')
|
||||
{
|
||||
p -= 1;
|
||||
line_pos += 1;
|
||||
}
|
||||
|
||||
for(; p > 0 && buffer.data[p] != '\n'; p -= 1, line_pos += 1)
|
||||
if(skip_lf)
|
||||
{
|
||||
|
||||
skip_lf = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logf("line_pos %s", line_pos);
|
||||
|
||||
return line_pos;
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ struct Editor
|
||||
FlatBuffer buf;
|
||||
Tokenizer tk;
|
||||
LineBuffers linebufs;
|
||||
i64 offset;
|
||||
|
||||
Vec2 cursor_pos;
|
||||
Vec2 select_start;
|
||||
@ -276,6 +277,11 @@ HandleInputs(EditorCtx* ctx, Inputs* inputs)
|
||||
case Input.Left:
|
||||
case Input.Right:
|
||||
{
|
||||
UIPanel* p = GetFocusedPanel();
|
||||
if(!Nil(p))
|
||||
{
|
||||
Move(&p.ed.buf, key, node.value.md);
|
||||
}
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
@ -1131,28 +1131,43 @@ DrawLine(UIItem* item)
|
||||
f32 x = item.rect.x0;
|
||||
FontAtlas* atlas = &ctx.atlas_buf.atlas;
|
||||
|
||||
UIPanel* panel = GetFocusedPanel();
|
||||
bool active = panel.id == item.parent.key.text;
|
||||
bool edit_mode = EditModeActive();
|
||||
|
||||
Vertex* v;
|
||||
if(item.highlighted_char >= 0 && active)
|
||||
{
|
||||
v = ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count;
|
||||
AddUIIndices(ctx);
|
||||
}
|
||||
|
||||
for(u64 i = 0; i < item.key.text.length && item.key.text[i] != '\0'; i += 1)
|
||||
{
|
||||
u8 ch = item.key.text.ptr[i];
|
||||
if(ch < 128)
|
||||
{
|
||||
DrawGlyph(item, &atlas.glyphs[ch], atlas.size/ctx.text_size, &x, y, i == item.highlighted_char);
|
||||
DrawGlyph(item, &atlas.glyphs[ch], atlas.size/ctx.text_size, &x, y, !edit_mode && i == item.highlighted_char);
|
||||
}
|
||||
}
|
||||
|
||||
if(item.highlighted_char >= 0)
|
||||
if(v)
|
||||
{
|
||||
y = item.rect.y0 + 2;
|
||||
x = item.rect.x0;
|
||||
UIPanel* panel = GetFocusedPanel();
|
||||
bool text_in_focus = panel.id == item.parent.key.text;
|
||||
|
||||
f32 adv = atlas.glyphs[' '].advance;
|
||||
Vertex* v = ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count;
|
||||
for(u64 i = 0; i < item.highlighted_char; i += 1)
|
||||
{
|
||||
if(item.key.text[i] == '\t')
|
||||
{
|
||||
x += adv*2;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += adv;
|
||||
}
|
||||
}
|
||||
|
||||
v.dst_start.x = x;
|
||||
v.dst_start.y = y;
|
||||
@ -1160,7 +1175,7 @@ DrawLine(UIItem* item)
|
||||
v.dst_end.y = y + ctx.text_size - 2;
|
||||
v.cols = Vec4(1.0);
|
||||
|
||||
if(text_in_focus)
|
||||
if(edit_mode)
|
||||
{
|
||||
v.dst_end.x = v.dst_start.x + 2;
|
||||
}
|
||||
@ -1175,7 +1190,6 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32 scale, f32* x_pos, f32 y, bool highlig
|
||||
UICtx* ctx = GetCtx();
|
||||
Vertex* bg_v = null, v = null;
|
||||
f32 h;
|
||||
bool text_in_focus = false;
|
||||
|
||||
if(glyph.ch == '\t')
|
||||
{
|
||||
@ -1203,6 +1217,11 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32 scale, f32* x_pos, f32 y, bool highlig
|
||||
v.src_end.y = glyph.atlas_bottom;
|
||||
}
|
||||
|
||||
if(highlight)
|
||||
{
|
||||
col = Vec4(Vec3(1.0)-col.xyz, 1.0);
|
||||
}
|
||||
|
||||
v.cols = col;
|
||||
|
||||
v.texture = 1;
|
||||
|
||||
@ -5,7 +5,7 @@ import ui : Nil;
|
||||
import ui;
|
||||
import editor;
|
||||
import std.format : sformat;
|
||||
import std.math.rounding : ceil;
|
||||
import std.math.rounding : ceil, floor;
|
||||
|
||||
const UIPanel g_ui_nil_panel;
|
||||
UIPanel* g_UI_NIL_PANEL;
|
||||
@ -42,6 +42,7 @@ struct TextPart
|
||||
{
|
||||
UIItem* item;
|
||||
TextPart* next;
|
||||
u32 count;
|
||||
}
|
||||
|
||||
UIItem*
|
||||
@ -175,26 +176,38 @@ EditorView(UIPanel* panel)
|
||||
{
|
||||
UICtx* ctx = GetCtx();
|
||||
UIItem* item = Panel(panel, UIF.Clickable);
|
||||
Editor* ed = panel.ed;
|
||||
|
||||
bool focused = panel == GetFocusedPanel();
|
||||
u64 rows = cast(u64)ceil(item.size.y/16.0);
|
||||
GetLines(&panel.ed.buf, &panel.ed.linebufs, 0, rows);
|
||||
for(u64 i = 0; i < panel.ed.linebufs.lines.length; i += 1)
|
||||
|
||||
f32 text_size = 16.0;
|
||||
f32 height = 0.0;
|
||||
|
||||
i64 rows = cast(i64)ceil(item.size.y/text_size);
|
||||
if(ed.buf.rows != rows)
|
||||
{
|
||||
u8[] line = panel.ed.linebufs.lines[i];
|
||||
if(line.length > 0)
|
||||
{
|
||||
if(panel.ed.buf.pos.y == i && focused)
|
||||
{
|
||||
SetHighlightedChar(panel.ed.buf.pos.x);
|
||||
Logf("editor height %s text_size %s rows %s", item.size.y, text_size, rows);
|
||||
ed.buf.rows = rows;
|
||||
}
|
||||
|
||||
TextPart* tp = WrappedTextLine(line, panel.id, 16.0, i);
|
||||
GetLines(&ed.buf, &ed.linebufs, rows);
|
||||
u64 i = 0;
|
||||
for(LineBuffer* buf = ed.linebufs.first; buf != null; buf = buf.next, i += 1)
|
||||
{
|
||||
if(buf.text.length > 0)
|
||||
{
|
||||
i64 line_no = i+ed.buf.offset;
|
||||
if(ed.buf.pos.y == line_no && focused)
|
||||
{
|
||||
SetHighlightedChar(ed.buf.pos.x);
|
||||
}
|
||||
|
||||
TextPart* tp = WrappedTextLine(buf.text, panel.id, text_size, line_no);
|
||||
height += (text_size * tp.count);
|
||||
if(TextClicked(tp))
|
||||
{
|
||||
SetFocusedPanel(panel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SetHighlightedChar(-1);
|
||||
@ -242,6 +255,8 @@ WrappedTextLine(u8[] text, u8[] parent_id, f32 text_size, u64 line_no)
|
||||
Node!(u8[])* lines = MakeMultiline(text, parent.size.x, parent_id, line_no);
|
||||
for(Node!(u8[])* line = lines; line != null; line = line.next, tp = tp.next)
|
||||
{
|
||||
part.count += 1;
|
||||
|
||||
tp.item = Get(line.value);
|
||||
tp.next = ScratchAlloc!(TextPart)();
|
||||
tp.next.item = g_UI_NIL;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user