things coming together
This commit is contained in:
parent
08fe3c4b81
commit
8e74e90109
@ -777,16 +777,19 @@ Move(FlatBuffer* fb, Input key, Modifier md)
|
|||||||
case Up:
|
case Up:
|
||||||
{
|
{
|
||||||
MoveToEmptyLine!(true)(fb);
|
MoveToEmptyLine!(true)(fb);
|
||||||
|
taken = true;
|
||||||
} break;
|
} break;
|
||||||
case Down:
|
case Down:
|
||||||
{
|
{
|
||||||
MoveToEmptyLine!(false)(fb);
|
MoveToEmptyLine!(false)(fb);
|
||||||
|
taken = true;
|
||||||
} break;
|
} break;
|
||||||
case Left:
|
case Left:
|
||||||
{
|
{
|
||||||
if(fb.pos > 0)
|
if(fb.pos > 0)
|
||||||
{
|
{
|
||||||
MoveToWordEdge!(false)(fb);
|
MoveToWordEdge!(false)(fb);
|
||||||
|
taken = true;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Right:
|
case Right:
|
||||||
@ -794,6 +797,7 @@ Move(FlatBuffer* fb, Input key, Modifier md)
|
|||||||
if(fb.pos < fb.length)
|
if(fb.pos < fb.length)
|
||||||
{
|
{
|
||||||
MoveToWordEdge!(true)(fb);
|
MoveToWordEdge!(true)(fb);
|
||||||
|
taken = true;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Home: fb.pos = 0; taken = true; break;
|
case Home: fb.pos = 0; taken = true; break;
|
||||||
@ -816,6 +820,7 @@ Move(FlatBuffer* fb, Input key, Modifier md)
|
|||||||
if(fb.pos > 0)
|
if(fb.pos > 0)
|
||||||
{
|
{
|
||||||
MoveToNextWord!(false)(fb);
|
MoveToNextWord!(false)(fb);
|
||||||
|
taken = true;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Right:
|
case Right:
|
||||||
@ -823,6 +828,7 @@ Move(FlatBuffer* fb, Input key, Modifier md)
|
|||||||
if(fb.pos < fb.length)
|
if(fb.pos < fb.length)
|
||||||
{
|
{
|
||||||
MoveToNextWord!(true)(fb);
|
MoveToNextWord!(true)(fb);
|
||||||
|
taken = true;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
@ -871,8 +877,6 @@ Move(FlatBuffer* fb, Input key, Modifier md)
|
|||||||
|
|
||||||
UpdateSelection(fb);
|
UpdateSelection(fb);
|
||||||
|
|
||||||
Logf("selection %s", fb.selection.v);
|
|
||||||
|
|
||||||
return taken;
|
return taken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import dlib;
|
import dlib;
|
||||||
|
import dlib.util : Str;
|
||||||
|
|
||||||
import vulkan;
|
import vulkan;
|
||||||
import std.format : sformat;
|
import std.format : sformat;
|
||||||
@ -94,16 +95,23 @@ struct Ctx
|
|||||||
alias rd_ctx this;
|
alias rd_ctx this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TextInputBuffer
|
||||||
|
{
|
||||||
|
u8[] data;
|
||||||
|
u64 length;
|
||||||
|
}
|
||||||
|
|
||||||
struct CmdPalette
|
struct CmdPalette
|
||||||
{
|
{
|
||||||
Arena arena;
|
TextInputBuffer text_input;
|
||||||
Arena cmd_arena;
|
|
||||||
u8[] buffer;
|
|
||||||
u32 icount;
|
|
||||||
i64 selected;
|
i64 selected;
|
||||||
u64 visible_opts;
|
Command[CMD_LIST.length] cmd_arr;
|
||||||
Command current;
|
Command[] cmds;
|
||||||
Parameter[] params;
|
|
||||||
|
Arena exec_cmd_arena;
|
||||||
|
TextInputBuffer exec_cmd_input;
|
||||||
|
i64 exec_cmd_selected;
|
||||||
|
string[] exec_cmd_opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Editor
|
struct Editor
|
||||||
@ -148,7 +156,6 @@ struct Command
|
|||||||
string desc;
|
string desc;
|
||||||
string cmd;
|
string cmd;
|
||||||
CmdType type;
|
CmdType type;
|
||||||
bool hidden;
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
CmdFn fn;
|
CmdFn fn;
|
||||||
@ -211,12 +218,6 @@ enum EditState
|
|||||||
SetPanelFocus, // if moving left/right move up parent tree until one is found with a2d.x, same thing for up/down a2d.y
|
SetPanelFocus, // if moving left/right move up parent tree until one is found with a2d.x, same thing for up/down a2d.y
|
||||||
} alias ES = EditState;
|
} alias ES = EditState;
|
||||||
|
|
||||||
struct Parameter
|
|
||||||
{
|
|
||||||
string value;
|
|
||||||
bool visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
__gshared bool g_input_mode = false;
|
__gshared bool g_input_mode = false;
|
||||||
__gshared Ctx g_ctx;
|
__gshared Ctx g_ctx;
|
||||||
|
|
||||||
@ -225,13 +226,13 @@ const Command NO_CMD = {
|
|||||||
type: CT.None,
|
type: CT.None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Command[5] CMD_LIST = [
|
Command[20] CMD_LIST = [
|
||||||
{
|
{
|
||||||
name: "Open",
|
name: "Open",
|
||||||
cmd: "open",
|
cmd: "open",
|
||||||
desc: "Open a file in the focused editor view.",
|
desc: "Open a file in the focused editor view.",
|
||||||
type: CT.Callback,
|
type: CT.Callback,
|
||||||
fn: &NotImplementedCallback,
|
fn: &OpenFileWindow,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Save",
|
name: "Save",
|
||||||
@ -252,17 +253,137 @@ Command[5] CMD_LIST = [
|
|||||||
cmd: "vsplit",
|
cmd: "vsplit",
|
||||||
desc: "Split the current editor view vertically.",
|
desc: "Split the current editor view vertically.",
|
||||||
type: CT.Callback,
|
type: CT.Callback,
|
||||||
fn: &NotImplementedCallback,
|
fn: &SplitVertically,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Horizontal Split",
|
name: "Horizontal Split",
|
||||||
cmd: "hsplit",
|
cmd: "hsplit",
|
||||||
desc: "Split the current editor view horizontally.",
|
desc: "Split the current editor view horizontally.",
|
||||||
type: CT.Callback,
|
type: CT.Callback,
|
||||||
|
fn: &SplitHorizontally,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 1",
|
||||||
|
cmd: "testopt1",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
|
fn: &NotImplementedCallback,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 2",
|
||||||
|
cmd: "testopt2",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
|
fn: &NotImplementedCallback,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 3",
|
||||||
|
cmd: "testopt3",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
|
fn: &NotImplementedCallback,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 4",
|
||||||
|
cmd: "testopt4",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
|
fn: &NotImplementedCallback,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 5",
|
||||||
|
cmd: "testopt5",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
|
fn: &NotImplementedCallback,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 6",
|
||||||
|
cmd: "testopt6",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
|
fn: &NotImplementedCallback,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 7",
|
||||||
|
cmd: "testopt7",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
|
fn: &NotImplementedCallback,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 8",
|
||||||
|
cmd: "testopt8",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
|
fn: &NotImplementedCallback,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 9",
|
||||||
|
cmd: "testopt9",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
|
fn: &NotImplementedCallback,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 10",
|
||||||
|
cmd: "testopt10",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
|
fn: &NotImplementedCallback,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 11",
|
||||||
|
cmd: "testopt11",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
|
fn: &NotImplementedCallback,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 12",
|
||||||
|
cmd: "testopt12",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
|
fn: &NotImplementedCallback,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 13",
|
||||||
|
cmd: "testopt13",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
|
fn: &NotImplementedCallback,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 14",
|
||||||
|
cmd: "testopt14",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
|
fn: &NotImplementedCallback,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Test Option 15",
|
||||||
|
cmd: "testopt15",
|
||||||
|
desc: "This is a test option",
|
||||||
|
type: CT.Callback,
|
||||||
fn: &NotImplementedCallback,
|
fn: &NotImplementedCallback,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
bool
|
||||||
|
SplitVertically(Ctx* ctx)
|
||||||
|
{
|
||||||
|
AddPanel(ctx.focused_panel, A2D.X);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SplitHorizontally(Ctx* ctx)
|
||||||
|
{
|
||||||
|
AddPanel(ctx.focused_panel, A2D.Y);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
NotImplementedCallback(Ctx* ctx)
|
NotImplementedCallback(Ctx* ctx)
|
||||||
{
|
{
|
||||||
@ -311,7 +432,7 @@ Cycle(Inputs* inputs)
|
|||||||
|
|
||||||
if(ctx.state == ES.RunCmd)
|
if(ctx.state == ES.RunCmd)
|
||||||
{
|
{
|
||||||
if(ctx.cmd.current.fn(ctx))
|
if(ctx.cmd.cmds[ctx.cmd.selected].fn(ctx))
|
||||||
{
|
{
|
||||||
ctx.state = ES.NormalMode;
|
ctx.state = ES.NormalMode;
|
||||||
}
|
}
|
||||||
@ -336,9 +457,9 @@ InitCtx(PlatformWindow* window)
|
|||||||
|
|
||||||
ctx.window = window;
|
ctx.window = window;
|
||||||
ctx.arena = CreateArena(MB(2));
|
ctx.arena = CreateArena(MB(2));
|
||||||
ctx.cmd.arena = CreateArena(MB(1));
|
ctx.cmd.text_input.data = Alloc!(u8)(1024);
|
||||||
ctx.cmd.cmd_arena = CreateArena(MB(1));
|
ctx.cmd.exec_cmd_input.data = Alloc!(u8)(1024);
|
||||||
ctx.cmd.buffer = Alloc!(u8)(1024);
|
ctx.cmd.exec_cmd_arena = CreateArena(MB(1));
|
||||||
ctx.timer = CreateTimer();
|
ctx.timer = CreateTimer();
|
||||||
|
|
||||||
InitUI(ctx);
|
InitUI(ctx);
|
||||||
@ -517,6 +638,12 @@ OpenFile(Editor* ed, string file_name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
Str(TextInputBuffer text_buffer)
|
||||||
|
{
|
||||||
|
return Str(text_buffer.data[0 .. text_buffer.length]);
|
||||||
|
}
|
||||||
|
|
||||||
Editor*
|
Editor*
|
||||||
CreateEditor()
|
CreateEditor()
|
||||||
{
|
{
|
||||||
@ -595,12 +722,25 @@ ResetCtx(Editor* ed)
|
|||||||
ResetCtx();
|
ResetCtx();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ResetCmd(Ctx* ctx)
|
||||||
|
{
|
||||||
|
ctx.cmd.text_input.length = 0;
|
||||||
|
ctx.cmd.selected = 0;
|
||||||
|
ctx.cmd.cmds = ctx.cmd.cmd_arr[0 .. $];
|
||||||
|
ctx.cmd.exec_cmd_input.length = 0;
|
||||||
|
ctx.cmd.exec_cmd_selected = 0;
|
||||||
|
ctx.cmd.exec_cmd_opts = [];
|
||||||
|
ctx.cmd.cmds = CMD_LIST[0 .. $];
|
||||||
|
|
||||||
|
Reset(&ctx.cmd.exec_cmd_arena);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ResetCtx()
|
ResetCtx()
|
||||||
{
|
{
|
||||||
g_ctx.state = ES.NormalMode;
|
g_ctx.state = ES.NormalMode;
|
||||||
g_ctx.cmd.icount = 0;
|
g_ctx.cmd.text_input.length = 0;
|
||||||
g_ctx.cmd.current = cast(Command)NO_CMD;
|
|
||||||
g_ctx.cmd.selected = 0;
|
g_ctx.cmd.selected = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -742,15 +882,7 @@ HandleInputs(UIPanel* p, LinkedList!(UIInput)* inputs, bool hovered, bool focuse
|
|||||||
if(Shift(node.md))
|
if(Shift(node.md))
|
||||||
{
|
{
|
||||||
ctx.state = ES.CmdPalette;
|
ctx.state = ES.CmdPalette;
|
||||||
ctx.cmd.icount = 0;
|
ResetCmd(ctx);
|
||||||
ctx.cmd.selected = 0;
|
|
||||||
ctx.cmd.params = [];
|
|
||||||
ctx.cmd.visible_opts = CMD_LIST.length;
|
|
||||||
|
|
||||||
static foreach(i; 0 .. CMD_LIST.length)
|
|
||||||
{
|
|
||||||
CMD_LIST[i].hidden = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
taken = true;
|
taken = true;
|
||||||
}
|
}
|
||||||
@ -890,20 +1022,22 @@ CharCases()
|
|||||||
bool
|
bool
|
||||||
HandleInputMode(Ctx* ctx, UIPanel* p, UIInput* ev)
|
HandleInputMode(Ctx* ctx, UIPanel* p, UIInput* ev)
|
||||||
{
|
{
|
||||||
bool taken = false;
|
bool taken;
|
||||||
|
|
||||||
switch(ev.key)
|
if(!taken) switch(ev.key)
|
||||||
{
|
{
|
||||||
mixin(CharCases());
|
mixin(CharCases());
|
||||||
case Input.Backspace:
|
case Input.Backspace:
|
||||||
{
|
{
|
||||||
Backspace(&p.ed.buf);
|
Backspace(&p.ed.buf);
|
||||||
|
taken = true;
|
||||||
} break;
|
} break;
|
||||||
case Input.Escape:
|
case Input.Escape:
|
||||||
{
|
{
|
||||||
ctx.state = ES.NormalMode;
|
ctx.state = ES.NormalMode;
|
||||||
|
taken = true;
|
||||||
} break;
|
} break;
|
||||||
default: MoveCursor(p.ed, ev); break;
|
default: taken = MoveCursor(p.ed, ev); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return taken;
|
return taken;
|
||||||
@ -999,17 +1133,22 @@ StrContains(bool begins_with)(string str, string match)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
HandleCmdMode(Ctx* ctx)
|
HandleCmdMode(Ctx* ctx, bool* enter_hit, bool* buffer_changed, bool* selection_changed)
|
||||||
{
|
{
|
||||||
UIPanel* panel = ctx.focused_panel;
|
UIPanel* panel = ctx.focused_panel;
|
||||||
Editor* ed = panel.ed;
|
Editor* ed = panel.ed;
|
||||||
CmdPalette* cmd = &ctx.cmd;
|
TextInputBuffer* text_buffer = ctx.state == ES.CmdPalette ? &ctx.cmd.text_input : &ctx.cmd.exec_cmd_input;
|
||||||
|
i64* selected = ctx.state == ES.CmdPalette ? &ctx.cmd.selected : &ctx.cmd.exec_cmd_selected;
|
||||||
|
|
||||||
bool buffer_changed;
|
for(UIInput* ev = ctx.events.first; ev; ev = ev.next)
|
||||||
for(UIInput* ev = ctx.events.first; ev && ctx.state == ES.CmdPalette; ev = ev.next)
|
|
||||||
{
|
{
|
||||||
bool taken;
|
bool taken;
|
||||||
|
|
||||||
|
if(ctx.state != ES.CmdPalette && ctx.state != ES.RunCmd)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch(ev.type)
|
switch(ev.type)
|
||||||
{
|
{
|
||||||
case UIE.Press:
|
case UIE.Press:
|
||||||
@ -1018,11 +1157,9 @@ HandleCmdMode(Ctx* ctx)
|
|||||||
{
|
{
|
||||||
case Enter:
|
case Enter:
|
||||||
{
|
{
|
||||||
if(cmd.current.type != CT.None)
|
if(ctx.state == ES.CmdPalette)
|
||||||
{
|
{
|
||||||
cmd.current = CMD_LIST[cmd.selected];
|
switch(ctx.cmd.cmds[ctx.cmd.selected].type) with(CmdType)
|
||||||
|
|
||||||
switch(cmd.current.type) with(CmdType)
|
|
||||||
{
|
{
|
||||||
case Config:
|
case Config:
|
||||||
{
|
{
|
||||||
@ -1034,45 +1171,31 @@ HandleCmdMode(Ctx* ctx)
|
|||||||
} break;
|
} break;
|
||||||
case Callback:
|
case Callback:
|
||||||
{
|
{
|
||||||
assert(cmd.current.fn, "Callback type doesn't have a function pointer set");
|
assert(ctx.cmd.cmds[ctx.cmd.selected].fn, "Callback type doesn't have a function pointer set");
|
||||||
ctx.state = ES.RunCmd;
|
ctx.state = ES.RunCmd;
|
||||||
} break;
|
} break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*enter_hit = true;
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case Backspace:
|
case Backspace:
|
||||||
{
|
{
|
||||||
if(cmd.icount > 0)
|
if(text_buffer.length)
|
||||||
{
|
{
|
||||||
cmd.icount -= 1;
|
text_buffer.length -= 1;
|
||||||
if(cmd.icount == cmd.current.name.length)
|
*buffer_changed = true;
|
||||||
{
|
|
||||||
cmd.current = cast(Command)NO_CMD;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_changed = true;
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Up, Down:
|
case Up, Down:
|
||||||
{
|
{
|
||||||
i32 incr = ev.key == Up ? -1 : +1;
|
i32 incr = ev.key == Up ? -1 : +1;
|
||||||
i64 selected = cmd.selected;
|
*selected = (*selected)+incr;
|
||||||
for(i64 i = selected+incr; true; i += incr)
|
|
||||||
{
|
|
||||||
if(i < 0 || i >= CMD_LIST.length)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!CMD_LIST[i].hidden)
|
*selection_changed = true;
|
||||||
{
|
|
||||||
selected = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.selected = selected;
|
|
||||||
} break;
|
} break;
|
||||||
case Escape:
|
case Escape:
|
||||||
{
|
{
|
||||||
@ -1082,11 +1205,11 @@ HandleCmdMode(Ctx* ctx)
|
|||||||
{
|
{
|
||||||
if(ev.text.length)
|
if(ev.text.length)
|
||||||
{
|
{
|
||||||
Check(cmd, ev.text.length);
|
Check(text_buffer, ev.text.length);
|
||||||
cmd.buffer[cmd.icount .. cmd.icount+ev.text.length] = cast(u8[])ev.text[0 .. $];
|
text_buffer.data[text_buffer.length .. text_buffer.length+ev.text.length] = cast(u8[])ev.text[0 .. $];
|
||||||
cmd.icount += ev.text.length;
|
text_buffer.length += ev.text.length;
|
||||||
|
|
||||||
buffer_changed = true;
|
*buffer_changed = true;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@ -1099,67 +1222,14 @@ HandleCmdMode(Ctx* ctx)
|
|||||||
DLLRemove(&ctx.events, ev, null);
|
DLLRemove(&ctx.events, ev, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(buffer_changed)
|
|
||||||
{
|
|
||||||
if(cmd.icount)
|
|
||||||
{
|
|
||||||
cmd.visible_opts = 0;
|
|
||||||
string buffer_text = Str(cmd.buffer[0 .. cmd.icount]);
|
|
||||||
static foreach(i; 0 .. CMD_LIST.length)
|
|
||||||
{
|
|
||||||
CMD_LIST[i].hidden = !(StrContains!(false)(CMD_LIST[i].cmd, buffer_text) || StrContains!(false)(CMD_LIST[i].name, buffer_text));
|
|
||||||
cmd.visible_opts += !CMD_LIST[i].hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(CMD_LIST[cmd.selected].hidden)
|
|
||||||
{
|
|
||||||
i64 selected = 0;
|
|
||||||
foreach(i; 0 .. CMD_LIST.length)
|
|
||||||
{
|
|
||||||
if(!CMD_LIST[i].hidden)
|
|
||||||
{
|
|
||||||
selected = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.selected = selected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static foreach(i; 0 .. CMD_LIST.length)
|
|
||||||
{
|
|
||||||
CMD_LIST[i].hidden = false;
|
|
||||||
}
|
|
||||||
cmd.visible_opts = CMD_LIST.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma(inline) void
|
pragma(inline) void
|
||||||
Check(CmdPalette* cmd, u64 length)
|
Check(TextInputBuffer* text_buffer, u64 length)
|
||||||
{
|
{
|
||||||
if(cmd.icount+length >= cmd.buffer.length)
|
if(text_buffer.length+length >= text_buffer.data.length)
|
||||||
{
|
{
|
||||||
cmd.buffer = Realloc!(u8)(cmd.buffer, cmd.buffer.length*2);
|
text_buffer.data = Realloc!(u8)(text_buffer.data, text_buffer.data.length*2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string
|
|
||||||
GetParam(CmdPalette* cmd)
|
|
||||||
{
|
|
||||||
string param;
|
|
||||||
for(u64 i = cmd.current.name.length; i < cmd.icount; i += 1)
|
|
||||||
{
|
|
||||||
if(cmd.buffer[i] != ' ')
|
|
||||||
{
|
|
||||||
param = Str(cmd.buffer[i .. cmd.icount]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return param;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
339
src/editor/ui.d
339
src/editor/ui.d
@ -75,6 +75,13 @@ __gshared Style SEP_STYLE = {
|
|||||||
hl_col: Vec4(0.2, 0.2, 0.2, 1.0),
|
hl_col: Vec4(0.2, 0.2, 0.2, 1.0),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
__gshared Style SCROLLBAR_STYLE = {
|
||||||
|
col: GREY,
|
||||||
|
hl_col: WHITE,
|
||||||
|
corner_radius: Vec4(4.0f),
|
||||||
|
edge_softness: 1.0,
|
||||||
|
};
|
||||||
|
|
||||||
__gshared Style CURSOR_STYLE = {
|
__gshared Style CURSOR_STYLE = {
|
||||||
col: Vec4(1.0),
|
col: Vec4(1.0),
|
||||||
hl_col: Vec4(1.0),
|
hl_col: Vec4(1.0),
|
||||||
@ -639,19 +646,19 @@ Panel(Ctx* ctx, UIPanel* panel)
|
|||||||
Scissor(ctx, rects[1], &style);
|
Scissor(ctx, rects[1], &style);
|
||||||
|
|
||||||
text_rect = Pad(rects[1], PAD);
|
text_rect = Pad(rects[1], PAD);
|
||||||
text_rect.p0.y += offset;
|
|
||||||
|
|
||||||
I64Vec2 cursor_pos = VecPos(&panel.ed.buf);
|
I64Vec2 cursor_coords = VecPos(&panel.ed.buf);
|
||||||
|
LineBuffer* current_lbuf = GetLine(&panel.ed.buf, cursor_coords.y);
|
||||||
UIItem* cursor = MakeItem("###cursor_%s", panel.id);
|
UIItem* cursor = MakeItem("###cursor_%s", panel.id);
|
||||||
if(ctx.focused_panel == panel)
|
if(ctx.focused_panel == panel)
|
||||||
{
|
{
|
||||||
i64 y_pos = cursor_pos.y - panel.ed.line_offset;
|
i64 y_pos = cursor_coords.y - panel.ed.line_offset;
|
||||||
|
|
||||||
cursor.size.x = Active(ES.InputMode) ? 2.0 : fg.abuf.atlas.max_advance;
|
cursor.size.x = Active(ES.InputMode) ? 2.0 : fg.abuf.atlas.max_advance;
|
||||||
cursor.size.y = lheight;
|
cursor.size.y = lheight;
|
||||||
|
|
||||||
cursor.target_pos.y = text_rect.p0.y + (y_pos*lheight);
|
cursor.target_pos.y = text_rect.p0.y + (y_pos*lheight);
|
||||||
cursor.target_pos.x = text_rect.p0.x + (cursor_pos.x*fg.abuf.atlas.max_advance);
|
cursor.target_pos.x = text_rect.p0.x + CalcTextWidth(current_lbuf.text[0 .. cursor_coords.x], &fg.abuf);
|
||||||
|
|
||||||
AnimatePos(cursor);
|
AnimatePos(cursor);
|
||||||
|
|
||||||
@ -663,6 +670,8 @@ Panel(Ctx* ctx, UIPanel* panel)
|
|||||||
DrawRect(ctx, cursor.rect, &CURSOR_STYLE);
|
DrawRect(ctx, cursor.rect, &CURSOR_STYLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
text_rect.p0.y += offset;
|
||||||
|
|
||||||
u64 i = start_ln;
|
u64 i = start_ln;
|
||||||
|
|
||||||
if(ctx.focused_panel == panel)
|
if(ctx.focused_panel == panel)
|
||||||
@ -671,18 +680,18 @@ Panel(Ctx* ctx, UIPanel* panel)
|
|||||||
{
|
{
|
||||||
for(LineBuffer* lbuf = GetLine(&panel.ed.buf, i); i < max_ln && !CheckNil(g_NIL_LINE_BUF, lbuf); i += 1, lbuf = GetLine(&panel.ed.buf, i))
|
for(LineBuffer* lbuf = GetLine(&panel.ed.buf, i); i < max_ln && !CheckNil(g_NIL_LINE_BUF, lbuf); i += 1, lbuf = GetLine(&panel.ed.buf, i))
|
||||||
{
|
{
|
||||||
if(i == cursor_pos.y)
|
if(i == cursor_coords.y)
|
||||||
{
|
{
|
||||||
string str = Str(lbuf.text[0 .. cursor_pos.x]);
|
string str = Str(lbuf.text[0 .. cursor_coords.x]);
|
||||||
u8[] tks = cast(u8[])lbuf.style[0 .. cursor_pos.x];
|
u8[] tks = cast(u8[])lbuf.style[0 .. cursor_coords.x];
|
||||||
|
|
||||||
DrawText(ctx, str, tks, fg, text_rect, TA.Left);
|
DrawText(ctx, str, tks, fg, text_rect, TA.Left);
|
||||||
|
|
||||||
Rect split_rect = text_rect;
|
Rect split_rect = text_rect;
|
||||||
split_rect.p0.x = cursor.p0.x;
|
split_rect.p0.x = cursor.p0.x;
|
||||||
|
|
||||||
str = Str(lbuf.text[cursor_pos.x .. $]);
|
str = Str(lbuf.text[cursor_coords.x .. $]);
|
||||||
tks = cast(u8[])lbuf.style[cursor_pos.x .. $];
|
tks = cast(u8[])lbuf.style[cursor_coords.x .. $];
|
||||||
|
|
||||||
DrawText(ctx, str, tks, fg, split_rect, TA.Left);
|
DrawText(ctx, str, tks, fg, split_rect, TA.Left);
|
||||||
}
|
}
|
||||||
@ -698,7 +707,7 @@ Panel(Ctx* ctx, UIPanel* panel)
|
|||||||
{
|
{
|
||||||
for(LineBuffer* lbuf = GetLine(&panel.ed.buf, i); i < max_ln && !CheckNil(g_NIL_LINE_BUF, lbuf); i += 1, lbuf = GetLine(&panel.ed.buf, i))
|
for(LineBuffer* lbuf = GetLine(&panel.ed.buf, i); i < max_ln && !CheckNil(g_NIL_LINE_BUF, lbuf); i += 1, lbuf = GetLine(&panel.ed.buf, i))
|
||||||
{
|
{
|
||||||
DrawText(ctx, Str(lbuf.text), cast(u8[])lbuf.style, fg, text_rect, TA.Left, cursor_pos.y == i ? cursor_pos.x : -1);
|
DrawText(ctx, Str(lbuf.text), cast(u8[])lbuf.style, fg, text_rect, TA.Left, cursor_coords.y == i ? cursor_coords.x : -1);
|
||||||
text_rect.p0.y += lheight;
|
text_rect.p0.y += lheight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -754,65 +763,94 @@ Panel(Ctx* ctx, UIPanel* panel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CommandPalette(Ctx* ctx)
|
SearchInputWindow(T)(string hash_text, TextInputBuffer* text_input, T[] options, bool ready_cond, i64* selected, bool scroll_to_selected) if(is(T == Command) || is(T == string))
|
||||||
{
|
{
|
||||||
|
Ctx* ctx = GetCtx();
|
||||||
Vec2 extent = GetExtent();
|
Vec2 extent = GetExtent();
|
||||||
CmdPalette* cmd = &ctx.cmd;
|
|
||||||
|
|
||||||
f32 x = extent.x * 0.1;
|
f32 x = extent.x * 0.1;
|
||||||
f32 y = extent.y * 0.2;
|
f32 y = extent.y * 0.2;
|
||||||
f32 w = extent.x * 0.8;
|
f32 w = extent.x * 0.8;
|
||||||
f32 h = extent.y * 0.6;
|
f32 h = extent.y * 0.6;
|
||||||
|
|
||||||
UIItem* cmd_item = MakeItem("###cmd_palette");
|
UIItem* window_item = MakeItem(hash_text);
|
||||||
SetReady(cmd_item, ctx.state == ES.CmdPalette);
|
SetReady(window_item, ready_cond);
|
||||||
if(cmd_item.ready_t > 0.0)
|
if(window_item.ready_t > 0.0)
|
||||||
{
|
{
|
||||||
const f32 PAD = 2.0f;
|
const f32 PAD = 2.0f;
|
||||||
|
|
||||||
FontGlyphs* fg = GetFontGlyphs(14);
|
FontGlyphs* fg = GetFontGlyphs(14);
|
||||||
FontGlyphs* sub_fg = GetFontGlyphs(12);
|
|
||||||
|
|
||||||
f32 lheight = fg.abuf.atlas.line_height;
|
f32 lheight = fg.abuf.atlas.line_height;
|
||||||
|
static if(is(T == Command))
|
||||||
|
{
|
||||||
|
FontGlyphs* sub_fg = GetFontGlyphs(12);
|
||||||
f32 sub_lheight = sub_fg.abuf.atlas.line_height;
|
f32 sub_lheight = sub_fg.abuf.atlas.line_height;
|
||||||
|
}
|
||||||
|
|
||||||
cmd_item.p0 = Vec2(x, y);
|
window_item.p0 = Vec2(x, y);
|
||||||
cmd_item.p1 = Vec2(x+w, y+h);
|
window_item.p1 = Vec2(x+w, y+h);
|
||||||
cmd_item.size = Vec2(w, h);
|
window_item.size = Vec2(w, h);
|
||||||
|
|
||||||
Style style = CMD_STYLE;
|
Style style = CMD_STYLE;
|
||||||
|
|
||||||
Rect[2] rects = Split(cmd_item.rect, lheight+PAD*4.0, A2D.Y);
|
Rect[2] rects = Split(window_item.rect, lheight+PAD*4.0, A2D.Y);
|
||||||
|
|
||||||
style.corner_radius.zw = 0.0;
|
style.corner_radius.zw = 0.0;
|
||||||
|
|
||||||
DrawRect(ctx, rects[0], &style, 0.0, cmd_item.ready_t);
|
DrawRect(ctx, rects[0], &style, 0.0, window_item.ready_t);
|
||||||
DrawBorder(ctx, rects[0], &style, 0.0, cmd_item.ready_t);
|
DrawBorder(ctx, rects[0], &style, 0.0, window_item.ready_t);
|
||||||
|
|
||||||
Rect text_input_rect = rects[0];
|
Rect text_input_rect = rects[0];
|
||||||
text_input_rect.p0.y += PAD*2.0f;
|
text_input_rect.p0.y += PAD*2.0f;
|
||||||
text_input_rect.p0.x += PAD*4.0f;
|
text_input_rect.p0.x += PAD*4.0f;
|
||||||
|
|
||||||
string input_str = cmd.icount ? Str(cmd.buffer[0 .. cmd.icount]) : "Type to search...";
|
string input_str = text_input.length ? Str(text_input.data[0 .. text_input.length]) : "Type to search...";
|
||||||
Vec4 input_col = cmd.icount ? WHITE : GREY;
|
Vec4 input_col = text_input.length ? WHITE : GREY;
|
||||||
DrawText(ctx, input_str, input_col, fg, text_input_rect, TA.Left, -1, cmd_item.ready_t);
|
DrawText(ctx, input_str, input_col, fg, text_input_rect, TA.Left, -1, window_item.ready_t);
|
||||||
|
|
||||||
style.corner_radius.zw = CORNER_RADIUS;
|
style.corner_radius.zw = CORNER_RADIUS;
|
||||||
style.corner_radius.xy = 0.0;
|
style.corner_radius.xy = 0.0;
|
||||||
|
|
||||||
DrawRect(ctx, rects[1], &style, 0.0, cmd_item.ready_t);
|
DrawRect(ctx, rects[1], &style, 0.0, window_item.ready_t);
|
||||||
|
|
||||||
Rect border_rect = rects[1];
|
Rect border_rect = rects[1];
|
||||||
|
|
||||||
|
Scissor(ctx, rects[1], &CMD_STYLE);
|
||||||
|
|
||||||
rects[1].p0 += style.border_thickness;
|
rects[1].p0 += style.border_thickness;
|
||||||
rects[1].p1 -= style.border_thickness;
|
rects[1].p1 -= style.border_thickness;
|
||||||
|
|
||||||
Rect opt_rect = rects[1];
|
f32 full_opt_height = lheight+PAD*3.0f;
|
||||||
foreach(i; 0 .. CMD_LIST.length)
|
static if(is(T == Command))
|
||||||
{
|
{
|
||||||
if(CMD_LIST[i].hidden) continue;
|
full_opt_height += sub_lheight;
|
||||||
|
}
|
||||||
|
|
||||||
Rect[2] opt_rects = Split(opt_rect, lheight+sub_lheight+PAD*3.0f, A2D.Y);
|
f32 opt_section_height = rects[1].p1.y-rects[1].p0.y;
|
||||||
|
i64 start_opt_index = cast(i64)floor(window_item.scroll_offset.y/full_opt_height);
|
||||||
|
f32 opt_start_offset = window_item.scroll_offset.y%full_opt_height;
|
||||||
|
|
||||||
|
if(scroll_to_selected)
|
||||||
|
{
|
||||||
|
f32 opt_start_pos = (*selected) * full_opt_height;
|
||||||
|
f32 opt_end_pos = opt_start_pos + full_opt_height;
|
||||||
|
|
||||||
|
if(window_item.scroll_target.y > opt_start_pos)
|
||||||
|
{
|
||||||
|
window_item.scroll_target.y = opt_start_pos;
|
||||||
|
}
|
||||||
|
else if(window_item.scroll_target.y+opt_section_height < opt_end_pos)
|
||||||
|
{
|
||||||
|
window_item.scroll_target.y = opt_end_pos-opt_section_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect opt_rect = rects[1];
|
||||||
|
opt_rect.p0.y -= opt_start_offset;
|
||||||
|
|
||||||
|
UIItem* selected_opt_item = g_UI_NIL;
|
||||||
|
if(start_opt_index < options.length) foreach(i; start_opt_index .. options.length)
|
||||||
|
{
|
||||||
|
Rect[2] opt_rects = Split(opt_rect, full_opt_height, A2D.Y);
|
||||||
if(opt_rects[0].p0.y == opt_rects[0].p1.y)
|
if(opt_rects[0].p0.y == opt_rects[0].p1.y)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@ -821,32 +859,204 @@ CommandPalette(Ctx* ctx)
|
|||||||
UIItem* opt_item = MakeItem!(UIF.Click|UIF.Priority)("###opt_%s", i);
|
UIItem* opt_item = MakeItem!(UIF.Click|UIF.Priority)("###opt_%s", i);
|
||||||
|
|
||||||
f32 opt_height = opt_rects[0].p1.y-opt_rects[1].p0.y;
|
f32 opt_height = opt_rects[0].p1.y-opt_rects[1].p0.y;
|
||||||
opt_item.size = Vec2(cmd_item.size.x, opt_height);
|
opt_item.size = Vec2(window_item.size.x, opt_height);
|
||||||
opt_item.rect = opt_rects[0];
|
opt_item.rect = opt_rects[0];
|
||||||
|
|
||||||
bool hovered = Hovered!(true)(opt_item, &cmd.selected, i) || cmd.selected == i;
|
bool hovered = Hovered!(true)(opt_item, selected, i) || *selected == i;
|
||||||
SetHot(opt_item, hovered);
|
SetHot(opt_item, hovered);
|
||||||
|
|
||||||
DrawRect(ctx, opt_rects[0], &CMD_OPT_STYLES[i%2], opt_item.hot_t, cmd_item.ready_t);
|
DrawRect(ctx, opt_rects[0], &CMD_OPT_STYLES[i%2], opt_item.hot_t, window_item.ready_t);
|
||||||
|
|
||||||
if(opt_rects[0].p1.y - opt_rects[0].p0.y > PAD)
|
if(opt_rects[0].p1.y - opt_rects[0].p0.y > PAD)
|
||||||
{
|
{
|
||||||
opt_rects[0].p0.y += PAD;
|
opt_rects[0].p0.y += PAD;
|
||||||
opt_rects[0].p0.x += PAD*2.0f;
|
opt_rects[0].p0.x += PAD*2.0f;
|
||||||
DrawText(ctx, CMD_LIST[i].name, WHITE, fg, opt_rects[0], TA.Left, -1, cmd_item.ready_t);
|
|
||||||
|
|
||||||
|
static if(is(T == Command))
|
||||||
|
{
|
||||||
|
DrawText(ctx, options[i].name, WHITE, fg, opt_rects[0], TA.Left, -1, window_item.ready_t);
|
||||||
opt_rects[0].p0.y += lheight+PAD;
|
opt_rects[0].p0.y += lheight+PAD;
|
||||||
|
DrawText(ctx, options[i].desc, GREY, sub_fg, opt_rects[0], TA.Left, -1, window_item.ready_t);
|
||||||
DrawText(ctx, CMD_LIST[i].desc, GREY, sub_fg, opt_rects[0], TA.Left, -1, cmd_item.ready_t);
|
}
|
||||||
|
static if(is(T == string))
|
||||||
|
{
|
||||||
|
DrawText(ctx, options[i], WHITE, fg, opt_rects[0], TA.Left, -1, window_item.ready_t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opt_rect = opt_rects[1];
|
opt_rect = opt_rects[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawBorder(ctx, border_rect, &style, 0.0, cmd_item.ready_t);
|
f32 total_cmd_height = options.length*full_opt_height;
|
||||||
|
f32 scrollable_height = clamp(total_cmd_height-opt_section_height, 0.0, f32.max);
|
||||||
|
|
||||||
HandleCmdMode(ctx);
|
window_item.scroll_target.y = clamp(window_item.scroll_target.y, 0.0, scrollable_height);
|
||||||
|
|
||||||
|
if(options.length && total_cmd_height > opt_section_height)
|
||||||
|
{
|
||||||
|
UIItem* scrollbar_item = MakeItem!(UIF.Drag|UIF.Priority|UIF.TargetLeniency)("%s_scroll", hash_text);
|
||||||
|
|
||||||
|
f32 scrollbar_pct = opt_section_height/total_cmd_height;
|
||||||
|
f32 scrollbar_height = opt_section_height*scrollbar_pct;
|
||||||
|
f32 offset_pct = Remap(window_item.scroll_target.y, 0.0, scrollable_height, 0.0, 1.0);
|
||||||
|
f32 scrollable_range = opt_section_height-scrollbar_height;
|
||||||
|
f32 scrollbar_offset = offset_pct*scrollable_range;
|
||||||
|
f32 inner_width = rects[1].p1.x-rects[1].p0.x;
|
||||||
|
|
||||||
|
Rect[2] scrollbar_rects = Split(rects[1], inner_width-10.0f, A2D.X);
|
||||||
|
|
||||||
|
scrollbar_item.rect = scrollbar_rects[1];
|
||||||
|
scrollbar_item.rect.p0.y += scrollbar_offset;
|
||||||
|
scrollbar_item.rect.p1.y = scrollbar_item.rect.p0.y+scrollbar_height;
|
||||||
|
scrollbar_item.rect.p1.x -= 2.0f;
|
||||||
|
|
||||||
|
i32 scrolled;
|
||||||
|
for(UIInput* i = ctx.events.first; !Nil(i) && ready_cond; i = i.next)
|
||||||
|
{
|
||||||
|
if(i.type == UIE.Scroll)
|
||||||
|
{
|
||||||
|
scrolled += i.scroll;
|
||||||
|
DLLRemove(&ctx.events, i, g_UI_NIL_INPUT);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IVec2 drag;
|
||||||
|
if(Dragged(ctx, scrollbar_item, &drag) || scrolled != 0)
|
||||||
|
{
|
||||||
|
drag.y -= scrolled*40;
|
||||||
|
|
||||||
|
f32 mov_pct = Remap(drag.y, 0.0, scrollable_range, 0.0, 1.0);
|
||||||
|
offset_pct -= mov_pct;
|
||||||
|
offset_pct = clamp(offset_pct, 0.0, 1.0);
|
||||||
|
window_item.scroll_target.y = scrollable_height * offset_pct;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawRect(ctx, scrollbar_item.rect, &SCROLLBAR_STYLE, 0.0f, window_item.ready_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
EndScissor(ctx);
|
||||||
|
|
||||||
|
DrawBorder(ctx, border_rect, &style, 0.0, window_item.ready_t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window_item.scroll_target.y = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
OpenFileWindow(Ctx* ctx)
|
||||||
|
{
|
||||||
|
bool exit;
|
||||||
|
CmdPalette* cmd = &ctx.cmd;
|
||||||
|
|
||||||
|
if(!cmd.exec_cmd_opts.length && !cmd.exec_cmd_input.length)
|
||||||
|
{
|
||||||
|
cmd.exec_cmd_opts = ctx.file_names[0 .. $];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool enter_hit, buffer_changed, selection_changed;
|
||||||
|
if(ctx.state == ES.RunCmd)
|
||||||
|
{
|
||||||
|
HandleCmdMode(ctx, &enter_hit, &buffer_changed, &selection_changed);
|
||||||
|
if(buffer_changed)
|
||||||
|
{
|
||||||
|
if(cmd.exec_cmd_input.length)
|
||||||
|
{
|
||||||
|
Reset(&cmd.exec_cmd_arena);
|
||||||
|
cmd.exec_cmd_opts = Alloc!(string)(ctx.file_names.length);
|
||||||
|
|
||||||
|
u64 option_count;
|
||||||
|
string buffer_text = Str(cmd.exec_cmd_input);
|
||||||
|
foreach(i; 0 .. ctx.file_names.length)
|
||||||
|
{
|
||||||
|
if(StrContains!(false)(ctx.file_names[i], buffer_text))
|
||||||
|
{
|
||||||
|
cmd.exec_cmd_opts[option_count++] = ctx.file_names[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.exec_cmd_opts = cmd.exec_cmd_opts[0 .. option_count];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmd.exec_cmd_opts = ctx.file_names[0 .. $];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(buffer_changed || selection_changed)
|
||||||
|
{
|
||||||
|
cmd.exec_cmd_selected = clamp(cmd.exec_cmd_selected, 0, cmd.exec_cmd_opts.length ? cmd.exec_cmd_opts.length-1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cmd.exec_cmd_opts.length)
|
||||||
|
{
|
||||||
|
string file_name = cmd.exec_cmd_opts[cmd.exec_cmd_selected];
|
||||||
|
if(enter_hit && file_name.length)
|
||||||
|
{
|
||||||
|
OpenFile(ctx.focused_panel.ed, file_name);
|
||||||
|
exit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SearchInputWindow(
|
||||||
|
"###open_file",
|
||||||
|
&cmd.exec_cmd_input,
|
||||||
|
cmd.exec_cmd_opts,
|
||||||
|
ctx.state == ES.RunCmd,
|
||||||
|
&cmd.exec_cmd_selected,
|
||||||
|
selection_changed
|
||||||
|
);
|
||||||
|
|
||||||
|
return exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CommandPalette(Ctx* ctx)
|
||||||
|
{
|
||||||
|
CmdPalette* cmd = &ctx.cmd;
|
||||||
|
|
||||||
|
bool enter_hit, buffer_changed, selection_changed;
|
||||||
|
if(ctx.state == ES.CmdPalette)
|
||||||
|
{
|
||||||
|
HandleCmdMode(ctx, &enter_hit, &buffer_changed, &selection_changed);
|
||||||
|
|
||||||
|
if(buffer_changed)
|
||||||
|
{
|
||||||
|
if(cmd.text_input.length)
|
||||||
|
{
|
||||||
|
u64 list_count;
|
||||||
|
|
||||||
|
string buffer_text = Str(cmd.text_input);
|
||||||
|
static foreach(i; 0 .. CMD_LIST.length)
|
||||||
|
{
|
||||||
|
if(StrContains!(false)(CMD_LIST[i].cmd, buffer_text) || StrContains!(false)(CMD_LIST[i].name, buffer_text))
|
||||||
|
{
|
||||||
|
cmd.cmd_arr[list_count++] = CMD_LIST[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.cmds = cmd.cmd_arr[0 .. list_count];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmd.cmds = CMD_LIST[0 .. $];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(buffer_changed || selection_changed)
|
||||||
|
{
|
||||||
|
cmd.selected = clamp(cmd.selected, 0, cmd.cmds.length ? cmd.cmds.length-1 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SearchInputWindow(
|
||||||
|
"###cmd_palette",
|
||||||
|
&cmd.text_input,
|
||||||
|
cmd.cmds,
|
||||||
|
ctx.state == ES.CmdPalette,
|
||||||
|
&cmd.selected,
|
||||||
|
selection_changed
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -866,7 +1076,7 @@ AddPanel(UIPanel* target, Axis2D axis)
|
|||||||
first.parent = second.parent = target;
|
first.parent = second.parent = target;
|
||||||
first.pct = second.pct = 0.5;
|
first.pct = second.pct = 0.5;
|
||||||
|
|
||||||
g_ctx.focus_key = second.key;
|
Focus(second);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -892,7 +1102,7 @@ AddPanel(UIPanel* target, Axis2D axis)
|
|||||||
|
|
||||||
panel.pct = new_pct;
|
panel.pct = new_pct;
|
||||||
|
|
||||||
g_ctx.focus_key = panel.key;
|
Focus(panel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1096,7 +1306,9 @@ BeginUI(Inputs* inputs)
|
|||||||
ctx.events.first = ctx.events.last = null;
|
ctx.events.first = ctx.events.last = null;
|
||||||
|
|
||||||
bool mouse_moved;
|
bool mouse_moved;
|
||||||
|
static f32 mouse_down_elapsed = 0.0;
|
||||||
static bool dragging;
|
static bool dragging;
|
||||||
|
static i32 final_y;
|
||||||
static bool mouse_down;
|
static bool mouse_down;
|
||||||
for(InputEvent* i = inputs.first; i; i = i.next)
|
for(InputEvent* i = inputs.first; i; i = i.next)
|
||||||
{
|
{
|
||||||
@ -1105,26 +1317,35 @@ BeginUI(Inputs* inputs)
|
|||||||
case Input.LeftClick:
|
case Input.LeftClick:
|
||||||
{
|
{
|
||||||
mouse_down = i.pressed;
|
mouse_down = i.pressed;
|
||||||
if(!mouse_down)
|
if(mouse_down)
|
||||||
{
|
{
|
||||||
PushUIEvent(ctx, UIInput(dragging ? UIE.DragRelease : UIE.Click));
|
PushUIEvent(ctx, UIInput(UIE.Click));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(dragging)
|
||||||
|
{
|
||||||
|
PushUIEvent(ctx, UIInput(UIE.DragRelease));
|
||||||
|
final_y = 0;
|
||||||
|
}
|
||||||
|
mouse_down_elapsed = 0.0;
|
||||||
dragging = false;
|
dragging = false;
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case Input.MouseMotion:
|
case Input.MouseMotion:
|
||||||
{
|
{
|
||||||
mouse_moved = true;
|
mouse_moved = true;
|
||||||
ctx.mouse_pos = IVec2(i.x, i.y);
|
ctx.mouse_pos = IVec2(i.x, i.y);
|
||||||
|
|
||||||
if(!dragging && mouse_down)
|
if(!dragging && mouse_down_elapsed > 0.06f)
|
||||||
{
|
{
|
||||||
PushUIEvent(ctx, UIInput(type: UIE.DragStart, pos: IVec2(i.x, i.y)));
|
PushUIEvent(ctx, UIInput(type: UIE.DragStart, pos: IVec2(i.x, i.y)));
|
||||||
|
dragging = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
dragging = mouse_down;
|
|
||||||
|
|
||||||
if(dragging)
|
if(dragging)
|
||||||
{
|
{
|
||||||
|
final_y += i.rel_y;
|
||||||
PushUIEvent(ctx, UIInput(type: UIE.Drag, rel: IVec2(i.rel_x, i.rel_y)));
|
PushUIEvent(ctx, UIInput(type: UIE.Drag, rel: IVec2(i.rel_x, i.rel_y)));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -1145,6 +1366,11 @@ BeginUI(Inputs* inputs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mouse_down)
|
||||||
|
{
|
||||||
|
mouse_down_elapsed += g_delta;
|
||||||
|
}
|
||||||
|
|
||||||
u64 next_frame = ctx.frame+1;
|
u64 next_frame = ctx.frame+1;
|
||||||
|
|
||||||
// Check current mouse target
|
// Check current mouse target
|
||||||
@ -1435,19 +1661,19 @@ DrawBorder(Ctx* ctx, Rect rect, Style* style, f32 hot_t = 0.0, f32 ready_t = 1.0
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DrawRect(Ctx* ctx, Rect rect, Style* style, f32 hot_t = 0.0, f32 ready_t = 1.0)
|
DrawRect(Ctx* ctx, Rect rect, Style* style, f32 hot_t = 0.0f, f32 ready_t = 1.0f)
|
||||||
{
|
{
|
||||||
Vec4 col = style.col;
|
Vec4 col = style.col;
|
||||||
AnimateHot(hot_t, style.hl_col, &col);
|
AnimateHot(hot_t, style.hl_col, &col);
|
||||||
AnimateReady(ready_t, &col);
|
AnimateReady(ready_t, &col);
|
||||||
|
|
||||||
bool bordered = style.border_thickness > 0.0009;
|
bool bordered = style.border_thickness > 0.0009f;
|
||||||
|
|
||||||
Vertex* v = GetVertex(ctx);
|
Vertex* v = GetVertex(ctx);
|
||||||
v.dst_start = rect.p0 + style.border_thickness;
|
v.dst_start = rect.p0 + style.border_thickness;
|
||||||
v.dst_end = rect.p1 - style.border_thickness;
|
v.dst_end = rect.p1 - style.border_thickness;
|
||||||
v.cols = col;
|
v.cols = col;
|
||||||
v.corner_radius = style.corner_radius*(cast(f32)(bordered)*0.5);
|
v.corner_radius = style.corner_radius * (bordered ? 0.5f : 1.0f);
|
||||||
v.edge_softness = style.edge_softness;
|
v.edge_softness = style.edge_softness;
|
||||||
|
|
||||||
Clamp(ctx, v);
|
Clamp(ctx, v);
|
||||||
@ -1707,7 +1933,16 @@ NewItem(Ctx* ctx)
|
|||||||
UIItem*
|
UIItem*
|
||||||
MakeItem(UIFlags flags = UIF.None, Args...)(string str, Args args)
|
MakeItem(UIFlags flags = UIF.None, Args...)(string str, Args args)
|
||||||
{
|
{
|
||||||
char[] key = sformat(Alloc!(char)(&g_ctx.str_arenas[g_ctx.f_idx], cast(u64)(str.length*1.5)), str, args);
|
u64 len = cast(u64)(str.length*1.5);
|
||||||
|
static foreach(i; 0 .. Args.length)
|
||||||
|
{
|
||||||
|
static if(StringType!(Args[i]))
|
||||||
|
{
|
||||||
|
len += args[i].length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char[] key = sformat(Alloc!(char)(&g_ctx.str_arenas[g_ctx.f_idx], len), str, args);
|
||||||
return MakeItem(key, flags);
|
return MakeItem(key, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1861,7 +2096,7 @@ DrawGlyph(Rect rect, Glyph* glyph, f32* x_pos, f32 y, f32 line_height, Vec4 col
|
|||||||
}
|
}
|
||||||
else if(glyph.ch == '\t')
|
else if(glyph.ch == '\t')
|
||||||
{
|
{
|
||||||
*x_pos += advance * (ctx.tab_width - 1);
|
*x_pos += advance*ctx.tab_width;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user