From ada1f5a70a1f600cc14a045e89bf3a7e3d0b4fe8 Mon Sep 17 00:00:00 2001 From: Matthew Date: Sun, 12 Oct 2025 13:53:42 +1100 Subject: [PATCH] fix line counter on text wrap, readd cursor --- src/editor/buffer.d | 3 +- src/editor/ui.d | 27 ++++++--- src/editor/widgets.d | 134 ++++++++++++++++++++++++++++++++----------- 3 files changed, 121 insertions(+), 43 deletions(-) diff --git a/src/editor/buffer.d b/src/editor/buffer.d index 5688e62..b865459 100644 --- a/src/editor/buffer.d +++ b/src/editor/buffer.d @@ -248,6 +248,7 @@ Insert(FlatBuffer* fb, u8[] insert, u64 length, u64 pos) if(new_ch == '\n' && pos > 0) { + Logf("yeah"); u8 l = fb.data[pos-1]; u8 r = fb.data[pos]; bool expand = (l == '(' && r == ')') || (l == '{' && r == '}') || (l == '[' && r == ']'); @@ -271,7 +272,7 @@ Insert(FlatBuffer* fb, u8[] insert, u64 length, u64 pos) } } } - else if(new_ch > 0) + else if(new_ch != '\n' && new_ch > 0) { length += 1; insert[1] = new_ch; diff --git a/src/editor/ui.d b/src/editor/ui.d index 74a234e..3930a8c 100644 --- a/src/editor/ui.d +++ b/src/editor/ui.d @@ -1229,7 +1229,7 @@ struct TextBuffer } Node!(TextBuffer)* -MakeMultiline(u8[] text, f32 width, u8[] parent_id, u64 line_no, TS[] style = []) +MakeMultiline(u8[] text, f32 width, TS[] style = []) { f32 scaled_width = width * (g_ui_ctx.atlas_buf.atlas.size/g_ui_ctx.text_size); f32 text_width = CalcTextWidth(text); @@ -1249,19 +1249,13 @@ MakeMultiline(u8[] text, f32 width, u8[] parent_id, u64 line_no, TS[] style = [] if(ch_w + w > scaled_width || i == text.length-1) { u64 len = i-start; - u8[extra_buf] buf = 0; - (cast(char[])buf).sformat("%s%05s%05s", cast(char[])parent_id, line_no, line); - u8[] str = ScratchAlloc!(u8)(len+extra_buf); - - str[0 .. len] = text[start .. start+len]; - str[len .. len+extra_buf] = buf[0 .. $]; + u8[] str = ScratchAllocCopySlice!(u8)(text, start, len); TS[] stl = []; if(style.length > 0) { - stl = ScratchAlloc!(TS)(len); - stl[0 .. len] = style[start .. start+len]; + stl = ScratchAllocCopySlice!(TS)(style, start, len); } Node!(TextBuffer)* n = node; @@ -1606,6 +1600,21 @@ DrawBorderedRect(Vec2 pos, Vec2 size, f32 border, f32 radius, f32 softness, Vec4 DrawBorder(pos, size, border, radius, softness, border_col); } +pragma(inline) Glyph* +GetGlyph(u8 ch) +{ + FontAtlas* a = &g_ui_ctx.atlas_buf.atlas; + return ch < a.glyphs.length ? a.glyphs.ptr + ch : a.glyphs.ptr; +} + +void +DrawRect(f32 x, f32 y, FontAtlas* atlas, u8 ch, Vec4 col, bool edit_mode) +{ + Glyph* g = ch < atlas.glyphs.length ? atlas.glyphs.ptr + ch : atlas.glyphs.ptr; + Vec4[4] cols = col; + DrawRect(Vec2(x, y-TEXT_SIZE*0.8), Vec2(edit_mode ? 1.0 : g.advance, TEXT_SIZE), 0.0, 0.0, cols); +} + void DrawRect(Vec2 pos, Vec2 size, f32 corner_radius, f32 border, Vec4[4] cols) { diff --git a/src/editor/widgets.d b/src/editor/widgets.d index 3243ad3..ffbb03b 100644 --- a/src/editor/widgets.d +++ b/src/editor/widgets.d @@ -176,25 +176,36 @@ SetPanelSizes(UIPanel* panel) } } +pragma(inline) void +DrawChar(FontAtlas* atlas, u8 ch, f32* x_pos, f32 y, Vec4 col = Vec4(1.0)) +{ + if(ch < atlas.glyphs.length) + { + Glyph* g = atlas.glyphs.ptr + ch; + DrawGlyph(g, 1.0, x_pos, y, col); + } +} + void Panel2(UIPanel* panel) { - if(panel.ed == null) return; - UICtx* ctx = GetCtx(); UIItem* item = Get(panel.id); Editor* ed = panel.ed; + bool focused = GetFocusedPanel() == panel; UIPanel* parent = panel.parent; UIPanel* prev = panel.prev; + Vec2 click_adjust = Vec2( + parent.axis == A2D.X ? 10 : 0, + parent.axis == A2D.Y ? 10 : 0 + ); + if(!Nil(prev)) { - Vec2 p0, p1; - p0.x = parent.axis == A2D.X ? panel.pos.x - 10 : panel.pos.x; - p0.y = parent.axis == A2D.Y ? panel.pos.y - 10 : panel.pos.y; - p1.x = parent.axis == A2D.X ? panel.pos.x + 10 : panel.pos.x + panel.size.x; - p1.y = parent.axis == A2D.Y ? panel.pos.y + 10 : panel.pos.y + panel.size.y; + Vec2 p0 = panel.pos-click_adjust; + Vec2 p1 = panel.pos+panel.size+click_adjust; if(Dragged(item, p0, p1)) { @@ -215,31 +226,89 @@ Panel2(UIPanel* panel) } } - DrawBorderedRect(panel.pos, panel.size, 2.0, 2.0, 0.1, DEFAULT_COL, DEFAULT_BORDER_COL); - - i64 rows = cast(i64)ceil(panel.size.y/TEXT_SIZE); - - f32 lcw = LineCounter2(panel, 0, rows); - - GetLines(&ed.buf, &ed.linebufs, rows); - - f32 x = panel.pos.x + lcw; - f32 y = panel.pos.y + TEXT_SIZE; - - for(auto buf = ed.linebufs.first; buf != null; buf = buf.next) + if(panel.ed != null) { - f32 x_pos = x; - - foreach(i; 0 .. buf.text.length) + if(Clicked(item, panel.pos, panel.pos+panel.size-click_adjust)) { - if(buf.text[i] < ctx.atlas_buf.atlas.glyphs.length) - { - Glyph* g = ctx.atlas_buf.atlas.glyphs.ptr + buf.text[i]; - DrawGlyph(g, 1.0, &x_pos, y, buf.style[i]); - } + SetFocusedPanel(panel); } - y += TEXT_SIZE; + DrawBorderedRect(panel.pos, panel.size, 2.0, 2.0, 0.1, DEFAULT_COL, focused ? HL_BORDER_COL : DEFAULT_BORDER_COL); + + i64 rows = cast(i64)ceil(panel.size.y/TEXT_SIZE); + + GetLines(&ed.buf, &ed.linebufs, rows); + + i64 offset = ed.buf.offset; + i64 end = offset + ed.linebufs.count; + + char[64] ch_buf = '\0'; + char[] fmt = ch_buf.sformat("%%0%ss", u64(end.toChars().length)); + + u8[] end_line_text = ScratchAlloc!(u8)(end.toChars().length); + end_line_text[] = '0'; + + f32 lcw = CalcTextWidth(end_line_text); + f32 padding = 4.0; + + DrawRect(panel.pos, panel.pos+Vec2(lcw+padding*2, panel.size.y), 0.0, 0.0, focused ? LC_HL_COLOR : LC_COLOR); + + f32 x = panel.pos.x; + f32 y = panel.pos.y + TEXT_SIZE; + + auto atlas = &ctx.atlas_buf.atlas; + bool edit = EditModeActive(); + U64Vec2 pos = VecPos(&ed.buf); + u64 i; + for(auto buf = ed.linebufs.first; buf != null; buf = buf.next, i += 1) + { + f32 x_pos = x + padding; + char[32] line_buf = '\0'; + char[] line_str = sformat(line_buf, fmt, offset+i); + + foreach(j; 0 .. line_str.length) + { + DrawChar(&ctx.atlas_buf.atlas, line_str[j], &x_pos, y, Vec4(1.0)); + } + + x_pos += padding; + + u64 ch_offset; + auto parts = MakeMultiline(buf.text, panel.size.x-lcw, buf.style); + for(auto n = parts; n != null; n = n.next) + { + auto l = &n.value; + + if(pos.y == i) + { + f32 hl_x = x + lcw + padding*2.0; + Glyph* g = GetGlyph(' '); + foreach(j; 0 .. l.text.length) + { + bool hl = j == pos.x-ch_offset; + if(hl) + { + break; + } + + g = j == l.text.length-1 ? GetGlyph(' ') : GetGlyph(l.text[j]); + hl_x += GlyphWidth(g); + } + + DrawRect(hl_x, y, atlas, cast(u8)g.ch, Vec4(1.0), edit); + } + + foreach(j; 0 .. l.text.length) + { + bool hl = pos.y == i && !edit && j == pos.x-ch_offset; + DrawChar(&ctx.atlas_buf.atlas, l.text[j], &x_pos, y, hl ? Vec4(Vec3(0.0), 1.0) : SYNTAX_COLORS[l.style[j]]); + } + + y += TEXT_SIZE; + x_pos = x + lcw + padding*2.0; + ch_offset += l.text.length; + } + } } } @@ -284,11 +353,7 @@ LineCounter2(UIPanel* panel, i64 start_row, i64 end_row) foreach(j; 0 .. line_counts[i].length) { - if(line_counts[i][j] < ctx.atlas_buf.atlas.glyphs.length) - { - Glyph* g = ctx.atlas_buf.atlas.glyphs.ptr + line_counts[i][j]; - DrawGlyph(g, 1.0, &x_pos, y, Vec4(1.0)); - } + DrawChar(&ctx.atlas_buf.atlas, line_counts[i][j], &x_pos, y); } y += TEXT_SIZE; @@ -639,6 +704,7 @@ TextClicked(TextPart* text_part) TextPart* WrappedTextLine(u8[] text, u8[] parent_id, f32 text_size, u64 line_no, TS[] style = [], U64Vec2* hl_pos, bool focused) { + /* Push!("color")(Vec4(1.0)); Push!("text_size")(text_size); @@ -696,6 +762,8 @@ WrappedTextLine(u8[] text, u8[] parent_id, f32 text_size, u64 line_no, TS[] styl Pop!("color"); return part; + */ + return null; } UIItem*