implement scrolling, various fixes

This commit is contained in:
Matthew 2025-12-23 18:43:20 +11:00
parent 39ab34ebeb
commit ace749228d
3 changed files with 326 additions and 110 deletions

@ -1 +1 @@
Subproject commit 7f4c109106eaabda180158a8f7a92c9d2e60d3db Subproject commit 809814577db807d5911e79216d6e114a2d5a2dfd

View File

@ -154,7 +154,11 @@ struct UIInput
UIInput* next, prev; UIInput* next, prev;
union union
{ {
Input key; struct
{
Input key;
string text;
};
IVec2 rel; IVec2 rel;
IVec2 pos; IVec2 pos;
} }
@ -168,8 +172,8 @@ UICtxParameter(T, string name)
{ {
import std.traits, std.array; import std.traits, std.array;
string stack_top = "\tStackTop!("~T.stringof~") "~name~";\n"; string stack_top = "\tStackTop!("~T.stringof~") "~name~";\n";
string stack = "\tStack!("~T.stringof~")* "~name~"_top;\n"; string stack = "\tStack!("~T.stringof~")* "~name~"_top;\n";
return stack_top~stack; return stack_top~stack;
} }
@ -177,7 +181,8 @@ UICtxParameter(T, string name)
mixin(CtxParameterGen!(T, name)()); mixin(CtxParameterGen!(T, name)());
} }
template CtxMemberInfo(int i) template
CtxMemberInfo(int i)
{ {
import std.string : endsWith, startsWith; import std.string : endsWith, startsWith;
import std.traits : isInstanceOf, isPointer; import std.traits : isInstanceOf, isPointer;
@ -274,31 +279,32 @@ struct StackTop(T)
Stack!(T)* free; Stack!(T)* free;
} }
mixin template UIItemParameters() static string
UIItemParameterGen()
{ {
static string string fields = "";
UIItemParameterGen() static foreach(i, m; UICtx.tupleof)
{ {
string fields = "";
static foreach(i, m; UICtx.tupleof)
{ {
enum info = CtxMemberInfo!(i);
static if(info.is_stack)
{ {
enum info = CtxMemberInfo!(i); fields ~= typeof(UICtx.tupleof[i].top.value).stringof ~ " " ~ info.id;
static if(info.is_stack) static if(is(typeof(UICtx.tupleof[i]): f32))
{ {
fields ~= typeof(UICtx.tupleof[i].top.value).stringof ~ " " ~ info.id; fields ~= " = 0.0";
static if(is(typeof(UICtx.tupleof[i]): f32))
{
fields ~= " = 0.0";
}
fields ~= ";\n";
} }
fields ~= ";\n";
} }
} }
return fields;
} }
return fields;
}
mixin template
UIItemParameters()
{
mixin(UIItemParameterGen()); mixin(UIItemParameterGen());
} }
@ -677,17 +683,21 @@ InitSingleLine:
{ {
if(item.flags & (UIF.ScrollX << axis)) if(item.flags & (UIF.ScrollX << axis))
{ {
item.scroll_offset.v[axis] += scroll_speed * (item.scroll_target.v[axis] - item.scroll_offset.v[axis]); if(fabsf(item.scroll_offset.v[axis] - item.scroll_target.v[axis]) > 0.0009)
if(fabsf(item.scroll_offset.v[axis] - item.scroll_target.v[axis]) < 2.0)
{ {
item.scroll_offset.v[axis] = item.scroll_target.v[axis]; f32 v = scroll_speed * (item.scroll_target.v[axis] - item.scroll_offset.v[axis]);
item.scroll_offset.v[axis] += v;
if(fabsf(item.scroll_offset.v[axis] - item.scroll_target.v[axis]) < 2.0)
{
item.scroll_offset.v[axis] = item.scroll_target.v[axis];
}
} }
} }
if(item.flags & (UIF.ClampX << axis)) if(item.flags & (UIF.ClampX << axis))
{ {
item.scroll_offset = clamp(item.scroll_offset.v[axis], item.scroll_clamp[axis].x, item.scroll_clamp[axis].y); item.scroll_offset.v[axis] = clamp(item.scroll_offset.v[axis], item.scroll_clamp[axis].x, item.scroll_clamp[axis].y);
} }
} }
@ -822,7 +832,7 @@ BeginUI(Inputs* inputs)
} break; } break;
default: default:
{ {
PushUIEvent(ctx, UIInput(type: UIE.Press, key: i.key)); PushUIEvent(ctx, UIInput(type: UIE.Press, key: i.key, text: i.pressed ? i.text : []));
} break; } break;
} }
} }
@ -851,7 +861,7 @@ BeginUI(Inputs* inputs)
// Ctx state // Ctx state
ctx.f_idx = ctx.frame%FRAME_OVERLAP; ctx.f_idx = ctx.frame%FRAME_OVERLAP;
ctx.inputs = inputs; ctx.inputs = inputs;
ctx.char_width = GlyphWidth(&ctx.atlas_buf.atlas.glyphs['0']); ctx.char_width = GlyphWidth(&ctx.atlas_buf.atlas.glyphs[' ']);
ResetStacks(ctx); ResetStacks(ctx);
@ -880,13 +890,13 @@ BeginUI(Inputs* inputs)
// Root Item // Root Item
UISize[2] sizes = [UISize(ST.Pixels, ctx.res.x), UISize(ST.Pixels, ctx.res.y)]; UISize[2] sizes = [UISize(ST.Pixels, ctx.res.x), UISize(ST.Pixels, ctx.res.y)];
Push!("size_info")(ctx, sizes); Push!("size_info")(sizes);
ctx.root = MakeItem("###root"); ctx.root = MakeItem("###root");
ctx.window_root = MakeItem("###window_root"); ctx.window_root = MakeItem("###window_root");
Pop!("size_info")(ctx); Pop!("size_info");
Push!("parent")(ctx, ctx.root); Push!("parent")(ctx.root);
} }
void void
@ -999,7 +1009,7 @@ EndUI()
{ {
f32 size = InnerSize!(axis)(item); f32 size = InnerSize!(axis)(item);
if(item.flags & (UIF.PortalX << axis)) if(item.flags & (UIF.PortalViewX << axis))
{ {
continue; continue;
} }
@ -1067,7 +1077,7 @@ EndUI()
} }
else if(item == item.parent.first) else if(item == item.parent.first)
{ {
pos += item.parent.padding.v[axis]; pos += item.parent.padding.v[axis] + item.parent.view_offset.v[axis];
} }
f32 inner_pos = pos; f32 inner_pos = pos;
@ -1082,6 +1092,7 @@ EndUI()
assert(!isNaN(item.rect.p0.v[axis])); assert(!isNaN(item.rect.p0.v[axis]));
assert(!isNaN(item.rect.p1.v[axis])); assert(!isNaN(item.rect.p1.v[axis]));
/*
debug debug
{ {
bool portal = cast(bool)(item.parent.flags & (UIF.PortalViewX << axis)); bool portal = cast(bool)(item.parent.flags & (UIF.PortalViewX << axis));
@ -1103,6 +1114,7 @@ EndUI()
assert(in_bounds_start && in_bounds_end); assert(in_bounds_start && in_bounds_end);
} }
} }
*/
if(!Nil(item.first)) if(!Nil(item.first))
{ {
@ -1169,8 +1181,8 @@ RenderItem(UICtx* ctx, UIItem* item)
{ {
DrawUI(ctx); DrawUI(ctx);
u32 x = cast(u32)(scissor_x ? floor(item.rect.p0.x) : ctx.res.x); u32 x = cast(u32)(scissor_x ? floor(item.rect.p0.x) : 0);
u32 y = cast(u32)(scissor_y ? floor(item.rect.p0.y) : ctx.res.y); u32 y = cast(u32)(scissor_y ? floor(item.rect.p0.y) : 0);
u32 w = cast(u32)(scissor_x ? floor(item.rect.p1.x) - x : ctx.res.x); u32 w = cast(u32)(scissor_x ? floor(item.rect.p1.x) - x : ctx.res.x);
u32 h = cast(u32)(scissor_y ? floor(item.rect.p1.y) - y : ctx.res.y); u32 h = cast(u32)(scissor_y ? floor(item.rect.p1.y) - y : ctx.res.y);
SetScissor(&ctx.rd, x, y, w, h); SetScissor(&ctx.rd, x, y, w, h);
@ -1178,7 +1190,6 @@ RenderItem(UICtx* ctx, UIItem* item)
if(item.flags & UIF.DrawBackground) if(item.flags & UIF.DrawBackground)
{ {
// DrawRect
Vertex* v = GetVertex(ctx); Vertex* v = GetVertex(ctx);
v.dst_start = item.rect.p0 + item.border_thickness; v.dst_start = item.rect.p0 + item.border_thickness;
v.dst_end = item.rect.p1 - item.border_thickness; v.dst_end = item.rect.p1 - item.border_thickness;
@ -1284,23 +1295,117 @@ GetExtent(Renderer* rd)
} }
template template
StackIDs(string stack) StackIDs(string stack, string ctx = "ctx")
{ {
import std.string : replace; import std.string : replace;
struct Identifiers { string stack, stack_top_node; } struct Identifiers { string stack, stack_top_node; }
enum Identifiers StackIDs = { enum Identifiers StackIDs = {
stack: replace("ctx.@", "@", stack), stack: replace(ctx~".@", "@", stack),
stack_top_node: replace("ctx.@_top", "@", stack), stack_top_node: replace(ctx~".@_top", "@", stack),
}; };
} }
void void
Push(string stack_str, bool auto_pop = false, T)(UICtx* ctx, T value) PushSizeInfoVec(int i)(SizeType type, f32 value, f32 strictness = 1.0, bool auto_pop = false)
{
UISize[2] size_info = g_size_info_default;
size_info[i].type = type;
size_info[i].value = value;
size_info[i].strictness = strictness;
Push!("size_info")(size_info, auto_pop);
}
void
PushSizeInfoX(SizeType type, f32 value, f32 strictness = 1.0, bool auto_pop = false)
{
PushSizeInfoVec!(0)(type, value, strictness, auto_pop);
}
void
PushSizeInfoY(SizeType type, f32 value, f32 strictness = 1.0, bool auto_pop = false)
{
PushSizeInfoVec!(1)(type, value, strictness, auto_pop);
}
void
PushScrollClampVec(int i)(Vec2 clamp, bool auto_pop)
{
Vec2[2] scroll_clamp = g_scroll_clamp_default;
scroll_clamp[i] = clamp;
Push!("scroll_clamp")(scroll_clamp, auto_pop);
}
void
PushScrollClampX(f32 start, f32 end, bool auto_pop = false)
{
PushScrollClampVec!(0)(Vec2(start, end), auto_pop);
}
void
PushScrollClampY(f32 start, f32 end, bool auto_pop = false)
{
PushScrollClampVec!(1)(Vec2(start, end), auto_pop);
}
void
PushBorderCol(Vec4 col, bool auto_pop = false)
{
Vec4[4] arr = col;
PushBorderCol(arr, auto_pop);
}
void
PushBgCol(Vec4 col, bool auto_pop = false)
{
Vec4[4] arr = col;
PushBgCol(arr, auto_pop);
}
void
PushPaddingX(f32 padding, bool auto_pop = false)
{
PushPadding(Vec2(padding, 0.0), auto_pop);
}
void
PushPaddingY(f32 padding, bool auto_pop = false)
{
PushPadding(Vec2(0.0, padding), auto_pop);
}
void
PushViewOffsetX(f32 offset, bool auto_pop = false)
{
PushViewOffset(Vec2(offset, 0.0), auto_pop);
}
void
PushViewOffsetY(f32 offset, bool auto_pop = false)
{
PushViewOffset(Vec2(0.0, offset), auto_pop);
}
void
PushScrollTargetX(f32 target, bool auto_pop = false)
{
PushScrollTarget(Vec2(target, 0.0), auto_pop);
}
void
PushScrollTargetY(f32 target, bool auto_pop = false)
{
PushScrollTarget(Vec2(0.0, target), auto_pop);
}
void
Push(string stack_str, T)(T value, bool auto_pop = false)
{ {
import std.string : replace; import std.string : replace;
enum ids = StackIDs!(stack_str); enum ids = StackIDs!(stack_str, "g_ui_ctx");
auto stack = &mixin(ids.stack); auto stack = &mixin(ids.stack);
auto top = mixin(ids.stack_top_node); auto top = mixin(ids.stack_top_node);
@ -1312,7 +1417,7 @@ Push(string stack_str, bool auto_pop = false, T)(UICtx* ctx, T value)
} }
else else
{ {
node = Alloc!(Stack!(T))(&ctx.temp_arena); node = Alloc!(Stack!(T))(&g_ui_ctx.temp_arena);
} }
node.next = stack.top; node.next = stack.top;
@ -1322,12 +1427,29 @@ Push(string stack_str, bool auto_pop = false, T)(UICtx* ctx, T value)
stack.top = node; stack.top = node;
} }
static string
PushScope(string stack_str, alias __value)()
{
enum string id = __traits(identifier, __value);
static if(id == "__value")
{
string value_str = "cast(typeof("~StackIDs!(stack_str, "g_ui_ctx").stack~".top.value))(" ~ __value.stringof ~ ")";
}
else
{
string value_str = __traits(identifier, __value);
}
return "Push!(\"" ~ stack_str ~ "\")(" ~ value_str ~ ");\n scope(exit) Pop!(\"" ~ stack_str ~ "\");";
}
auto auto
Pop(string stack_str)(UICtx* ctx) Pop(string stack_str)()
{ {
import std.string : replace; import std.string : replace;
enum ids = StackIDs!(stack_str); enum ids = StackIDs!(stack_str, "g_ui_ctx");
auto stack = &mixin(ids.stack); auto stack = &mixin(ids.stack);
auto top = mixin(ids.stack_top_node); auto top = mixin(ids.stack_top_node);
@ -1345,14 +1467,52 @@ Pop(string stack_str)(UICtx* ctx)
} }
void void
Pop(stack_strs...)(UICtx* ctx) Pop(stack_strs...)()
{ {
static foreach(stack; stack_strs) static foreach(stack; stack_strs)
{ {
Pop!(stack)(ctx); Pop!(stack)();
} }
} }
static string
GenPushFuncs()
{
import std.array : split;
import std.uni : toUpper;
string funcs = "";
static foreach(i, m; UICtx.tupleof)
{
{
enum info = CtxMemberInfo!(i);
static if(info.is_stack)
{
string[] parts = split(info.id, "_");
string fn_name = "Push";
foreach(p; parts)
{
if(p.length == 1)
{
fn_name ~= toUpper(p[0 .. 1]);
}
else
{
fn_name ~= toUpper(p[0 .. 1]) ~ p[1 .. $];
}
}
funcs ~= "pragma(inline) void " ~ fn_name ~ "(T)(T value, bool auto_pop = false){ Push!(\"" ~ info.id ~ "\")(value, auto_pop); }\n";
}
}
}
return funcs;
}
mixin(GenPushFuncs());
void void
AutoPopStacks(UICtx* ctx) AutoPopStacks(UICtx* ctx)
{ {
@ -1368,7 +1528,7 @@ AutoPopStacks(UICtx* ctx)
if(ctx.tupleof[i].top.auto_pop) if(ctx.tupleof[i].top.auto_pop)
{ {
ctx.tupleof[i].top.auto_pop = false; ctx.tupleof[i].top.auto_pop = false;
Pop!(member_info.id)(ctx); Pop!(member_info.id);
} }
} }
} }
@ -1595,8 +1755,6 @@ NewItem(UICtx* ctx)
item = Alloc!(UIItem)(&ctx.arena); item = Alloc!(UIItem)(&ctx.arena);
} }
item.last_frame = ctx.frame-2;
return item; return item;
} }
@ -1666,8 +1824,7 @@ CalcTextWidth(string str)
pragma(inline) f32 pragma(inline) f32
GlyphWidth(Glyph* g) GlyphWidth(Glyph* g)
{ {
f32 width = 0.0; f32 width = g.ch == '\t' ? (g_ui_ctx.atlas_buf.atlas.glyphs[' '].advance*cast(f32)(g_ui_ctx.tab_width)) : g.advance;
width += g.ch == '\t' ? (g_ui_ctx.atlas_buf.atlas.glyphs[' '].advance*cast(f32)(g_ui_ctx.tab_width)) : g.advance;
return width; return width;
} }
@ -1962,11 +2119,22 @@ Dragged(UIItem* item, Rect* rect)
return result; return result;
} }
pragma(inline) Vec4[4] static Vec4[4]
Vec4Arr(Vec4 col) Vec4Arr(Vec4 vec)
{ {
Vec4[4] arr = col; return [vec, vec, vec, vec];
return arr; }
static Vec2[2]
Vec2ArrX(alias Vec2 vec)()
{
return [vec, Vec2(0.0)];
}
static Vec2[2]
Vec2ArrY(alias Vec2 vec)()
{
return [Vec2(0.0), vec];
} }
unittest unittest
@ -1995,7 +2163,7 @@ unittest
Vec4 w = Vec4(1.0); Vec4 w = Vec4(1.0);
Vec4[4] col = w; Vec4[4] col = w;
Push!("bg_col")(ctx, col); Push!("bg_col")(col);
assert(ctx.bg_col.top.value == col); assert(ctx.bg_col.top.value == col);
EndUI(); EndUI();
@ -2011,7 +2179,7 @@ unittest
{ {
BeginUI(&inputs); BeginUI(&inputs);
Push!("size_info")(ctx, MakeUISizeX(ST.Percentage, 0.5)); Push!("size_info")(MakeUISizeX(ST.Percentage, 0.5));
UIItem* root = ctx.root; UIItem* root = ctx.root;
UIItem* i0 = MakeItem("###i0"); UIItem* i0 = MakeItem("###i0");

View File

@ -14,6 +14,93 @@ Nil(UIPanel* panel)
return panel == null || panel == g_UI_NIL_PANEL; return panel == null || panel == g_UI_NIL_PANEL;
} }
void
LineCounterView(u64 max_line, u64 lines, u64 line_offset, f32 view_offset)
{
UICtx* ctx = GetCtx();
UIKey zero = ZeroKey();
u64 ch_width = max_line.toChars().length;
f32 lc_width = cast(f32)(ch_width+1)*ctx.char_width; // Should figure out how to accurately measure text width
PushLayoutAxis(A2D.Y, true);
PushViewOffsetY(view_offset, true);
PushPaddingX(4.0, true);
PushSizeInfoX(ST.Pixels, lc_width, 1.0, true);
UIItem* line_count = MakeItem(zero, UIF.DrawBorder|UIF.PortalViewY);
PushTextCol(Vec4(1.0));
PushSizeInfoY(ST.Pixels, TEXT_SIZE);
PushParent(line_count);
u64 end_line = lines+line_offset;
for(u64 i = line_offset; i < end_line; i += 1)
{
char[] buf = ScratchAlloc!(char)(ch_width);
Push!("display_string")(ConvToStr(sformat(buf, "%s", i)), true);
MakeItem(zero, UIF.DrawText);
}
Pop!("text_col", "size_info", "parent");
}
void
EditorTextView(UIItem* editor, Editor* ed, u64 lines, u64 line_offset, f32 view_offset)
{
PushLayoutAxis(A2D.Y, true);
f32 clamp_y = cast(f32)(ed.buf.line_count-lines)*TEXT_SIZE;
f32 scroll_pos = cast(f32)(ed.line_offset)*TEXT_SIZE;
PushLayoutAxis(A2D.Y, true);
PushScrollClampY(0.0, clamp_y, true);
PushSizeInfo(g_size_info_default, true);
PushBorderCol(Vec4(1.0), true);
PushScrollTargetY(scroll_pos, true);
PushViewOffsetY(view_offset, true);
static bool end;
static f32 count = 0.0;
if(!end)
{
ed.cursor_pos.y = 500;
count += g_delta;
if(count > 0.5)
{
end = !end;
}
}
else
{
ed.cursor_pos.y = 0;
count -= g_delta;
if(count <= 0.0)
{
end = !end;
}
}
editor = MakeItem(editor.key, UIF.DrawBorder|UIF.ScrollY|UIF.ClampY);
u64 end_line = line_offset+lines;
UIKey zero = ZeroKey();
PushSizeInfoY(ST.TextSize, 1.0);
PushParent(editor);
scope(exit) Pop!("size_info", "parent");
u64 i = line_offset;
for(LineBuffer* lb = GetLine(&ed.buf, i); !CheckNil(g_NIL_LINE_BUF, lb) && i < line_offset+lines; i += 1, lb = GetLine(&ed.buf, i))
{
PushDisplayString(ConvToStr(lb.text), true);
UIItem* line = MakeItem(zero, UIF.DrawText);
}
}
void void
EditorView(Editor* ed) EditorView(Editor* ed)
{ {
@ -23,83 +110,44 @@ EditorView(Editor* ed)
UIItem* editor = Get(ed_key); UIItem* editor = Get(ed_key);
u64 frame_line_offset = ed.line_offset; u64 frame_line_offset = ed.line_offset;
f32 frame_view_offset = editor.scroll_offset.y%TEXT_SIZE; f32 frame_view_offset = -(editor.scroll_offset.y%TEXT_SIZE);
PushBgCol(Vec4(0.2, 0.3, 0.8, 1.0), true);
PushSizeInfoX(ST.Percentage, 1.0, 1.0, true);
Push!("bg_col", true)(ctx, Vec4Arr(Vec4(0.2, 0.3, 0.8, 1.0)));
Push!("size_info", true)(ctx, MakeUISizeX(ST.Percentage, 1.0));
UIItem* container = MakeItem(zero, UIF.DrawBackground); UIItem* container = MakeItem(zero, UIF.DrawBackground);
Push!("parent")(ctx, container); PushParent(container);
PushBorderCol(Vec4(1.0));
Push!("border_col")(ctx, Vec4Arr(Vec4(1.0))); scope(exit) Pop!("parent", "border_col");
// Line Counter
f32 lc_width = ed.buf.line_count.toChars().length*ctx.char_width;
Push!("layout_axis", true)(ctx, A2D.Y);
Push!("view_offset" )(ctx, Vec2(0.0, frame_view_offset));
Push!("padding", true)(ctx, Vec2(4.0, 0.0));
Push!("size_info", true)(ctx, MakeUISizeX(ST.Pixels, lc_width));
UIItem* line_count = MakeItem(zero, UIF.DrawBorder);
// Editor
f32 scroll_pos = cast(f32)(ed.line_offset)*TEXT_SIZE;
Push!("layout_axis", true)(ctx, A2D.Y);
Push!("scroll_clamp", true)(ctx, cast(Vec2[2])[Vec2(0.0), Vec2(0.0, cast(f32)(ed.buf.line_count)*TEXT_SIZE)]);
Push!("size_info", true)(ctx, MakeUISize(UISize(ST.Percentage, 1.0), UISize(ST.Percentage, 1.0)));
Push!("border_col", true)(ctx, Vec4Arr(Vec4(1.0)));
Push!("scroll_target", true)(ctx, Vec2(0.0, scroll_pos));
editor = MakeItem(ed_key, UIF.DrawBorder|UIF.ScrollY|UIF.ClampY);
Pop!("view_offset")(ctx);
u64 view_lines; u64 view_lines;
if(editor.size.y > 0.0) if(editor.size.y > 0.0)
{ {
view_lines = cast(u64)ceil(editor.size.y/TEXT_SIZE); view_lines = cast(u64)ceil(editor.size.y/TEXT_SIZE)+1;
const u64 SCROLL_BUFFER = 2; const u64 SCROLL_BUFFER = 4;
u64 start = ed.line_offset; u64 start = ed.line_offset;
u64 end = start+view_lines; u64 end = start+view_lines;
if(ed.cursor_pos.y < start) if(ed.cursor_pos.y < start)
{ {
ed.line_offset = clamp(ed.cursor_pos.y - SCROLL_BUFFER, 0, ed.buf.line_count); u64 pos = ed.cursor_pos.y > SCROLL_BUFFER ? ed.cursor_pos.y - SCROLL_BUFFER : ed.cursor_pos.y;
ed.line_offset = clamp(pos, 0, ed.buf.line_count);
} }
else if(ed.cursor_pos.y > end) else if(ed.cursor_pos.y > end)
{ {
ed.line_offset = clamp(ed.cursor_pos.y + SCROLL_BUFFER - view_lines, 0, ed.buf.line_count); ed.line_offset = clamp(ed.cursor_pos.y + SCROLL_BUFFER - view_lines, 0, ed.buf.line_count);
} }
} }
Push!("size_info")(ctx, MakeUISizeY(ST.Pixels, TEXT_SIZE)); u64 start = cast(u64)floor(editor.scroll_offset.y/TEXT_SIZE);
Push!("parent" )(ctx, line_count);
Push!("text_col" )(ctx, Vec4(1.0));
u64 end_line = frame_line_offset+view_lines; LineCounterView(ed.buf.line_count, view_lines, start, frame_view_offset);
for(u64 i = frame_line_offset; i < end_line; i += 1) EditorTextView(editor, ed, view_lines, start, frame_view_offset);
{
MakeItem("%s##ed_%s", i, ed.editor_id, UIF.DrawText);
}
Pop!("parent", "size_info")(ctx);
Push!("size_info")(ctx, MakeUISizeY(ST.TextSize, 1.0));
Push!("parent")(ctx, editor);
u64 i = frame_line_offset;
for(LineBuffer* lb = GetLine(&ed.buf, i); !CheckNil(g_NIL_LINE_BUF, lb) && i < end_line; i += 1, lb = GetLine(&ed.buf, i))
{
Push!("display_string", true)(ctx, ConvToStr(lb.text));
UIItem* line = MakeItem(zero, UIF.DrawText);
}
Pop!("parent", "parent", "text_col")(ctx);
} }
/* /*