luma/luma/wm/ui.c
2025-07-06 17:58:57 +03:00

476 lines
13 KiB
C

#include"ui.h"
#include"tiny.h"
#include"../vid/api.h"
#include"../sys.h"
#include"wm.h"
#include"logserver.h"
/*static void gtext_render(struct GObj *_) {
struct GText *this = (void*) _;
LumaVidCommand *cmd = VidLink;
cmd->op = LUMA_VID_COMMAND_SET_COLOR_FLAT;
cmd->colorFlat.r = 0xF0;
cmd->colorFlat.g = 0xF0;
cmd->colorFlat.b = 0xF0;
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->colorFlat));
cmd->op = LUMA_VID_COMMAND_RECT;
cmd->rect.x1 = this->x;
cmd->rect.x2 = this->x + this->w - 1;
cmd->rect.y1 = this->y;
cmd->rect.y2 = this->y + this->h - 1;
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->rect));
cmd->op = LUMA_VID_COMMAND_SET_COLOR_FLAT;
cmd->colorFlat.r = 0x00;
cmd->colorFlat.g = 0x00;
cmd->colorFlat.b = 0x00;
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->colorFlat));
DynStr16 *txt = this->data;
if(!txt || !txt->len) txt = this->placeholder;
if(txt) {
cmd->op = LUMA_VID_COMMAND_TEXT;
cmd->text.x = this->x + 5;
cmd->text.y = this->y + 2;
cmd->text.wall = this->x + this->w;
std_copy(cmd->text.data, txt->data, cmd->text.len = txt->len);
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->text) + cmd->text.len);
}
cmd->op = LUMA_VID_COMMAND_END;
memory_barrier();
sys_signal_send(VidLink, -1);
sys_signal_wait(VidLink, NULL);
}
static void gtext_key(struct GObj *_, struct GKeyEvent ev) {
if(_->focus == 0) return;
struct GText *this = (void*) _;
if(ev.press) {
if(!this->data) {
this->data = g_dynstr16_new(8, 0, NULL);
}
if(ev.scancode == LK_BACKSPACE) {
if(this->data->len) {
this->data->len--;
}
} else {
uint8_t newCh = 0;
if(ev.scancode >= LK_A && ev.scancode <= LK_Z) {
newCh = ev.scancode - LK_A;
newCh += ev.shift ? 'A' : 'a';
} else if(ev.scancode == LK_SPACE) {
newCh = ' ';
}
if(newCh) this->data = g_dynstr16_append(this->data, 1, &newCh);
}
}
}
static void gtext_destroy(struct GObj *_) {
struct GText *this = (void*) _;
if(this->data) g_dynstr16_free(this->data);
if(this->placeholder) g_dynstr16_free(this->placeholder);
tiny_free(this);
}
struct GText *gtext_new(Coord x, Coord y, Coord w, Coord h, DynStr16 *placeholder, DynStr16 *str) {
struct GText *ret = tiny_calloc(sizeof(*ret), 1);
ret->onRender = gtext_render;
ret->onKey = gtext_key;
ret->destroy = gtext_destroy;
ret->x = x;
ret->y = y;
ret->w = w;
ret->h = h;
ret->placeholder = placeholder;
ret->data = str;
return ret;
}
static void gcont_render(struct GObj *_) {
struct GContainer *this = (void*) _;
for(size_t i = 0; i < this->childCount; i++) {
if(this->children[i].obj && this->children[i].obj->onRender) {
this->children[i].obj->onRender(this->children[i].obj);
}
}
}
static void gcont_key(struct GObj *_, struct GKeyEvent ev) {
if(_->focus == 0) return;
struct GContainer *this = (void*) _;
for(size_t i = 0; i < this->childCount; i++) {
if(this->children[i].obj && this->children[i].obj->onKey) {
this->children[i].obj->onKey(this->children[i].obj, ev);
}
}
}
static void gcont_destroy(struct GObj *_) {
struct GContainer *this = (void*) _;
for(size_t i = 0; i < this->childCount; i++) {
if(this->children[i].obj) {
this->children[i].obj->destroy(this->children[i].obj);
}
}
tiny_free(this->children);
tiny_free(this);
}
struct GContainer *gcont_new(Coord x, Coord y, Coord w, Coord h, FitterFunc fitter) {
struct GContainer *ret = tiny_calloc(sizeof(*ret), 1);
ret->onRender = gcont_render;
ret->onKey = gcont_key;
ret->destroy = gcont_destroy;
ret->x = x;
ret->y = y;
ret->w = w;
ret->h = h;
ret->fitter = fitter;
return ret;
}
int gcont_add(struct GContainer *this, GContainerChildMeta meta, struct GObj* child) {
struct GContainerChild *newchildren = tiny_realloc(this->children, sizeof(*this->children) * (this->childCount + 1));
if(newchildren) {
this->children = newchildren;
this->children[this->childCount].meta = meta;
this->children[this->childCount].obj = child;
this->childCount++;
if(this->fitter) this->fitter((struct GObj*) this);
return 1;
} else {
return 0;
}
}
void gcont_set(struct GContainer *this, size_t index, GContainerChildMeta meta, struct GObj *obj) {
this->children[index] = (struct GContainerChild) {
.meta = meta,
.obj = obj,
};
if(this->fitter) this->fitter((struct GObj*) this);
}
void gcont_del(struct GContainer *this, size_t index) {
std_move(&this->children[index], &this->children[index + 1], sizeof(*this->children) * (this->childCount - index - 1));
this->children = tiny_realloc(this->children, sizeof(*this->children) * (--this->childCount));
}
void gcont_splitter_v(struct GObj *_) {
struct GContainer *c = (void*) _;
struct GContainerChild *o = c->children;
for(size_t i = 0; i < c->childCount; i++, o++) {
if(o[0].obj) {
o[0].obj->x = c->x;
o[0].obj->y = c->y + c->h * i / c->childCount;
o[0].obj->w = c->w;
o[0].obj->h = c->h / c->childCount;
if(o[0].obj->fitter) o[0].obj->fitter(o[0].obj);
}
}
}
void gcont_splitter_h(struct GObj *_) {
struct GContainer *c = (void*) _;
struct GContainerChild *o = c->children;
for(size_t i = 0; i < c->childCount; i++, o++) {
if(o[0].obj) {
o[0].obj->x = c->x + c->w * i / c->childCount;
o[0].obj->y = c->y;
o[0].obj->w = c->w / c->childCount;
o[0].obj->h = c->h;
if(o[0].obj->fitter) o[0].obj->fitter(o[0].obj);
}
}
}
static void gwindow_render(struct GObj *_) {
struct GWindow *this = (void*) _;
LumaVidCommand *cmd = VidLink;
cmd->op = LUMA_VID_COMMAND_SET_COLOR_FLAT;
if(this->focus) {
cmd->colorFlat.r = 0xF0;
cmd->colorFlat.g = 0xF0;
cmd->colorFlat.b = 0xF0;
} else {
cmd->colorFlat.r = 0x80;
cmd->colorFlat.g = 0x80;
cmd->colorFlat.b = 0x80;
}
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->colorFlat));
cmd->op = LUMA_VID_COMMAND_RECT;
cmd->rect.x1 = this->x;
cmd->rect.x2 = this->x + this->w - 1;
cmd->rect.y1 = this->y;
cmd->rect.y2 = this->y + 11;
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->rect));
cmd->op = LUMA_VID_COMMAND_SET_COLOR_FLAT;
cmd->colorFlat.r = 0x00;
cmd->colorFlat.g = 0x00;
cmd->colorFlat.b = 0x00;
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->colorFlat));
cmd->op = LUMA_VID_COMMAND_TEXT;
cmd->text.x = this->x + 3;
cmd->text.y = this->y + 1;
std_copy(cmd->text.data, this->name->data, cmd->text.len = this->name->len);
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->text) + cmd->text.len);
cmd->op = LUMA_VID_COMMAND_END;
memory_barrier();
sys_signal_send(VidLink, -1);
sys_signal_wait(VidLink, NULL);
if(this->child) {
if(this->child->onRender) this->child->onRender(this->child);
}
}
static void gwindow_key(struct GObj *_, struct GKeyEvent ev) {
if(_->focus == 0) return;
struct GWindow *this = (void*) _;
if(this->child) {
if(this->child->onKey) this->child->onKey(this->child, ev);
}
}
static void gwindow_fitter(struct GObj *_) {
struct GWindow *this = (void*) _;
if(this->child) {
this->child->x = this->x;
this->child->y = this->y + 12;
this->child->w = this->w;
this->child->h = this->h - 12;
if(this->child->fitter) this->child->fitter(this->child);
}
}
static void gwindow_destroy(struct GObj *_) {
struct GWindow *this = (void*) _;
if(this->child) {
this->child->destroy(this->child);
}
if(this->name) {
g_dynstr16_free(this->name);
}
tiny_free(this);
}
struct GWindow *gwindow_new(Coord x, Coord y, Coord w, Coord h, DynStr16 *name, struct GObj *child, size_t owner) {
struct GWindow *ret = tiny_calloc(sizeof(*ret), 1);
ret->onRender = gwindow_render;
ret->onKey = gwindow_key;
ret->fitter = gwindow_fitter;
ret->destroy = gwindow_destroy;
ret->x = x;
ret->y = y;
ret->w = w;
ret->h = h;
ret->name = name;
ret->child = child;
ret->owner = owner;
return ret;
}
int gwindow_regcmd(struct GWindow *this, Str16 *name, void *ud, GCMDFunc handler) {
struct Command *newarray = tiny_realloc(this->cmds.array, sizeof(*this->cmds.array) * (this->cmds.count + 1));
if(!newarray) {
return 0;
}
newarray[this->cmds.count] = (struct Command) {
.name = name,
.ud = ud,
.run = handler
};
this->cmds.array = newarray;
this->cmds.count++;
return 1;
}
static void glabel_render(struct GObj *_) {
struct GLabel *this = (void*) _;
LumaVidCommand *cmd = VidLink;
cmd->op = LUMA_VID_COMMAND_SET_COLOR_FLAT;
cmd->colorFlat.r = 0x00;
cmd->colorFlat.g = 0x00;
cmd->colorFlat.b = 0x00;
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->colorFlat));
if(this->data) {
cmd->op = LUMA_VID_COMMAND_TEXT;
cmd->text.x = this->x;
cmd->text.y = this->y;
cmd->text.wall = this->x + this->w;
std_copy(cmd->text.data, this->data->data, cmd->text.len = this->data->len);
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->text) + cmd->text.len);
}
cmd->op = LUMA_VID_COMMAND_END;
memory_barrier();
sys_signal_send(VidLink, -1);
sys_signal_wait(VidLink, NULL);
}
static void glabel_destroy(struct GObj *_) {
struct GLabel *this = (void*) _;
if(this->data && this->owned) {
g_dynstr16_free(this->data);
}
tiny_free(this);
}
struct GLabel *glabel_new(Coord x, Coord y, Coord w, Coord h, DynStr16 *data, int owned) {
struct GLabel *ret = tiny_calloc(sizeof(*ret), 1);
ret->onRender = glabel_render;
ret->onKey = NULL;
ret->fitter = NULL;
ret->destroy = glabel_destroy;
ret->x = x;
ret->y = y;
ret->w = w;
ret->h = h;
ret->data = data;
ret->owned = owned;
return ret;
}
static void glist_render(struct GObj *_) {
struct GList *this = (void*) _;
for(size_t i = 0; i < this->childCount; i++) {
LumaVidCommand *cmd = VidLink;
cmd->op = LUMA_VID_COMMAND_SET_COLOR_FLAT;
if(this->children[i].selected) {
cmd->colorFlat.r = 0xFF;
cmd->colorFlat.g = 0xFF;
cmd->colorFlat.b = 0xFF;
} else if(i == this->cursor) {
cmd->colorFlat.r = 0x80;
cmd->colorFlat.g = 0x80;
cmd->colorFlat.b = 0x80;
} else {
cmd->colorFlat.r = 0x00;
cmd->colorFlat.g = 0x00;
cmd->colorFlat.b = 0x00;
}
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->colorFlat));
cmd->op = LUMA_VID_COMMAND_TEXT;
cmd->text.x = this->x;
cmd->text.y = this->y + 13 * i;
cmd->text.wall = this->x + this->w;
std_copy(cmd->text.data, this->children[i].text->data, cmd->text.len = this->children[i].text->len);
cmd = (LumaVidCommand*) ((uintptr_t) cmd + sizeof(cmd->text) + cmd->text.len);
cmd->op = LUMA_VID_COMMAND_END;
memory_barrier();
sys_signal_send(VidLink, -1);
sys_signal_wait(VidLink, NULL);
}
}
static void glist_key(struct GObj *_, struct GKeyEvent ev) {
struct GList *this = (void*) _;
if(!ev.press) return;
if(ev.scancode == LK_DOWN) {
if(this->childCount) {
this->cursor = (this->cursor + 1) % this->childCount;
} else {
this->cursor = 0;
}
dirty_obj(_);
} else if(ev.scancode == LK_UP) {
if(this->childCount) {
this->cursor = (this->cursor - 1 + this->childCount) % this->childCount;
} else {
this->cursor = 0;
}
dirty_obj(_);
} else if(ev.scancode == LK_SPACE) {
if(this->cursor < this->childCount) {
this->children[this->cursor].selected ^= 1;
}
dirty_obj(_);
}
}
static void glist_destroy(struct GObj *_) {
struct GList *this = (void*) _;
for(size_t i = 0; i < this->childCount; i++) {
g_dynstr16_free(this->children[i].text);
}
tiny_free(this->children);
}
struct GList *glist_new(Coord x, Coord y, Coord w, Coord h) {
struct GList *ret = tiny_calloc(sizeof(*ret), 1);
ret->onRender = glist_render;
ret->onKey = glist_key;
ret->fitter = NULL;
ret->destroy = glist_destroy;
ret->x = x;
ret->y = y;
ret->w = w;
ret->h = h;
ret->childCount = 0;
ret->children = NULL;
return ret;
}
int glist_add(struct GList *this, DynStr16 *str, void *ud) {
struct GListChild *newchildren = tiny_realloc(this->children, sizeof(*this->children) * (this->childCount + 1));
if(newchildren) {
newchildren[this->childCount++] = (struct GListChild) {
.text = str,
.selected = 0,
.ud = ud,
};
this->children = newchildren;
return 1;
}
return 0;
}
void glist_clear(struct GList *this) {
this->childCount = 0;
tiny_free(this->children);
this->children = NULL;
this->cursor = 0;
}*/
DynStr16 *g_dynstr16_new(uint16_t cap, uint16_t len, const void *data) {
DynStr16 *ret = tiny_malloc(sizeof(*ret) + cap);
ret->cap = cap;
ret->len = len;
if(data) {
std_copy(ret->data, data, len);
}
return ret;
}
DynStr16 *g_dynstr16_append(DynStr16 *this, uint16_t len, const void *data) {
if(this->len + len > this->cap) {
this = tiny_realloc(this, sizeof(*this) + (this->cap = this->len + len));
}
std_copy(this->data + this->len, data, len);
this->len += len;
return this;
}
void g_dynstr16_free(DynStr16 *this) {
tiny_free(this);
}
Str16 *g_str16_new(uint16_t len, const void *data) {
Str16 *ret = tiny_malloc(sizeof(*ret) + len);
ret->len = len;
std_copy(ret->data, data, len);
return ret;
}