implement line counters

This commit is contained in:
Matthew 2025-09-22 03:32:34 +10:00
parent 7769a861e3
commit 9a1845d27a
5 changed files with 154 additions and 28 deletions

@ -1 +1 @@
Subproject commit ff94c5cb5e4b3c581521452a2a50b363a09cd8d6 Subproject commit 85177acdd04a21d0248051f718ef1e57e12f090e

View File

@ -395,7 +395,7 @@ AdjustOffset(FlatBuffer* fb)
{ {
i64 screen_pos = CurrentLine(fb) - offset; i64 screen_pos = CurrentLine(fb) - offset;
i64 start = 1; i64 start = 1;
i64 end = rows-1; i64 end = rows-2;
if(offset > 0 && screen_pos < start) if(offset > 0 && screen_pos < start)
{ {
offset += screen_pos - start; offset += screen_pos - start;

View File

@ -97,7 +97,7 @@ InitEditorCtx(PlatformWindow* window)
} }
UIPanel* UIPanel*
CreatePanel(EditorCtx* ctx) CreatePanel(EditorCtx* ctx, SizeType size_type = ST.Percentage)
{ {
UIPanel* p = Alloc!(UIPanel)(&ctx.arena); UIPanel* p = Alloc!(UIPanel)(&ctx.arena);
p.axis = A2D.Y; p.axis = A2D.Y;

View File

@ -11,6 +11,7 @@ import std.math.traits : isNaN;
import std.math.rounding : ceil; import std.math.rounding : ceil;
import std.format : sformat; import std.format : sformat;
import core.stdc.string : memset; import core.stdc.string : memset;
import core.stdc.math : fabsf;
import editor; import editor;
@ -63,6 +64,7 @@ enum SizeType
{ {
Pixels, Pixels,
Percentage, Percentage,
FitChild,
} }
alias ST = SizeType; alias ST = SizeType;
@ -107,6 +109,7 @@ struct UICtx
Axis2D layout_axis; Axis2D layout_axis;
Vec2 adjustment; Vec2 adjustment;
Vec2 offset; Vec2 offset;
Vec2 padding;
u32 tab_width; u32 tab_width;
f32 text_size; f32 text_size;
f32 border_thickness; f32 border_thickness;
@ -154,15 +157,16 @@ struct UIItem
i64 highlighted_char; i64 highlighted_char;
// Calculated Parameters // Calculated Parameters
Vec2 size;
Rect rect;
Vec4[4] color; Vec4[4] color;
Vec4[4] border_color; Vec4[4] border_color;
Rect rect;
Vec2 size;
Vec2 last_click_pos;
Vec2 offset;
Vec2 padding;
f32 border_thickness; f32 border_thickness;
f32 corner_radius; f32 corner_radius;
f32 edge_softness; f32 edge_softness;
Vec2 last_click_pos;
Vec2 offset;
} }
struct UISize struct UISize
@ -275,6 +279,8 @@ InitUICtx(PlatformWindow* window)
font: font, font: font,
font_data: cast(u8[])FONT_BYTES, font_data: cast(u8[])FONT_BYTES,
adjustment: 0.0, adjustment: 0.0,
padding: Vec2(0.0),
offset: 0.0,
}; };
u64 vertex_size = 10000; u64 vertex_size = 10000;
@ -530,6 +536,12 @@ SetColor(Vec4 col)
SetColor(col, col, col, col); SetColor(col, col, col, col);
} }
void
SetPadding(Vec2 padding)
{
g_ui_ctx.padding = padding;
}
void void
SetColor(Vec4 col0, Vec4 col1, Vec4 col2, Vec4 col3) SetColor(Vec4 col0, Vec4 col1, Vec4 col2, Vec4 col3)
{ {
@ -696,7 +708,7 @@ CalcFixedSizes(UIItem* item)
{ {
if(i.size_info[axis].type == ST.Pixels) if(i.size_info[axis].type == ST.Pixels)
{ {
i.size.v[axis] = i.size_info[axis].value + i.adjustment.v[axis]; i.size.v[axis] = i.size_info[axis].value + i.adjustment.v[axis] + fabsf(i.offset.v[axis]) + (i.padding.v[axis] * 2.0);
assert(!isNaN(i.size.v[axis])); assert(!isNaN(i.size.v[axis]));
} }
} }
@ -712,7 +724,7 @@ CalcPercentageSizes(UIItem* item)
{ {
if(i.size_info[axis].type == ST.Percentage) if(i.size_info[axis].type == ST.Percentage)
{ {
i.size.v[axis] = (i.parent.size.v[axis]*i.size_info[axis].value) + i.adjustment.v[axis]; i.size.v[axis] = (i.parent.size.v[axis]*i.size_info[axis].value) + fabsf(i.adjustment.v[axis]) + i.offset.v[axis];
assert(!isNaN(i.size.v[axis])); assert(!isNaN(i.size.v[axis]));
} }
} }
@ -725,10 +737,20 @@ CalcPositions(alias axis)(UIItem* item)
f32 pos = 0.0; f32 pos = 0.0;
for(UIItem* i = item; !Nil(i);) for(UIItem* i = item; !Nil(i);)
{ {
f32 end_pos = pos + i.size.v[axis]; f32 end_pos = pos + i.size.v[axis] + i.offset.v[axis];
i.rect.vec0.v[axis] = pos + i.offset.v[axis]; i.rect.vec0.v[axis] = pos + i.offset.v[axis];
i.rect.vec1.v[axis] = end_pos; i.rect.vec1.v[axis] = end_pos;
if(i.parent.offset.v[axis] != 0.0)
{
Logf("parent %s %s %s %s", cast(char[])i.parent.key.text, end_pos, i.parent.rect.vec0.v[axis], i.parent.offset.v[axis]);
}
if(i.offset.v[axis] != 0.0)
{
Logf("%s %s %s %s", cast(char[])i.key.text, end_pos, i.rect.vec0.v[axis], i.offset.v[axis]);
}
assert(!isNaN(i.rect.vec0.v[axis])); assert(!isNaN(i.rect.vec0.v[axis]));
assert(!isNaN(i.rect.vec1.v[axis])); assert(!isNaN(i.rect.vec1.v[axis]));
@ -842,6 +864,7 @@ BuildItem(UIItem* item, UISize size_x, UISize size_y, UIFlags properties)
item.last_frame = ctx.frame; item.last_frame = ctx.frame;
item.highlighted_char = ctx.highlighted_char; item.highlighted_char = ctx.highlighted_char;
item.offset = ctx.offset; item.offset = ctx.offset;
item.padding = ctx.padding;
item.parent = ctx.top_parent == g_UI_NIL_NODE ? g_UI_NIL : ctx.top_parent.item; item.parent = ctx.top_parent == g_UI_NIL_NODE ? g_UI_NIL : ctx.top_parent.item;
if(!Nil(item.parent)) if(!Nil(item.parent))
@ -1136,16 +1159,14 @@ void
DrawLine(UIItem* item) DrawLine(UIItem* item)
{ {
UICtx* ctx = GetCtx(); UICtx* ctx = GetCtx();
f32 y = item.rect.y0 + ctx.text_size; f32 y = item.rect.y0 + ctx.text_size + item.padding.v[A2D.Y];
f32 x = item.rect.x0; f32 x = item.rect.x0 + item.padding.v[A2D.X];
FontAtlas* atlas = &ctx.atlas_buf.atlas; FontAtlas* atlas = &ctx.atlas_buf.atlas;
UIPanel* panel = GetFocusedPanel();
bool active = panel.id == item.parent.key.text;
bool edit_mode = EditModeActive(); bool edit_mode = EditModeActive();
Vertex* v; Vertex* v;
if(item.highlighted_char >= 0 && active) if(item.highlighted_char >= 0)
{ {
v = ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count; v = ctx.buffers[ctx.f_idx].vtx.ptr + ctx.buffers[ctx.f_idx].count;
AddUIIndices(ctx); AddUIIndices(ctx);
@ -1333,6 +1354,18 @@ Clicked(UIItem* item, DNode!(InputEvent)* n)
return result; return result;
} }
u8[]
ScratchName(u8[] base, string append)
{
u8[] u8_append = CastStr!(u8)(append);
u8[] id = ScratchAlloc!(u8)(base.length+append.length);
id[0 .. base.length] = base[0 .. $];
id[base.length .. $] = u8_append[0 .. $];
return id;
}
void void
SetFocus(UIItem* item) SetFocus(UIItem* item)
{ {

View File

@ -8,6 +8,8 @@ import std.format : sformat;
import std.math.rounding : ceil, floor; import std.math.rounding : ceil, floor;
import std.math.exponential : pow; import std.math.exponential : pow;
import core.stdc.math : fabsf; import core.stdc.math : fabsf;
import std.conv;
import core.stdc.stdio : sprintf;
const UIPanel g_ui_nil_panel; const UIPanel g_ui_nil_panel;
UIPanel* g_UI_NIL_PANEL; UIPanel* g_UI_NIL_PANEL;
@ -28,17 +30,18 @@ struct UIPanel
u8[] id; u8[] id;
Editor* ed; Editor* ed;
UIPanel* parent; UIPanel* parent;
UIPanel* next; UIPanel* next;
UIPanel* prev; UIPanel* prev;
UIPanel* first; UIPanel* first;
UIPanel* last; UIPanel* last;
UIPanel* list_next; UIPanel* list_next;
Axis2D axis; Axis2D axis;
f32 pct; SizeType size_type;
Vec4 color; f32 pct;
Vec4 color;
i64 prev_offset; i64 prev_offset;
i64 start_row; i64 start_row;
@ -131,6 +134,85 @@ Panel(UIPanel* panel, UIFlags flags = UIF.None)
return item; return item;
} }
UIItem*
LineCounter(u8[] parent_id, FlatBuffer* buf, f32 offset, i64 start_row, i64 end_row)
{
u8[] id = ScratchName(parent_id, "linec");
auto end_chars = end_row.toChars();
u64 width = cast(u64)(end_chars.length);
char[20] ch_buf;
ch_buf.sformat("%%0%sllu%%s", width);
u8[] max_row_text;
u8[][] line_counts = ScratchAlloc!(u8[])(end_row-start_row);
if(line_counts.length > 0)
{
for(u64 i = 0; start_row+i < end_row; i += 1)
{
line_counts[i] = ScratchAlloc!(u8)(width+parent_id.length);
sprintf(cast(char*)line_counts[i].ptr, ch_buf.ptr, start_row+i, cast(char*)parent_id.ptr);
}
max_row_text = ScratchAlloc!(u8)(width);
max_row_text[] = cast(u8)'0';
}
SetPadding(Vec2(4.0, 0.0));
SetColor(Vec4(0.2, 0.5, 0.65, 1.0));
UISize s_x = UISize(ST.Pixels, CalcTextWidth(max_row_text));
UISize s_y = UISize(ST.Percentage, 1.0);
UIItem* item = Container(ScratchName(parent_id, "linec"), s_x, s_y, A2D.Y, UIF.DrawBackground);
SetOffset(Vec2(0.0, offset));
UIItem* inner = Container(ScratchName(parent_id, "lcinner"), s_x, s_y, A2D.Y, UIF.None);
for(u64 i = 0; i < line_counts.length; i += 1)
{
UIItem* line = Text(line_counts[i]);
}
SetOffset(Vec2(0.0));
SetPadding(Vec2(0.0));
EndContainer();
EndContainer();
return item;
}
UIItem*
Container(u8[] text, UISize size_x, UISize size_y, Axis2D axis, UIF flags = UIF.None)
{
UIItem* item = Get(text);
SetLayoutAxis(axis);
BuildItem(item, size_x, size_y, flags);
PushParent(item);
return item;
}
void
EndContainer()
{
PopParent();
}
UIItem*
Text(u8[] text)
{
UIItem* item = Get(text);
f32 width = CalcTextWidth(item.key.text);
BuildItem(item, UISize(ST.Pixels, width), UISize(ST.Pixels, 16.0), UIF.DrawText);
return item;
}
void void
Separator(UIPanel* panel, UIItem* parent, f32* adj_x, f32* adj_y) Separator(UIPanel* panel, UIItem* parent, f32* adj_x, f32* adj_y)
{ {
@ -234,6 +316,8 @@ EditorView(UIPanel* panel)
bool focused = panel == GetFocusedPanel(); bool focused = panel == GetFocusedPanel();
Container(ScratchName(panel.id, "cntr"), UISize(ST.Percentage, 1.0), UISize(ST.Percentage, 1.0), A2D.X);
f32 text_size = 16.0; f32 text_size = 16.0;
f32 height = 0.0; f32 height = 0.0;
@ -248,7 +332,9 @@ EditorView(UIPanel* panel)
SetPanelScroll(panel, rows, text_size); SetPanelScroll(panel, rows, text_size);
} }
f32 offset = 0.0;
i64 line_offset = ed.buf.offset; i64 line_offset = ed.buf.offset;
i64 line_rows = rows;
if(panel.anim.remaining_time > 0.0) with(panel.anim) if(panel.anim.remaining_time > 0.0) with(panel.anim)
{ {
remaining_time -= g_delta; remaining_time -= g_delta;
@ -257,9 +343,8 @@ EditorView(UIPanel* panel)
remaining_time = 0.0; remaining_time = 0.0;
} }
f32 offset = Remap(remaining_time, 0.0, start_time, 0.0, 1.0); offset = Remap(remaining_time, 0.0, start_time, 0.0, 1.0);
offset = Remap(EaseOutExp(offset), 0.0, 1.0, start_value, end_value); offset = Remap(EaseOutExp(offset), 0.0, 1.0, start_value, end_value);
SetOffset(Vec2(0.0, offset));
if(remaining_time == 0.0) if(remaining_time == 0.0)
{ {
@ -267,6 +352,7 @@ EditorView(UIPanel* panel)
} }
line_offset = panel.start_row; line_offset = panel.start_row;
line_rows = panel.end_row-panel.start_row;
GetLines(&ed.buf, &ed.linebufs, panel.start_row, panel.end_row-panel.start_row); GetLines(&ed.buf, &ed.linebufs, panel.start_row, panel.end_row-panel.start_row);
} }
else else
@ -274,6 +360,11 @@ EditorView(UIPanel* panel)
GetLines(&ed.buf, &ed.linebufs, rows); GetLines(&ed.buf, &ed.linebufs, rows);
} }
LineCounter(panel.id, &panel.ed.buf, offset, line_offset, line_offset+line_rows);
SetOffset(Vec2(0.0, offset));
Container(ScratchName(panel.id, "lines"), UISize(ST.Percentage, 1.0), UISize(ST.Percentage, 1.0), A2D.Y);
U64Vec2 pos = VecPos(&ed.buf); U64Vec2 pos = VecPos(&ed.buf);
u64 i = 0; u64 i = 0;
for(LineBuffer* buf = ed.linebufs.first; buf != null; buf = buf.next, i += 1) for(LineBuffer* buf = ed.linebufs.first; buf != null; buf = buf.next, i += 1)
@ -296,7 +387,7 @@ EditorView(UIPanel* panel)
SetHighlightedChar(-1); SetHighlightedChar(-1);
} }
SetOffset(Vec2(0.0));
Signal(item); Signal(item);
@ -305,7 +396,9 @@ EditorView(UIPanel* panel)
SetFocusedPanel(panel); SetFocusedPanel(panel);
} }
SetOffset(Vec2(0.0)); EndContainer();
EndContainer();
EndPanel(); EndPanel();
} }