ref: 3b83debfa8a7a5dc82c40d6500d35a9c98135cea
parent: cef5fe0310139ee6d16db580e30cb0bc5657c54b
author: sirjofri <sirjofri@sirjofri.de>
date: Sun May 26 11:42:59 EDT 2024
better option handling (buttons and entry boxes)
--- a/plan9.c
+++ b/plan9.c
@@ -186,11 +186,8 @@
exits(nil);
}
-char *showcmd = "c_game show";
-
static void p9_draw_text(void *handle, int x, int y, int fonttype, int fontsize, int align, int color, const char *text)
{
- // todo: align, fontsize, fonttype
Font *f;
Point p, size;
frontend *fe = (frontend*)handle;
@@ -616,52 +613,104 @@
}
}
+typedef struct Option Option;
+struct Option {
+ char *name;
+ Control *kctl;
+ Control *vctl;
+};
+
+Option options[32];
+
+Option*
+findoption(char *name)
+{
+ Option *o;
+ for (o = options; o->name; o++)
+ if (strcmp(o->name, name) == 0)
+ return o;
+ return nil;
+}
+
+Option*
+findoptionname(char *ctl)
+{
+ Option *o;
+ for (o = options; o->name; o++)
+ if (strcmp(o->vctl->name, ctl) == 0)
+ return o;
+ return nil;
+}
+
void
+clearoptions(void)
+{
+ for (Option *o = options; o->name; o++) {
+ if (o->name == nil)
+ return;
+ free(o->name);
+ chanprint(fe->cs->ctl, "c_settings remove %q", o->kctl->name);
+ chanprint(fe->cs->ctl, "c_settings remove %q", o->vctl->name);
+ deactivate(o->vctl);
+ closecontrol(o->kctl);
+ closecontrol(o->vctl);
+ o->kctl = o->vctl = nil;
+ o->name = nil;
+ }
+}
+
+void
addoption(config_item *cfg)
{
- char buf[128];
- int isnew;
+ char buf[8];
Control *label, *entry;
+ int last;
+ Option *o;
- snprint(buf, 128, "l_%s", cfg->name);
- label = controlcalled(buf);
- isnew = 0;
- if (!label) {
- label = createlabel(fe->cs, buf);
- isnew = 1;
+ for (o = options; o->name; o++) {
+ last++;
}
+
+ o->name = strdup(cfg->name);
+
+ snprint(buf, sizeof(buf), "l_%d", last);
+ label = createlabel(fe->cs, buf);
+ o->kctl = label;
chanprint(fe->cs->ctl, "%q value %q", buf, cfg->name);
chanprint(fe->cs->ctl, "%q align center", buf);
chanprint(fe->cs->ctl, "%q size 100 %d 500 %d", buf, font->height*2, font->height*2);
- if (isnew)
- chanprint(fe->cs->ctl, "c_settings add %q", buf);
- snprint(buf, 128, "e_%s", cfg->name);
+ chanprint(fe->cs->ctl, "c_settings add %q", buf);
- isnew = 0;
- entry = controlcalled(buf);
- if (!entry)
- isnew = 1;
+ snprint(buf, sizeof(buf), "e_%d", last);
+
+ entry = nil;
switch (cfg->type) {
case C_STRING:
- if (!entry)
- entry = createentry(fe->cs, buf);
+ entry = createentry(fe->cs, buf);
chanprint(fe->cs->ctl, "%q border 1", buf);
chanprint(fe->cs->ctl, "%q size 100 %d 500 %d", buf, font->height, font->height);
chanprint(fe->cs->ctl, "%q value %q", buf, cfg->u.string.sval);
+ chanprint(fe->cs->ctl, "%q align center", buf);
+ controlwire(entry, "data", fe->settingschan);
break;
case C_BOOLEAN:
if (!entry)
- entry = createbutton(fe->cs, buf);
+ entry = createtextbutton(fe->cs, buf);
chanprint(fe->cs->ctl, "%q border 1", buf);
+ chanprint(fe->cs->ctl, "%q textcolor black\n%q pressedtextcolor black", buf, buf);
chanprint(fe->cs->ctl, "%q size 100 %d 500 %d", buf, font->height, font->height);
chanprint(fe->cs->ctl, "%q value %d", buf, cfg->u.boolean.bval);
+ chanprint(fe->cs->ctl, "%q text %s", buf, cfg->u.boolean.bval ? "yes" : "no");
+ chanprint(fe->cs->ctl, "%q align center", buf);
+ chanprint(fe->cs->ctl, "%q mask transparent", buf);
+ controlwire(entry, "event", fe->settingschan);
break;
case C_CHOICES:
// todo
break;
}
- if (entry && isnew) {
- controlwire(entry, "event", fe->settingschan);
+ o->vctl = entry;
+ if (entry) {
activate(entry);
chanprint(fe->cs->ctl, "c_settings add %q", buf);
}
@@ -677,6 +726,17 @@
config_item *cfg;
Control *c, *info;
+ /* assumptions: if b_savecfg exists, then l_cfginfo also exists */
+
+ c = controlcalled("b_savecfg");
+ /* if already set up, remove from widget to add back later */
+ if (c) {
+ chanprint(fe->cs->ctl, "c_settings remove l_cfginfo");
+ chanprint(fe->cs->ctl, "c_settings remove b_savecfg");
+ }
+
+ clearoptions();
+
for (int i = 0; i < nelem(configcats); i++) {
cfg = midend_get_config(fe->me, configcats[i], &t);
if (configs[i]) {
@@ -685,21 +745,20 @@
}
configs[i] = cfg;
- while (cfg && cfg->type != C_END) {
+ for (; cfg && cfg->type != C_END; cfg++) {
addoption(cfg);
- cfg++;
}
}
- c = controlcalled("b_savecfg");
/* if already set up, early return */
- if (c)
+ if (c) {
+ goto Addbuttons;
return;
+ }
info = createlabel(fe->cs, "l_cfginfo");
chanprint(fe->cs->ctl, "l_cfginfo align centerleft");
chanprint(fe->cs->ctl, "l_cfginfo size 50 %d 500 %d", font->height, font->height);
- chanprint(fe->cs->ctl, "c_settings add l_cfginfo");
c = createtextbutton(fe->cs, "b_savecfg");
chanprint(fe->cs->ctl, "b_savecfg text Save");
@@ -706,16 +765,45 @@
chanprint(fe->cs->ctl, "b_savecfg border 1");
chanprint(fe->cs->ctl, "b_savecfg align center");
chanprint(fe->cs->ctl, "b_savecfg size 50 %d 100 %d", font->height, font->height);
- chanprint(fe->cs->ctl, "c_settings add b_savecfg");
controlwire(c, "event", fe->c);
activate(c);
+
+Addbuttons:
+ chanprint(fe->cs->ctl, "c_settings add l_cfginfo");
+ chanprint(fe->cs->ctl, "c_settings add b_savecfg");
}
+void setoption(char *name, char *value, config_item *conf);
+
+void
+readoptions(void)
+{
+ char buf[128];
+ char *val;
+ config_item *cfg;
+ Control *c;
+ Option *o;
+
+ for (int i = 0; i < nelem(configcats); i++) {
+ for (cfg = configs[i]; cfg && cfg->type != C_END; cfg++) {
+ if (cfg->type != C_STRING)
+ continue;
+ o = findoption(cfg->name);
+ if (!o || !o->vctl)
+ continue;
+ chanprint(fe->cs->ctl, "%q data", o->vctl->name);
+ val = recvp(fe->settingschan);
+ setoption(cfg->name, val, cfg);
+ }
+ }
+}
+
int
saveoptions(void)
{
char *s;
int r = 1;
+ readoptions();
for (int i = 0; i < nelem(configcats); i++) {
s = midend_set_config(fe->me, configcats[i], configs[i]);
if (s) {
@@ -722,6 +810,8 @@
chanprint(fe->cs->ctl, "l_cfginfo value %q", s);
r = 0;
}
+ free_cfg(configs[i]);
+ configs[i] = nil;
}
loadoptions();
LOG("saved options");
@@ -729,27 +819,36 @@
}
void
-setoption(char *name, char *value)
+setoption(char *name, char *value, config_item *conf)
{
int n;
config_item *cfg;
+ Option *o;
+
+ if (conf) {
+ cfg = conf;
+ goto Found;
+ }
for (int i = 0; i < nelem(configs); i++) {
- cfg = configs[i];
- while (cfg && cfg->type != C_END) {
+ for (cfg = configs[i]; cfg && cfg->type != C_END; cfg++) {
if (strcmp(cfg->name, name) == 0)
goto Found;
- cfg++;
}
}
return;
+
Found:
+ Log("Set %q to %q\n", cfg->name, value);
switch (cfg->type) {
case C_STRING:
cfg->u.string.sval = value;
break;
case C_BOOLEAN:
- n = atoi(value);
- cfg->u.boolean.bval = n ? 1 : 0;
+ n = atoi(value) ? 1 : 0;
+ cfg->u.boolean.bval = n;
+ o = findoption(name);
+ chanprint(fe->cs->ctl, "%q value %d", o->vctl->name, n);
+ chanprint(fe->cs->ctl, "%q text %q", o->vctl->name, n ? "yes" : "no");
break;
case C_CHOICES:
// todo
@@ -983,7 +1082,8 @@
for (;;) {
switch (alt(a)) {
- case 0: /* libcontrol event channel */
+ case 0: /* libcontrol event channel */
+ Log("Control: %s\n", s);
tokenize(s, args, nelem(args));
if (strcmp(args[0], "b_game:") == 0) {
@@ -1015,10 +1115,10 @@
goto Out;
break;
case 4: /* settings */
+ Log("Setting: %s\n", s);
tokenize(s, args, nelem(args));
- s = args[0] + 2; /* get rid of "e_" */
- s[strlen(s)-1] = 0; /* get rid of sender ":" */
- setoption(s, args[2]);
+ args[0][strlen(args[0])-1] = 0; /* get rid of sender ":" */
+ setoption(findoptionname(args[0])->name, args[2], nil);
break;
}
}