continued ui work

This commit is contained in:
Matthew 2025-12-21 22:21:31 +11:00
parent cce502ae43
commit 9950647cf9
9 changed files with 274 additions and 184 deletions

Binary file not shown.

Binary file not shown.

View File

@ -12,25 +12,27 @@ struct FlatBuffer
Arena arena;
Arena ls_arena;
LineBuffers linebufs;
BufferInfo info;
u8[] file_name;
u8[] _buf;
u8* pbuf;
u8[] data;
u64 length;
Line[] lines;
u64 line_count;
i64 pos;
i64 col_pos;
I64Vec2 sel;
SelectMode sel_mode;
f32 view_width;
bool dirty;
alias info this;
}
struct BufferInfo
{
u64 line_count;
I64Vec2 selection;
IVec2 position;
}
enum SelectMode
@ -55,9 +57,6 @@ struct LineBuffers
Arena arena;
LineBuffer* first;
LineBuffer* last;
u64 count;
u64 start;
u64 end;
}
struct LineBuffer
@ -142,30 +141,29 @@ Init(FlatBuffer* fb, u8[] data, u8[] file_name)
fb.file_name = file_name;
fb.line_count = CountLF(data);
fb.length = data.length;
fb.sel = -1;
fb.selection = -1;
fb.sel_mode = SM.None;
fb.linebufs = CreateLineBuffers(MB(1));
SetBuffers(fb, buf);
MemCpy(fb.pbuf, data.ptr, data.length);
MemCpy(fb.data.ptr, data.ptr, data.length);
}
void
SetBuffers(FlatBuffer* fb, u8[] data)
{
fb._buf = data;
fb.pbuf = fb._buf.ptr+BUF_START;
fb.data = data;
}
void
Change(FlatBuffer* fb, u8[] data, u8[] file_name)
{
Free(fb._buf);
Free(fb.data);
Reset(&fb.linebufs.arena);
Init(fb, data, file_name);
ResetTokenizer(&fb.tk, fb._buf.length);
ResetTokenizer(&fb.tk, fb.data.length);
Fix(fb);
}
@ -182,14 +180,14 @@ CountLF(u8[] data)
}
pragma(inline) bool
ScanLineRightBrace(u8* pbuf, u64 start, u64 len)
ScanLineRightBrace(u8* data, u64 start, u64 len)
{
bool result;
for(u64 i = start; i < len; i += 1)
{
if(pbuf[i] == '\t' || pbuf[i] == ' ') continue;
if(data[i] == '\t' || data[i] == ' ') continue;
if(pbuf[i] == '}' || pbuf[i] == ']' || pbuf[i] == ')')
if(data[i] == '}' || data[i] == ']' || data[i] == ')')
{
result = true;
break;
@ -216,7 +214,7 @@ Fix(FlatBuffer* fb)
u64 ls_idx = 1;
for(u64 i = 0; i < length; i += 1)
{
if(pbuf[i] == '{' || pbuf[i] == '(' || pbuf[i] == '[')
if(data[i] == '{' || data[i] == '(' || data[i] == '[')
{
if(pending_level > 0)
{
@ -228,7 +226,7 @@ Fix(FlatBuffer* fb)
}
}
else if(pbuf[i] == '}' || pbuf[i] == ')' || pbuf[i] == ']')
else if(data[i] == '}' || data[i] == ')' || data[i] == ']')
{
if(ignore > 0)
{
@ -248,7 +246,7 @@ Fix(FlatBuffer* fb)
}
}
if(pbuf[i] == '\n')
if(data[i] == '\n')
{
level += pending_level;
pending_level = 0;
@ -284,10 +282,10 @@ CreateLineBuffers(u64 arena_size)
void
Insert(FlatBuffer* fb, u8[] insert, u64 length, u64 pos)
{
if(fb.length + length > fb._buf.length-SPACING)
if(fb.length + length > fb.data.length-SPACING)
{
SetBuffers(&fb.tk, Realloc(fb.tk._tokens, fb._buf.length*2));
SetBuffers(fb, Realloc(fb._buf, fb._buf.length*2));
SetBuffers(&fb.tk, Realloc(fb.tk.tokens, fb.data.length*2));
SetBuffers(fb, Realloc(fb.data, fb.data.length*2));
}
u64 new_lines;
@ -311,8 +309,8 @@ Insert(FlatBuffer* fb, u8[] insert, u64 length, u64 pos)
if(new_ch == '\n' && pos > 0)
{
u8 l = fb.pbuf[pos-1];
u8 r = fb.pbuf[pos];
u8 l = fb.data[pos-1];
u8 r = fb.data[pos];
bool expand = (l == '(' && r == ')') || (l == '{' && r == '}') || (l == '[' && r == ']');
u32 level = LevelFromPos(fb, pos) + u32(expand);
@ -343,11 +341,11 @@ Insert(FlatBuffer* fb, u8[] insert, u64 length, u64 pos)
u64 temp_len = fb.length-pos;
u8[] temp = Alloc!(u8)(&fb.arena, fb.pbuf[pos .. pos+temp_len]);
u8[] temp = Alloc!(u8)(&fb.arena, fb.data[pos .. pos+temp_len]);
fb.pbuf[pos .. pos+length] = insert[0 .. length];
fb.data[pos .. pos+length] = insert[0 .. length];
pos += length;
fb.pbuf[pos .. pos+temp_len] = temp[0 .. temp_len];
fb.data[pos .. pos+temp_len] = temp[0 .. temp_len];
fb.length += length;
@ -378,18 +376,18 @@ StartSelection(FlatBuffer* fb, SelectMode mode)
if(mode == SM.Normal)
{
fb.sel = fb.pos;
fb.selection = fb.pos;
}
else if(mode == SM.Line)
{
fb.sel = CurrentLine(fb);
fb.selection = CurrentLine(fb);
}
}
void
EndSelection(FlatBuffer* fb)
{
fb.sel = -1;
fb.selection = -1;
fb.sel_mode = SM.None;
}
@ -454,13 +452,6 @@ LineLength(FlatBuffer* fb, u64 line)
return fb.lines[line].length;
}
void
StartLineBuffer(FlatBuffer* fb, f32 view_width)
{
Reset(&fb.linebufs.arena);
fb.view_width = view_width;
}
LineBuffer*
GetLine(FlatBuffer* fb, u64 line)
{
@ -479,9 +470,8 @@ SliceLineBuffer(FlatBuffer* fb, Line* ls)
{
LineBuffer* lbuf = Alloc!(LineBuffer)(&fb.linebufs.arena);
lbuf.text = fb.pbuf[ls.pos .. ls.pos+ls.length];
lbuf.style = fb.tk.ptokens[ls.pos .. ls.pos+ls.length];
fb.linebufs.count += 1;
lbuf.text = fb.data[ls.pos .. ls.pos+ls.length];
lbuf.style = fb.tk.tokens[ls.pos .. ls.pos+ls.length];
return lbuf;
}
@ -489,7 +479,7 @@ SliceLineBuffer(FlatBuffer* fb, Line* ls)
void
MoveToEOL(FlatBuffer* fb)
{
if(fb.pbuf[fb.pos] != '\n')
if(fb.data[fb.pos] != '\n')
{
for(u64 i = 0; i < fb.lines.length; i += 1)
{
@ -505,7 +495,7 @@ MoveToEOL(FlatBuffer* fb)
void
MoveToSOL(FlatBuffer* fb)
{
if(fb.pos != 0 && fb.pbuf[fb.pos-1] != '\n')
if(fb.pos != 0 && fb.data[fb.pos-1] != '\n')
{
for(u64 i = 0; i < fb.lines.length; i += 1)
{
@ -577,7 +567,7 @@ MoveToEmptyLine(bool up)(FlatBuffer* fb)
break;
}
ch = fb.pbuf[i];
ch = fb.data[i];
}
static if(up)
@ -588,10 +578,10 @@ MoveToEmptyLine(bool up)(FlatBuffer* fb)
break;
}
ch = fb.pbuf[i-1];
ch = fb.data[i-1];
}
if(started && !CheckWhiteSpace(fb.pbuf[i]))
if(started && !CheckWhiteSpace(fb.data[i]))
{
started = false;
}
@ -674,8 +664,8 @@ MoveToWordEdge(bool forward)(FlatBuffer* fb)
if((forward && fb.pos < fb.length-1) || (!forward && fb.pos > 0))
{
ChType type = GetChType(fb.pbuf[fb.pos]);
if(type != GetChType(fb.pbuf[fb.pos+step]))
ChType type = GetChType(fb.data[fb.pos]);
if(type != GetChType(fb.data[fb.pos+step]))
{
fb.pos += step;
}
@ -683,11 +673,11 @@ MoveToWordEdge(bool forward)(FlatBuffer* fb)
{
static if(forward)
{
u8 next = i < fb.length-1 ? fb.pbuf[i+1] : 0;
u8 next = i < fb.length-1 ? fb.data[i+1] : 0;
}
else
{
u8 next = i > 1 ? fb.pbuf[i-1] : 0;
u8 next = i > 1 ? fb.data[i-1] : 0;
}
static if(forward) if(i == fb.length-2)
@ -712,7 +702,7 @@ MoveToWordEdge(bool forward)(FlatBuffer* fb)
}
}
while(CheckWhiteSpace(fb.pbuf[fb.pos]))
while(CheckWhiteSpace(fb.data[fb.pos]))
{
bool exit = forward ? fb.pos == fb.length-1 : fb.pos == 0;
if(exit) break;
@ -725,7 +715,7 @@ MoveToWordEdge(bool forward)(FlatBuffer* fb)
void
MoveToNextWord(bool forward)(FlatBuffer* fb)
{
ChType type = GetChType(fb.pbuf[fb.pos]);
ChType type = GetChType(fb.data[fb.pos]);
bool hit_ws;
u64 step = forward ? 1 : -1;
@ -743,7 +733,7 @@ MoveToNextWord(bool forward)(FlatBuffer* fb)
break;
}
u8 ch = fb.pbuf[i];
u8 ch = fb.data[i];
if(CheckWhiteSpace(ch))
{
@ -847,7 +837,7 @@ Move(FlatBuffer* fb, Input key, Modifier md)
} break;
case Left:
{
if(fb.pos > 0 && fb.pbuf[fb.pos-1] != '\n')
if(fb.pos > 0 && fb.data[fb.pos-1] != '\n')
{
fb.pos -= 1;
taken = true;
@ -855,7 +845,7 @@ Move(FlatBuffer* fb, Input key, Modifier md)
} break;
case Right:
{
if(fb.pos < fb.length && fb.pbuf[fb.pos] != '\n')
if(fb.pos < fb.length && fb.data[fb.pos] != '\n')
{
fb.pos += 1;
taken = true;
@ -874,7 +864,7 @@ Move(FlatBuffer* fb, Input key, Modifier md)
UpdateSelection(fb);
Logf("selection %s", fb.sel.v);
Logf("selection %s", fb.selection.v);
return taken;
}
@ -884,12 +874,12 @@ UpdateSelection(FlatBuffer* fb)
{
if(fb.sel_mode == SM.Normal)
{
fb.sel.y = fb.pos;
fb.selection.y = fb.pos;
}
if(fb.sel_mode == SM.Line)
{
fb.sel.y = CurrentLine(fb);
fb.selection.y = CurrentLine(fb);
}
}
@ -911,7 +901,7 @@ Delete(FlatBuffer* fb, u64 length, u64 pos)
for(u64 i = pos; i < fb.length && i < pos+length; i += 1)
{
if(fb.pbuf[i] == '\n')
if(fb.data[i] == '\n')
{
fb.line_count -= 1;
}
@ -921,8 +911,8 @@ Delete(FlatBuffer* fb, u64 length, u64 pos)
if(end != fb.length)
{
temp = Alloc!(u8)(&fb.arena, fb.length-end);
temp[0 .. temp.length] = fb.pbuf[end .. fb.length];
fb.pbuf[pos .. pos+temp.length] = temp[0 .. temp.length];
temp[0 .. temp.length] = fb.data[end .. fb.length];
fb.data[pos .. pos+temp.length] = temp[0 .. temp.length];
}
fb.length -= length;

View File

@ -28,6 +28,7 @@ struct EditorCtx
EditState state;
u8[128] input_buf;
u32 icount;
u64 editor_id_incr;
Timer timer;
CmdPalette cmd;
u8[][] file_names;
@ -49,14 +50,17 @@ struct CmdPalette
struct Editor
{
Arena arena;
u64 editor_id;
FlatBuffer buf;
Tokenizer tk;
Vec2 cursor_pos;
U64Vec2 cursor_pos;
Vec2 select_start;
Vec2 select_end;
u64 line_offset;
f32 text_size;
}
@ -414,7 +418,7 @@ SaveFile(Editor* ed, u8[] file_name)
u64 tab_count;
for(u64 i = 0; i < ed.buf.length; i += 1)
{
if(ed.buf.pbuf[i] == '\t')
if(ed.buf.data[i] == '\t')
{
tab_count += 1;
}
@ -427,7 +431,7 @@ SaveFile(Editor* ed, u8[] file_name)
u64 buf_pos;
for(u64 i = 0; i < ed.buf.length; i += 1)
{
if(ed.buf.pbuf[i] == '\t')
if(ed.buf.data[i] == '\t')
{
for(u64 j = 0; j < tab_width; j += 1)
{
@ -436,7 +440,7 @@ SaveFile(Editor* ed, u8[] file_name)
}
else
{
temp_buf[buf_pos++] = ed.buf.pbuf[i];
temp_buf[buf_pos++] = ed.buf.data[i];
}
}
@ -490,6 +494,7 @@ CreateEditor(EditorCtx* ctx)
ed.arena = CreateArena(MB(4));
ed.buf = CreateFlatBuffer([], []);
ed.editor_id = ctx.editor_id_incr++;
return ed;
}

View File

@ -389,8 +389,7 @@ struct Token
struct Tokenizer
{
Arena arena;
TokenStyle[] _tokens;
TokenStyle* ptokens;
TokenStyle[] tokens;
u64 tk_count;
u64 pos;
Token* first;
@ -406,8 +405,7 @@ Nil(Token* tk)
void
SetBuffers(Tokenizer* tk, TokenStyle[] tokens)
{
tk._tokens = tokens;
tk.ptokens = tokens.ptr+BUF_START;
tk.tokens = tokens;
}
Tokenizer
@ -417,7 +415,7 @@ CreateTokenizer(FlatBuffer* fb)
arena: CreateArena(MB(4)),
};
SetBuffers(&tk, Alloc!(TS)(fb._buf.length));
SetBuffers(&tk, Alloc!(TS)(fb.data.length));
g_NIL_TOKEN = cast(Token*)&g_nil_tk;
tk.first = tk.last = g_NIL_TOKEN;
@ -445,7 +443,7 @@ void
ResetTokenizer(Tokenizer* tk, u64 len)
{
Reset(&tk.arena);
Free(tk._tokens);
Free(tk.tokens);
SetBuffers(tk, Alloc!(TS)(len));
tk.pos = 0;
@ -469,7 +467,7 @@ MakeToken(Tokenizer* tk, TokenType type, u64 start, u64 end)
u8
Peek(FlatBuffer* fb)
{
return fb.tk.pos+1 < fb.length ? fb.pbuf[fb.tk.pos+1] : 0;
return fb.tk.pos+1 < fb.length ? fb.data[fb.tk.pos+1] : 0;
}
void
@ -483,7 +481,7 @@ TokenizeD(FlatBuffer* fb)
for(; tk.pos < fb.length;)
{
u8 ch = fb.pbuf[tk.pos];
u8 ch = fb.data[tk.pos];
bool alpha = (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
if(ch == ' ' || ch == '\t')
@ -492,7 +490,7 @@ TokenizeD(FlatBuffer* fb)
for(tk.pos += 1; tk.pos < fb.length; tk.pos += 1)
{
if(fb.pbuf[tk.pos] != ' ' && fb.pbuf[tk.pos] != '\t')
if(fb.data[tk.pos] != ' ' && fb.data[tk.pos] != '\t')
{
break;
}
@ -577,7 +575,7 @@ TokenizeD(FlatBuffer* fb)
for(; tk.pos < fb.length; tk.pos += 1)
{
u8 c = fb.pbuf[tk.pos];
u8 c = fb.data[tk.pos];
if(CheckWhiteSpace(c)) break;
if(!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z')) break;
@ -591,7 +589,7 @@ TokenizeD(FlatBuffer* fb)
for(; tk.pos < fb.length; tk.pos += 1)
{
if(fb.pbuf[tk.pos] != '.') break;
if(fb.data[tk.pos] != '.') break;
}
t.end = tk.pos;
@ -602,7 +600,7 @@ TokenizeD(FlatBuffer* fb)
for(; tk.pos < fb.length; tk.pos += 1)
{
if(CheckWhiteSpace(fb.pbuf[tk.pos])) break;
if(CheckWhiteSpace(fb.data[tk.pos])) break;
}
t.end = tk.pos;
@ -619,7 +617,7 @@ TokenizeD(FlatBuffer* fb)
for(; tk.pos < fb.length; tk.pos += 1)
{
if(CheckEOL(fb.pbuf[tk.pos]))
if(CheckEOL(fb.data[tk.pos]))
{
break;
}
@ -634,7 +632,7 @@ TokenizeD(FlatBuffer* fb)
for(; tk.pos < fb.length; tk.pos += 1)
{
if(fb.pbuf[tk.pos] == '/' && fb.pbuf[tk.pos-1] == '*')
if(fb.data[tk.pos] == '/' && fb.data[tk.pos-1] == '*')
{
break;
}
@ -655,7 +653,7 @@ TokenizeD(FlatBuffer* fb)
for(; tk.pos < fb.length; tk.pos += 1)
{
if(CheckWhiteSpace(fb.pbuf[tk.pos]))
if(CheckWhiteSpace(fb.data[tk.pos]))
{
break;
}
@ -716,7 +714,7 @@ TokenizeD(FlatBuffer* fb)
for(auto token = tk.first; !Nil(token); token = token.next)
{
tk.ptokens[token.start .. token.end] = TOKEN_STYLES[token.type];
tk.tokens[token.start .. token.end] = TOKEN_STYLES[token.type];
}
}
@ -826,7 +824,7 @@ CheckFuncOrTemplateSig(FlatBuffer* fb, Token* token)
u8[]
TokenStr(FlatBuffer* fb, Token* t)
{
return fb.pbuf[t.start .. t.end];
return fb.data[t.start .. t.end];
}
Token*
@ -911,7 +909,7 @@ ParseNum(FlatBuffer* fb)
{
tk.pos += 1;
u8 ch = fb.pbuf[tk.pos];
u8 ch = fb.data[tk.pos];
if(ch != '_' && ch != '.' && !(ch >= '0' && ch <= '9') && ch != 'x' && ch != 'X' && !((ch == '-' || ch == '+') && first))
{
@ -923,7 +921,7 @@ ParseNum(FlatBuffer* fb)
while (tk.pos < fb.length)
{
u8 ch = fb.pbuf[tk.pos];
u8 ch = fb.data[tk.pos];
if(ch != 'l' && ch != 'u' && ch != 'U' && ch != 'L' && ch != 'f' && ch != 'F')
{
break;
@ -952,9 +950,9 @@ ParseStr(u8 str_ch)(FlatBuffer* fb)
static if(str_ch == '`') tk.pos += 1;
bool ignore = str_ch != '`';
for(; (fb.pbuf[tk.pos] != str_ch || ignore) && tk.pos < fb.length; tk.pos += 1)
for(; (fb.data[tk.pos] != str_ch || ignore) && tk.pos < fb.length; tk.pos += 1)
{
static if(str_ch != '`') ignore = fb.pbuf[tk.pos] == '\\';
static if(str_ch != '`') ignore = fb.data[tk.pos] == '\\';
}
tk.pos += 1;
@ -971,7 +969,7 @@ ParseId(FlatBuffer* fb)
for(; tk.pos < fb.length; tk.pos += 1)
{
u8 ch = fb.pbuf[tk.pos];
u8 ch = fb.data[tk.pos];
if(!(ch >= 'a' && ch <= 'z') && !(ch >= 'A' && ch <= 'Z') && ch != '.' && ch != '_' && !(ch >= '0' && ch <= '9'))
{
@ -980,11 +978,11 @@ ParseId(FlatBuffer* fb)
}
}
u8 ch = fb.pbuf[t.start];
u8 ch = fb.data[t.start];
if(ch < D_KEYWORDS.length && D_KEYWORDS[ch] != null && D_KEYWORDS[ch].length > 0)
{
bool found = false;
u8[] id = fb.pbuf[t.start .. t.end];
u8[] id = fb.data[t.start .. t.end];
foreach(ref k; D_TYPES[ch])
{
@ -1032,7 +1030,7 @@ FixOpAssign(FlatBuffer* fb, Token* t)
{
if(t.end+1 < fb.length)
{
u8[] str = fb.pbuf[t.start .. t.end+1];
u8[] str = fb.data[t.start .. t.end+1];
if(
str == "/=" ||
str == "+=" ||
@ -1075,7 +1073,7 @@ SkipWhiteSpace(FlatBuffer* fb)
{
while (fb.tk.pos < fb.length)
{
u8 ch = fb.pbuf[fb.tk.pos];
u8 ch = fb.data[fb.tk.pos];
bool white_space = CheckWhiteSpace(ch);

View File

@ -90,7 +90,7 @@ enum Axis2D
{
X,
Y,
Max
Max,
}
alias A2D = Axis2D;
@ -111,10 +111,11 @@ enum UIFlags
ResizeAdjacent = 1<<10,
FloatingWindow = 1<<11,
CenteredWindow = 1<<12,
TextInput = 1<<13,
TextInput = 1<<13, // todo
RightAlignText = 1<<14,
CenterAlignText = 1<<15,
CenterAlignText = 1<<15, // todo
TextWrap = 1<<16,
PortalView = 1<<17, // Stencil mask this area, no bounds checking children within (for views to drag and view elements)
Clamp = UIFlags.ClampX | UIFlags.ClampY,
}
@ -241,6 +242,7 @@ struct UICtx
mixin UICtxParameter!(Vec4, "text_hl_col");
mixin UICtxParameter!(Vec2[2], "scroll_clamp");
mixin UICtxParameter!(Vec2, "scroll_target");
mixin UICtxParameter!(Vec2, "fixed_pos");
mixin UICtxParameter!(Vec2, "padding");
mixin UICtxParameter!(UIItem*, "parent");
mixin UICtxParameter!(Axis2D, "layout_axis");
@ -357,6 +359,7 @@ struct VPos
struct Vertex
{
Vec4[4] cols;
Vec2[2] bounds;
union
{
VPos[2] pos;
@ -372,7 +375,6 @@ struct Vertex
f32 corner_radius;
f32 edge_softness;
f32 raised;
f32 z_index;
u32 texture;
}
@ -557,8 +559,6 @@ Set(UIItem* item, UICtx* ctx)
UIItem*
MakeItem(Args...)(string str, Args args)
{
UIItem* item = g_UI_NIL;
static if(Args.length)
{
enum has_flag = Args[Args.length-1].stringof == UIFlags.stringof;
@ -567,11 +567,14 @@ MakeItem(Args...)(string str, Args args)
enum len = has_flag ? Args.length-1 : Args.length;
char[] key = sformat(ScratchAlloc!(char)(cast(u64)(str.length*1.5)), str, args[0 .. len]);
item = MakeItem(key, flags);
}
else
{
char[] key = CastStr(char)(str);
UIFlags flags = UIF.None;
}
return item;
return MakeItem(key, flags);
}
UIItem*
@ -802,7 +805,7 @@ BeginUI(Inputs* inputs)
foreach(i; 0 .. items.length)
{
UIItem* item = items[i].value;
if(item.last_frame != ctx.frame)
if(item.last_frame != ctx.frame || ZeroKey(item.key))
{
Logf("discarding %s", cast(char[])item.key.hash_text);
item.first = item.last = item.parent = item.prev = item.next = g_UI_NIL;
@ -986,30 +989,6 @@ EndUI()
break;
}
}
if(excess > 0.0009)
{
for(UIItem* c = item.last; !Nil(c); c = c.prev)
{
f32 reduced = Min(excess, c.size[axis]);
excess -= reduced;
c.size.v[axis] -= reduced;
if(excess < 0.0009)
{
break;
}
}
assert(excess < 0.0009);
}
}
}
else
{
for(UIItem* c = item.first; !Nil(c); c = c.next)
{
c.size.v[axis] = c.size.v[axis] > size ? size : c.size.v[axis];
}
}
}
@ -1108,6 +1087,7 @@ RenderItems(UIItem* root)
v.dst_end = item.rect.p1 - item.border_thickness;
v.cols = item.bg_col;
v.corner_radius = item.corner_radius;
v.bounds = ItemBounds(item.parent);
AddVertexCount(ctx);
}
@ -1121,6 +1101,7 @@ RenderItems(UIItem* root)
v.corner_radius = item.corner_radius;
v.border_thickness = item.border_thickness;
v.edge_softness = item.edge_softness;
v.bounds = ItemBounds(item.parent);
AddVertexCount(ctx);
}
@ -1389,6 +1370,13 @@ RootSize()
return cast(Vec2)GetExtent(&g_ui_ctx.rd);
}
UIKey
MakeKey(Args...)(string str, Args args)
{
char[] key = sformat(ScratchAlloc!(char)(cast(u64)(str.length)), str, args);
return MakeKey(key);
}
UIKey
MakeKey(T)(T str) if(StringType!T)
{
@ -1403,6 +1391,8 @@ MakeKey(T)(T str) if(StringType!T)
UIKey key;
if(str.length)
{
bool hash_only = false;
i64 pos = 0;
u32 hash_count = 0;
@ -1443,10 +1433,30 @@ MakeKey(T)(T str) if(StringType!T)
key.hash_text = id[pos .. $];
key.hash = hash_count == 2 ? Hash(id) : Hash(id[pos+hash_count .. $]);
}
}
return key;
}
UIKey
ZeroKey()
{
return UIKey();
}
bool
ZeroKey(UIKey key)
{
return key.hash == 0 && key.hash_text.length == 0;
}
UIItem*
Get(Args...)(string str, Args args)
{
char[] key = sformat(ScratchAlloc!(cast(u64)(str.length*1.5), str, args));
return Get(key);
}
pragma(inline) UIItem*
Get(T)(T k) if(is(T: UIKey) || StringType!T)
{
@ -1550,6 +1560,7 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y)
v.dst_end = Vec2(*x_pos+gb.w+gb.l, y+gb.h);
v.cols = item.text_col;
v.texture = true;
v.bounds = ItemBounds(item);
if(glyph.ch != '\t' && glyph.ch != '\n')
{
@ -1557,6 +1568,7 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y)
v.src_end = Vec2(gb.atlas_r, gb.atlas_b);
}
/*
f32 end_x = *x_pos + advance;
f32 width = end_x - *x_pos;
f32 bound_x = item.flags & UIF.RightAlignText ? item.rect.p0.x : item.rect.p1.x;
@ -1589,6 +1601,7 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y)
v.pos[i].end[axis] = v.pos[i].start.v[axis] > v.pos[i].end.v[axis] ? v.pos[i].start.v[axis] : v.pos[i].end.v[axis];
}
}
*/
AddVertexCount(ctx);
@ -1596,6 +1609,12 @@ DrawGlyph(UIItem* item, Glyph* glyph, f32* x_pos, f32 y)
}
}
pragma(inline) Vec2[2]
ItemBounds(UIItem* item)
{
return [item.rect.p0, item.rect.p1];
}
pragma(inline) f32
InnerSize(Axis2D axis)(UIItem* item)
{
@ -1794,6 +1813,13 @@ Dragged(UIItem* item, Rect* rect)
return result;
}
pragma(inline) Vec4[4]
Vec4Arr(Vec4 col)
{
Vec4[4] arr = col;
return arr;
}
unittest
{
{ // UI Key

View File

@ -4,6 +4,7 @@ import editor;
import parsing;
import buffer;
import std.algorithm.comparison : clamp;
import std.format;
import std.conv;
@ -13,6 +14,74 @@ Nil(UIPanel* panel)
return panel == null || panel == g_UI_NIL_PANEL;
}
void
EditorView(Editor* ed)
{
UICtx* ctx = GetCtx();
UIKey zero = ZeroKey();
UIKey ed_key = MakeKey("###ed_%s", ed.editor_id);
UIItem* editor = Get(ed_key);
u64 frame_line_offset = ed.line_offset;
u64 frame_view_offset = editor.scroll_offset%TEXT_SIZE;
Push!("border_col" )(ctx, Vec4Arr(Vec4(1.0)));
// Line Counter
f32 lc_width = ed.buf.line_count.toChars().length*ctx.char_width;
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!("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;
if(editor.size.y > 0.0)
{
view_lines = cast(u64)ceil(editor.size.y/TEXT_SIZE);
const u64 SCROLL_BUFFER = 2;
u64 start = ed.line_offset;
u64 end = start+view_lines;
if(ed.cursor_pos.y < start)
{
ed.line_offset = clamp(ed.cursor_pos.y - SCROLL_BUFFER, 0, ed.buf.line_count);
}
else if(ed.cursor_pos.y > end)
{
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));
Push!("parent" )(ctx, line_count);
Push!("text_col" )(ctx, Vec4(1.0));
u64 i = prev_offset;
for(LineBuffer* lb = GetLine(&ed.buf, i); i < prev_offset+view_lines; i += 1)
{
}
Pop!("parent")(ctx);
}
/*
void
Panel(UIPanel* panel)

View File

@ -14,6 +14,8 @@ layout (location = 1) in struct FragDataIn {
vec2 dst_center;
vec2 dst_half_size;
vec2 sdf_sample_pos;
vec2 bounds_p0;
vec2 bounds_p1;
float corner_radius;
float softness;
float raised;

View File

@ -8,15 +8,15 @@ layout (location = 0) in vec4 in_col_1;
layout (location = 1) in vec4 in_col_2;
layout (location = 2) in vec4 in_col_3;
layout (location = 3) in vec4 in_col_4;
layout (location = 4) in vec2 in_dst_start;
layout (location = 5) in vec2 in_dst_end;
layout (location = 6) in vec2 in_src_start;
layout (location = 7) in vec2 in_src_end;
layout (location = 8) in float border_thickness;
layout (location = 9) in float corner_radius;
layout (location = 10) in float edge_softness;
layout (location = 11) in float raised;
layout (location = 12) in float z_index;
layout (location = 4) in vec4 in_bounds;
layout (location = 5) in vec2 in_dst_start;
layout (location = 6) in vec2 in_dst_end;
layout (location = 7) in vec2 in_src_start;
layout (location = 8) in vec2 in_src_end;
layout (location = 9) in float border_thickness;
layout (location = 10) in float corner_radius;
layout (location = 11) in float edge_softness;
layout (location = 12) in float raised;
layout (location = 13) in uint in_has_texture;
layout (location = 0) flat out uint out_has_texture;