begin rebuilding UI framework
This commit is contained in:
parent
d69b5b5993
commit
2a3be6ad58
@ -1 +1 @@
|
||||
Subproject commit b05d0553837233818f1cbdb1dc3a3981eac1a0a3
|
||||
Subproject commit 589b2191babf009bef097d1272fac4a05a4c280d
|
||||
@ -948,8 +948,9 @@ unittest
|
||||
|
||||
// FlatBuffer Insert/Delete/Replace
|
||||
{
|
||||
/*
|
||||
u8[] data = StringToU8("This is a test string for testing the FlatBuffer struct.");
|
||||
FlatBuffer buf = CreateFlatBuffer(data);
|
||||
FlatBuffer buf = CreateFlatBuffer(data, "file");
|
||||
|
||||
u8[] insert = StringToU8("This is a string inserted into the beginning of the buffer. ");
|
||||
Insert(&buf, insert, insert.length, 0);
|
||||
@ -977,5 +978,6 @@ unittest
|
||||
{
|
||||
assert(buf.data[i] == ch, "FlatBuffer Replace failure: buffers do not match");
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import buffer;
|
||||
import ui : Nil;
|
||||
import ui;
|
||||
import parsing;
|
||||
import views;
|
||||
|
||||
import std.format;
|
||||
import std.stdio;
|
||||
@ -657,9 +658,7 @@ HandleInputs(EditorCtx* ctx, Inputs* inputs)
|
||||
} break;
|
||||
debug case d:
|
||||
{
|
||||
static bool dbg = false;
|
||||
dbg = !dbg;
|
||||
SetDebug(dbg);
|
||||
g_ui_ctx.dbg = !g_ui_ctx.dbg;
|
||||
} break;
|
||||
debug case g:
|
||||
{
|
||||
|
||||
1061
src/editor/ui.d
1061
src/editor/ui.d
File diff suppressed because it is too large
Load Diff
330
src/editor/views.d
Normal file
330
src/editor/views.d
Normal file
@ -0,0 +1,330 @@
|
||||
import dlib;
|
||||
import ui;
|
||||
import editor;
|
||||
import parsing;
|
||||
import buffer;
|
||||
|
||||
import std.format;
|
||||
import std.conv;
|
||||
|
||||
void
|
||||
Panel(UIPanel* panel)
|
||||
{
|
||||
UICtx* ctx = GetCtx();
|
||||
UIItem* item = Get(panel.id);
|
||||
Editor* ed = panel.ed;
|
||||
bool focused = GetFocusedPanel() == panel;
|
||||
|
||||
UIPanel* parent = panel.parent;
|
||||
UIPanel* prev = panel.prev;
|
||||
|
||||
Axis2D pax = parent.axis;
|
||||
|
||||
Vec2 adj = Vec2(
|
||||
parent.axis == A2D.X ? 10 : 0,
|
||||
parent.axis == A2D.Y ? 10 : 0
|
||||
);
|
||||
|
||||
Vec2 p0 = panel.rect.vec0+adj;
|
||||
Vec2 p1 = panel.rect.vec1-adj;
|
||||
|
||||
if(!Nil(prev)) with(panel)
|
||||
{
|
||||
Vec2 d0 = rect.vec0-adj;
|
||||
Vec2 d1 = Vec2(
|
||||
pax == A2D.X ? rect.vec0.x+adj.x : rect.vec1.x,
|
||||
pax == A2D.Y ? rect.vec0.y+adj.y : rect.vec1.y
|
||||
);
|
||||
|
||||
if(Dragged(item, d0, d1) && item.dragged.v[pax] != 0.0)
|
||||
{
|
||||
f32 mov_pct = Remap(item.dragged.v[pax], 0.0, panel.parent.size.v[pax], 0.0, 1.0);
|
||||
if(CheckPanelBounds(pct + mov_pct) && CheckPanelBounds(panel.prev.pct - mov_pct))
|
||||
{
|
||||
pct += mov_pct;
|
||||
panel.prev.pct -= mov_pct;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(panel.ed != null)
|
||||
{
|
||||
if(Clicked(item, p0, p1))
|
||||
{
|
||||
SetFocusedPanel(panel);
|
||||
}
|
||||
|
||||
Vec2 inner = InnerSize(panel);
|
||||
|
||||
SetScrollOffset(panel);
|
||||
|
||||
panel.start_ln = cast(u64)(floor(panel.scroll_offset/TEXT_SIZE));
|
||||
panel.end_ln = panel.start_ln + cast(u64)(ceil(inner.y/TEXT_SIZE));
|
||||
panel.vis_lines = panel.end_ln - panel.start_ln;
|
||||
|
||||
char[64] ch_buf = '\0';
|
||||
char[] fmt = ch_buf.sformat("%%0%ss", u64(panel.end_ln.toChars().length));
|
||||
|
||||
f32 lc_w = panel.end_ln.toChars().length*ctx.char_width + LINE_COUNT_PADDING*2.0;
|
||||
f32 code_view_width = inner.x-lc_w;
|
||||
|
||||
StartLineBuffer(&panel.ed.buf, code_view_width);
|
||||
|
||||
U64Vec2 pos = VecPos(&ed.buf);
|
||||
|
||||
DrawPanel(panel, lc_w, focused);
|
||||
|
||||
f32 y_rem = fmod(panel.scroll_offset, TEXT_SIZE);
|
||||
|
||||
f32 x = panel.rect.x0;
|
||||
f32 y = panel.rect.y0 + TEXT_SIZE - fmod(panel.scroll_offset, TEXT_SIZE);
|
||||
|
||||
u64 i = panel.start_ln;
|
||||
for(auto buf = GetLine(&ed.buf, i); !CheckNil(g_NIL_LINE_BUF, buf) && i < panel.end_ln; i += 1, buf = GetLine(&ed.buf, i))
|
||||
{
|
||||
f32 x_pos = x + LINE_COUNT_PADDING;
|
||||
DrawLineCount(fmt, &x_pos, y, i);
|
||||
|
||||
u64 ch_offset;
|
||||
|
||||
auto parts = MakeMultiline(buf.text, code_view_width, buf.style);
|
||||
if(parts == null)
|
||||
{
|
||||
if(pos.y == i)
|
||||
{
|
||||
DrawCursor([], 0, x+lc_w, y, ch_offset);
|
||||
}
|
||||
}
|
||||
else for(auto n = parts; n != null; n = n.next)
|
||||
{
|
||||
auto l = &n.value;
|
||||
|
||||
if(pos.y == i)
|
||||
{
|
||||
DrawCursor(l.text, pos.x, x+lc_w, y, ch_offset);
|
||||
}
|
||||
|
||||
foreach(j; 0 .. l.text.length)
|
||||
{
|
||||
bool hl = pos.y == i && !EditModeActive() && j == pos.x-ch_offset;
|
||||
DrawChar(l.text[j], &x_pos, y, hl ? Vec4(Vec3(0.0), 1.0) : SYNTAX_COLORS[l.style[j]]);
|
||||
}
|
||||
|
||||
y += TEXT_SIZE;
|
||||
x_pos = x + lc_w + LINE_COUNT_PADDING*2.0;
|
||||
ch_offset += l.text.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CommandPalette(CmdPalette* cmd)
|
||||
{
|
||||
UICtx* ctx = GetCtx();
|
||||
|
||||
u8[] text = cmd.buffer[0 .. cmd.icount];
|
||||
u8[][] options = cmd.opt_strs;
|
||||
|
||||
Vec2 size = RootSize();
|
||||
|
||||
f32 x = size.x*0.15;
|
||||
f32 y = size.y*0.1;
|
||||
f32 w = size.x*0.7;
|
||||
f32 h = 40.0;
|
||||
|
||||
DrawCmdRect(Vec2(x, y), Vec2(w, h), false);
|
||||
|
||||
f32 y_off = h*0.5 + 6;
|
||||
f32 ch_x = x + 6.0;
|
||||
f32 ch_y = y + y_off;
|
||||
|
||||
foreach(i; 0 .. text.length)
|
||||
{
|
||||
DrawChar(text[i], &ch_x, ch_y, Vec4(1.0));
|
||||
}
|
||||
|
||||
for(u64 i = 0; i < options.length; i += 1)
|
||||
{
|
||||
y += h;
|
||||
ch_x = x + 6.0;
|
||||
ch_y = y + y_off;
|
||||
|
||||
DrawCmdRect(Vec2(x, y), Vec2(w, h), cmd.selected == i);
|
||||
|
||||
foreach(j; 0 .. options[i].length)
|
||||
{
|
||||
DrawChar(options[i][j], &ch_x, ch_y, Vec4(1.0));
|
||||
}
|
||||
|
||||
if(y+h > size.y+h) break;
|
||||
}
|
||||
}
|
||||
|
||||
UIPanel*
|
||||
Recurse(UIPanel* panel)
|
||||
{
|
||||
UIPanel* result = g_UI_NIL_PANEL;
|
||||
if(!Nil(panel.first))
|
||||
{
|
||||
result = panel.first;
|
||||
}
|
||||
else if(!Nil(panel.next))
|
||||
{
|
||||
result = panel.next;
|
||||
}
|
||||
else for(UIPanel* p = panel.parent; !Nil(p); p = p.parent)
|
||||
{
|
||||
if(!Nil(p.next))
|
||||
{
|
||||
result = p.next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
CheckPanelBounds(f32 pct)
|
||||
{
|
||||
return pct >= 0.0 && pct <= 1.0;
|
||||
}
|
||||
|
||||
void
|
||||
PushPanel(UIPanel* parent, UIPanel* panel)
|
||||
{
|
||||
DLLPush(parent, panel, g_UI_NIL_PANEL);
|
||||
panel.parent = parent;
|
||||
}
|
||||
|
||||
void
|
||||
InsertPanel(UIPanel* parent, UIPanel* prev, UIPanel* panel)
|
||||
{
|
||||
DLLInsert(parent, panel, prev, g_UI_NIL_PANEL);
|
||||
panel.parent = prev.parent;
|
||||
}
|
||||
|
||||
void
|
||||
SetFocusedPanel(UIPanel* panel)
|
||||
{
|
||||
if(!CheckNil(g_UI_NIL_PANEL, panel))
|
||||
{
|
||||
g_ui_ctx.focused_panel = panel;
|
||||
}
|
||||
}
|
||||
|
||||
UIPanel*
|
||||
GetFocusedPanel()
|
||||
{
|
||||
return Nil(g_ui_ctx.focused_panel) ? g_UI_NIL_PANEL : g_ui_ctx.focused_panel;
|
||||
}
|
||||
|
||||
bool
|
||||
Nil(UIPanel* panel)
|
||||
{
|
||||
return panel == null || panel == g_UI_NIL_PANEL;
|
||||
}
|
||||
|
||||
Node!(TextBuffer)*
|
||||
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);
|
||||
|
||||
u64 line_count = cast(u64)(ceil(text_width/scaled_width));
|
||||
Node!(TextBuffer)* node = null;
|
||||
if(line_count > 0)
|
||||
{
|
||||
f32 w = 0.0;
|
||||
u64 line = 0;
|
||||
u64 start = 0;
|
||||
const u64 extra_buf = 20;
|
||||
for(u64 i = 0; i < text.length; i += 1)
|
||||
{
|
||||
f32 ch_w = GlyphWidth(g_ui_ctx.atlas_buf.atlas.glyphs.ptr + text[i]);
|
||||
|
||||
if(ch_w + w > scaled_width || i == text.length-1)
|
||||
{
|
||||
u64 len = i-start+1;
|
||||
|
||||
u8[] str = ScratchAlloc!(u8)(text, start, len);
|
||||
|
||||
TS[] stl = [];
|
||||
if(style.length > 0)
|
||||
{
|
||||
stl = ScratchAlloc!(TS)(style, start, len);
|
||||
}
|
||||
|
||||
Node!(TextBuffer)* n = node;
|
||||
for(;;)
|
||||
{
|
||||
if(node == null)
|
||||
{
|
||||
node = ScratchAlloc!(Node!(TextBuffer))();
|
||||
|
||||
node.value.text = str;
|
||||
node.value.style = stl;
|
||||
node.next = null;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(n.next == null)
|
||||
{
|
||||
n.next = ScratchAlloc!(Node!(TextBuffer))();
|
||||
|
||||
n.next.value.text = str;
|
||||
n.next.value.style = stl;
|
||||
n.next.next = null;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
n = n.next;
|
||||
}
|
||||
|
||||
line += 1;
|
||||
start = i;
|
||||
w = 0.0;
|
||||
}
|
||||
|
||||
w += ch_w;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
pragma(inline) void
|
||||
DrawCursor(u8[] text, u64 ch_x, f32 x, f32 y, u64 offset)
|
||||
{
|
||||
Glyph* g = GetGlyph(' ');
|
||||
foreach(j; 0 .. text.length)
|
||||
{
|
||||
bool hl = j == ch_x-offset;
|
||||
if(hl)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
g = j == text.length-1 ? GetGlyph(' ') : GetGlyph(text[j]);
|
||||
x += GlyphWidth(g);
|
||||
}
|
||||
|
||||
DrawRect(x, y, cast(u8)g.ch, Vec4(1.0), EditModeActive());
|
||||
}
|
||||
|
||||
pragma(inline) void
|
||||
DrawLineCount(char[] fmt, f32* x_pos, f32 y, u64 line)
|
||||
{
|
||||
char[32] line_buf = '\0';
|
||||
char[] line_str = sformat(line_buf, fmt, line+1);
|
||||
|
||||
foreach(j; 0 .. line_str.length)
|
||||
{
|
||||
DrawChar(line_str[j], x_pos, y, Vec4(1.0));
|
||||
}
|
||||
|
||||
*x_pos += LINE_COUNT_PADDING;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user