Taglists for creating GUIs! Some memory leak fixes.
This commit is contained in:
parent
cf12d340bd
commit
7cf6a7112a
20 changed files with 660 additions and 7 deletions
|
@ -49,6 +49,7 @@ HEADERS = \
|
|||
$$LINUX_HEADERS \
|
||||
src/system/color.h \
|
||||
src/system/surface.h \
|
||||
src/system/taglist.h \
|
||||
src/thirdparty/stb_ds.h \
|
||||
src/thirdparty/stb_image.h \
|
||||
src/thirdparty/memwatch/memwatch.h \
|
||||
|
@ -84,6 +85,7 @@ HEADERS = \
|
|||
SOURCES = \
|
||||
$$LINUX_SOURCES \
|
||||
src/system/surface.c \
|
||||
src/system/taglist.c \
|
||||
src/thirdparty/memwatch/memwatch.c \
|
||||
src/system/memory.c \
|
||||
src/system/array.c \
|
||||
|
|
|
@ -34,9 +34,11 @@ void buttonClickHandlerSet(ButtonT *button, widgetCallback callback) {
|
|||
static void buttonDel(WidgetT **widget) {
|
||||
ButtonT *b = (ButtonT *)*widget;
|
||||
|
||||
arrfree(b->base.children);
|
||||
if (b->title) free(b->title);
|
||||
free(b);
|
||||
b = NULL;
|
||||
*widget = W(b);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,9 +34,11 @@ void checkboxClickHandlerSet(CheckboxT *checkbox, widgetCallback callback) {
|
|||
static void checkboxDel(WidgetT **widget) {
|
||||
CheckboxT *c = (CheckboxT *)*widget;
|
||||
|
||||
arrfree(c->base.children);
|
||||
if (c->title) free(c->title);
|
||||
free(c);
|
||||
c = NULL;
|
||||
*widget = W(c);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -29,9 +29,11 @@ static void desktopPaint(WidgetT *desktop, RectT pos);
|
|||
static void desktopDel(WidgetT **widget) {
|
||||
DesktopT *d = (DesktopT *)*widget;
|
||||
|
||||
arrfree(d->base.children);
|
||||
surfaceDestroy(&d->base.surface);
|
||||
free(d);
|
||||
d = NULL;
|
||||
*widget = W(d);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,9 +28,11 @@ static void framePaint(WidgetT *widget, RectT pos);
|
|||
static void frameDel(WidgetT **widget) {
|
||||
FrameT *f = (FrameT *)*widget;
|
||||
|
||||
arrfree(f->base.children);
|
||||
if (f->title) free(f->title);
|
||||
free(f);
|
||||
f = NULL;
|
||||
*widget = W(f);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -52,9 +52,11 @@ void labelColorForegroundSet(LabelT *label, ColorT color) {
|
|||
static void labelDel(WidgetT **widget) {
|
||||
LabelT *l = (LabelT *)*widget;
|
||||
|
||||
arrfree(l->base.children);
|
||||
if (l->title) free(l->title);
|
||||
free(l);
|
||||
l = NULL;
|
||||
*widget = W(l);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -51,10 +51,13 @@ static void listboxDel(WidgetT **widget) {
|
|||
free(l->values[x]);
|
||||
}
|
||||
}
|
||||
arrfree(l->values);
|
||||
|
||||
arrfree(l->base.children);
|
||||
if (l->title) free(l->title);
|
||||
free(l);
|
||||
l = NULL;
|
||||
*widget = W(l);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,10 +34,12 @@ void pictureClickHandlerSet(PictureT *picture, widgetCallback callback) {
|
|||
static void pictureDel(WidgetT **widget) {
|
||||
PictureT *p = (PictureT *)*widget;
|
||||
|
||||
arrfree(p->base.children);
|
||||
if (p->image) imageUnload(&p->image);
|
||||
if (p->filename) free(p->filename);
|
||||
free(p);
|
||||
p = NULL;
|
||||
*widget = W(p);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -36,9 +36,11 @@ void radioClickHandlerSet(RadioT *radio, widgetCallback callback) {
|
|||
static void radioDel(WidgetT **widget) {
|
||||
RadioT *r = (RadioT *)*widget;
|
||||
|
||||
arrfree(r->base.children);
|
||||
if (r->title) free(r->title);
|
||||
free(r);
|
||||
r = NULL;
|
||||
*widget = W(r);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -503,8 +503,10 @@ static void terminalDel(WidgetT **widget) {
|
|||
}
|
||||
free(t->cells);
|
||||
|
||||
arrfree(t->base.children);
|
||||
free(t);
|
||||
t = NULL;
|
||||
*widget = W(t);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,10 +32,12 @@ static void textboxPaint(WidgetT *widget, RectT pos);
|
|||
static void textboxDel(WidgetT **widget) {
|
||||
TextboxT *t = (TextboxT *)*widget;
|
||||
|
||||
arrfree(t->base.children);
|
||||
if (t->title) free(t->title);
|
||||
if (t->value) free(t->value);
|
||||
free(t);
|
||||
t = NULL;
|
||||
*widget = W(t);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -47,9 +47,11 @@ static void updownVisibleSet(UpdownT *updown);
|
|||
static void updownDel(WidgetT **widget) {
|
||||
UpdownT *u = (UpdownT *)*widget;
|
||||
|
||||
arrfree(u->base.children);
|
||||
if (u->title) free(u->title);
|
||||
free(u);
|
||||
u = NULL;
|
||||
*widget = W(u);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,8 +28,10 @@ static void widgetDel(WidgetT **widget);
|
|||
static void widgetDel(WidgetT **widget) {
|
||||
WidgetT *w = (WidgetT *)*widget;
|
||||
|
||||
arrfree(w->children);
|
||||
free(w);
|
||||
w = NULL;
|
||||
*widget = w;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -80,9 +80,11 @@ static void windowDel(WidgetT **widget) {
|
|||
WindowT *w = (WindowT *)*widget;
|
||||
|
||||
surfaceDestroy(&w->base.surface);
|
||||
arrfree(w->base.children);
|
||||
if (w->title) free(w->title);
|
||||
free(w);
|
||||
w = NULL;
|
||||
*widget = W(w);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
* - No thumb in listbox scrollbar
|
||||
* - Window dragging is being screwball
|
||||
*
|
||||
* - Random crash on exit - looks memwatch / task related
|
||||
* - Random crash on exit - looks memwatch / task related - hasn't happened on DOS yet
|
||||
*/
|
||||
|
||||
|
||||
|
@ -61,6 +61,8 @@
|
|||
#include "listbox.h"
|
||||
#include "terminal.h"
|
||||
|
||||
#include "taglist.h"
|
||||
|
||||
|
||||
static TerminalT *t1 = NULL;
|
||||
static uint8_t lastKey = 0;
|
||||
|
@ -68,8 +70,9 @@ static uint8_t lastKey = 0;
|
|||
|
||||
static void buttonClick(WidgetT *widget);
|
||||
static void mainLoop(void *data);
|
||||
static void terminalTest(void *data);
|
||||
static void test(void *data);
|
||||
//static void test(void *data);
|
||||
static void testTagList(void *data);
|
||||
static void testTerminal(void *data);
|
||||
static void widgetDebugDraw(WidgetT *widget, uint8_t debugToggle);
|
||||
|
||||
|
||||
|
@ -122,6 +125,7 @@ static void mainLoop(void *data) {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
static void test(void *data) {
|
||||
DesktopT *desktop = (DesktopT *)guiRootGet();
|
||||
WindowT *w1 = NULL;
|
||||
|
@ -211,11 +215,153 @@ static void test(void *data) {
|
|||
t1 = terminalNew(0, 0, 80, 24);
|
||||
guiAttach(W(w4), W(t1));
|
||||
|
||||
taskCreate(terminalTest, "terminalTest");
|
||||
taskCreate(testTerminal, "terminalTest");
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static void testTagList(void *data) {
|
||||
WindowT *w1 = NULL;
|
||||
WindowT *w2 = NULL;
|
||||
WindowT *w3 = NULL;
|
||||
WindowT *w4 = NULL;
|
||||
ButtonT *b1 = NULL;
|
||||
LabelT *l1 = NULL;
|
||||
CheckboxT *c1 = NULL;
|
||||
RadioT *r1a = NULL;
|
||||
RadioT *r2a = NULL;
|
||||
RadioT *r3a = NULL;
|
||||
RadioT *r1b = NULL;
|
||||
RadioT *r2b = NULL;
|
||||
RadioT *r3b = NULL;
|
||||
PictureT *p1 = NULL;
|
||||
FrameT *f1 = NULL;
|
||||
TextboxT *tb1 = NULL;
|
||||
TextboxT *tb2 = NULL;
|
||||
UpdownT *u1 = NULL;
|
||||
ListboxT *lb1 = NULL;
|
||||
|
||||
(void)data;
|
||||
|
||||
TagItemT ui[] = {
|
||||
T_START,
|
||||
|
||||
T_WINDOW, O(w1),
|
||||
T_TITLE, P("Window 1"),
|
||||
T_X, 300, T_Y, 25, T_WIDTH, 300, T_HEIGHT, 200,
|
||||
T_PICTURE, O(p1),
|
||||
T_X, 0, T_Y, 0,
|
||||
T_FILENAME, P("kanga.png"),
|
||||
T_PICTURE, T_DONE,
|
||||
T_LISTBOX, O(lb1),
|
||||
T_TITLE, P("Listbox"),
|
||||
T_X, 155, T_Y, 10, T_WIDTH, 120, T_HEIGHT, 140,
|
||||
T_ITEM, P("One"),
|
||||
T_ITEM, P("Two"),
|
||||
T_ITEM, P("Three"),
|
||||
T_ITEM, P("Four"),
|
||||
T_ITEM, P("Five"),
|
||||
T_ITEM, P("Six"),
|
||||
T_ITEM, P("Seven"),
|
||||
T_ITEM, P("Eight"),
|
||||
T_ITEM, P("Nine"),
|
||||
T_ITEM, P("Ten"),
|
||||
T_STEP, 3,
|
||||
T_LISTBOX, T_DONE,
|
||||
T_WINDOW, T_DONE,
|
||||
|
||||
T_WINDOW, O(w2),
|
||||
T_TITLE, P("Window 2"),
|
||||
T_X, 150, T_Y, 150, T_WIDTH, 300, T_HEIGHT, 200,
|
||||
T_RADIOBUTTON, O(r1a),
|
||||
T_TITLE, P("Radio 1a"),
|
||||
T_X, 10, T_Y, 10,
|
||||
T_GROUP, 1,
|
||||
T_SELECTED, 1,
|
||||
T_RADIOBUTTON, T_DONE,
|
||||
T_RADIOBUTTON, O(r2a),
|
||||
T_TITLE, P("Radio 2a"),
|
||||
T_X, 20 + 80, T_Y, 10,
|
||||
T_GROUP, 1,
|
||||
T_RADIOBUTTON, T_DONE,
|
||||
T_RADIOBUTTON, O(r3a),
|
||||
T_TITLE, P("Radio 3a"),
|
||||
T_X, 30 + 80 * 2, T_Y, 10,
|
||||
T_GROUP, 1,
|
||||
T_RADIOBUTTON, T_DONE,
|
||||
T_RADIOBUTTON, O(r1b),
|
||||
T_TITLE, P("Radio 1b"),
|
||||
T_X, 10, T_Y, 35,
|
||||
T_GROUP, 2,
|
||||
T_RADIOBUTTON, T_DONE,
|
||||
T_RADIOBUTTON, O(r2b),
|
||||
T_TITLE, P("Radio 2b"),
|
||||
T_X, 20 + 80, T_Y, 35,
|
||||
T_GROUP, 2,
|
||||
T_SELECTED, 1,
|
||||
T_RADIOBUTTON, T_DONE,
|
||||
T_RADIOBUTTON, O(r3b),
|
||||
T_TITLE, P("Radio 3b"),
|
||||
T_X, 30 + 80 * 2, T_Y, 35,
|
||||
T_GROUP, 2,
|
||||
T_RADIOBUTTON, T_DONE,
|
||||
T_TEXTBOX, O(tb1),
|
||||
T_TITLE, P("Test Textbox"),
|
||||
T_X, 10, T_Y, 60, T_WIDTH, 265,
|
||||
T_VALUE, P("Really long text string to edit!"),
|
||||
T_TEXTBOX, T_DONE,
|
||||
T_TEXTBOX, O(tb2),
|
||||
T_TITLE, P("Test Textbox"),
|
||||
T_X, 10, T_Y, 85, T_WIDTH, 265,
|
||||
T_VALUE, P("Short String."),
|
||||
T_TEXTBOX, T_DONE,
|
||||
T_UPDOWN, O(u1),
|
||||
T_TITLE, P("UpDown"),
|
||||
T_X, 10, T_Y, 120,
|
||||
T_MINIMUM, 0, T_MAXIMUM, 1024, T_STEP, 5,
|
||||
T_UPDOWN, T_DONE,
|
||||
T_WINDOW, T_DONE,
|
||||
|
||||
T_WINDOW, O(w3),
|
||||
T_TITLE, P("Window 3"),
|
||||
T_X, 300, T_Y, 300, T_WIDTH, 300, T_HEIGHT, 200,
|
||||
T_FRAME, O(f1),
|
||||
T_TITLE, P("Test Frame"),
|
||||
T_X, 10, T_Y, 5, T_WIDTH, 175, T_HEIGHT, 125,
|
||||
T_BUTTON, O(b1),
|
||||
T_TITLE, P("Test Button"),
|
||||
T_X, 0, T_Y, 0,
|
||||
T_CLICK, P(buttonClick),
|
||||
T_BUTTON, T_DONE,
|
||||
T_LABEL, O(l1),
|
||||
T_TITLE, P("Test Label"),
|
||||
T_X, 10, T_Y, 40,
|
||||
T_LABEL, T_DONE,
|
||||
T_CHECKBOX, O(c1),
|
||||
T_TITLE, P("Test Checkbox"),
|
||||
T_X, 10, T_Y, 65,
|
||||
T_CHECKBOX, T_DONE,
|
||||
T_FRAME, T_DONE,
|
||||
T_WINDOW, T_DONE,
|
||||
|
||||
T_WINDOW, O(w4),
|
||||
T_TITLE, P("Terminal"),
|
||||
T_X, 10, T_Y, 10, T_WIDTH, 7 + 8 + (80 * 8), T_HEIGHT, 26 + 8 + (24 * 14),
|
||||
T_TERMINAL, O(t1),
|
||||
T_X, 0, T_Y, 0, T_WIDTH, 80, T_HEIGHT, 24,
|
||||
T_TERMINAL, T_DONE,
|
||||
T_WINDOW, T_DONE,
|
||||
|
||||
T_END
|
||||
};
|
||||
|
||||
tagListRun(ui);
|
||||
|
||||
taskCreate(testTerminal, "terminalTest");
|
||||
}
|
||||
|
||||
|
||||
static void terminalTest(void *data) {
|
||||
static void testTerminal(void *data) {
|
||||
FILE *in = NULL;
|
||||
char *buffer = NULL;
|
||||
uint16_t length = 0;
|
||||
|
@ -317,7 +463,7 @@ int main(int argc, char *argv[]) {
|
|||
guiStartup();
|
||||
taskStartup();
|
||||
|
||||
taskCreate(test, "test");
|
||||
taskCreate(testTagList, "testTagList");
|
||||
taskCreate(mainLoop, "mainLoop");
|
||||
taskRun();
|
||||
|
||||
|
|
|
@ -18,5 +18,7 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "array.h"
|
||||
|
||||
#define STB_DS_IMPLEMENTATION
|
||||
#include "stb_ds.h"
|
||||
|
|
|
@ -34,11 +34,15 @@
|
|||
|
||||
#ifdef __linux__
|
||||
|
||||
#define BITS64
|
||||
|
||||
// Linux DOS replacements.
|
||||
long biostime(int cmd, long newtime);
|
||||
|
||||
#else
|
||||
|
||||
#define BITS32
|
||||
|
||||
// DOS includes.
|
||||
#include <dos.h>
|
||||
#include <dpmi.h>
|
||||
|
|
383
client/src/system/taglist.c
Normal file
383
client/src/system/taglist.c
Normal file
|
@ -0,0 +1,383 @@
|
|||
/*
|
||||
* Kangaroo Punch MultiPlayer Game Server Mark II
|
||||
* Copyright (C) 2020-2021 Scott Duensing
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "taglist.h"
|
||||
|
||||
#include "gui.h"
|
||||
#include "widget.h"
|
||||
|
||||
#include "button.h"
|
||||
#include "checkbox.h"
|
||||
#include "frame.h"
|
||||
#include "label.h"
|
||||
#include "listbox.h"
|
||||
#include "picture.h"
|
||||
#include "radio.h"
|
||||
#include "terminal.h"
|
||||
#include "textbox.h"
|
||||
#include "updown.h"
|
||||
#include "window.h"
|
||||
|
||||
|
||||
typedef struct WidgetItemS {
|
||||
TagItemT type;
|
||||
WidgetT **widget;
|
||||
WidgetT **parent;
|
||||
TagItemT *tagList;
|
||||
} WidgetItemT;
|
||||
|
||||
|
||||
static WidgetItemT **_widgetList = NULL;
|
||||
|
||||
|
||||
static void tagListWidgetAttributeHandle(void);
|
||||
static uint32_t tagListWidgetHandle(TagItemT *list, uint32_t index, WidgetT **parent);
|
||||
|
||||
|
||||
uint8_t tagListRun(TagItemT *list) {
|
||||
|
||||
uint32_t index = 1;
|
||||
|
||||
// Is this a list? Lame check.
|
||||
if (list[0] != T_START) return 1;
|
||||
|
||||
// Process until we hit the end of the list.
|
||||
while (list[index] != T_END) {
|
||||
|
||||
// Is this a widget?
|
||||
if (list[index] > T_META_START_OF_WIDGETS && list[index] < T_META_END_OF_WIDGETS) {
|
||||
index = tagListWidgetHandle(list, index, NULL);
|
||||
tagListWidgetAttributeHandle();
|
||||
}
|
||||
|
||||
} // while
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void tagListWidgetAttributeHandle(void) {
|
||||
WidgetItemT *w;
|
||||
TagItemT t;
|
||||
TagItemT v;
|
||||
uint32_t i;
|
||||
uint32_t j;
|
||||
WidgetT *widget;
|
||||
WidgetT *parent;
|
||||
char *title;
|
||||
char *filename;
|
||||
RectT pos;
|
||||
widgetCallback click;
|
||||
void *userdata;
|
||||
int32_t valueInt;
|
||||
char *valueString;
|
||||
uint8_t hasValue;
|
||||
ColorT colorActive;
|
||||
ColorT colorForeground;
|
||||
ColorT colorBackground;
|
||||
uint8_t hasColorActive;
|
||||
uint8_t hasColorForeground;
|
||||
uint8_t hasColorBackground;
|
||||
int8_t selected;
|
||||
uint32_t group;
|
||||
int32_t length;
|
||||
int32_t maximum;
|
||||
int32_t minimum;
|
||||
int32_t step;
|
||||
char **items;
|
||||
uint32_t indexAttribute;
|
||||
uint8_t hasIndex;
|
||||
|
||||
// Process generated lists in reverse.
|
||||
while (arrlen(_widgetList) > 0) {
|
||||
w = arrpop(_widgetList);
|
||||
|
||||
// Reset all attributes for this widget.
|
||||
title = NULL;
|
||||
filename = NULL;
|
||||
pos.x = 0;
|
||||
pos.y = 0;
|
||||
pos.w = 0;
|
||||
pos.h = 0;
|
||||
click = NULL;
|
||||
userdata = NULL;
|
||||
hasValue = 0;
|
||||
valueInt = 0;
|
||||
valueString = NULL;
|
||||
colorActive = 0;
|
||||
colorBackground = 0;
|
||||
colorForeground = 0;
|
||||
hasColorActive = 0;
|
||||
hasColorBackground = 0;
|
||||
hasColorForeground = 0;
|
||||
selected = -1;
|
||||
group = 0;
|
||||
length = -1;
|
||||
minimum = 0;
|
||||
maximum = 255;
|
||||
step = 10;
|
||||
items = NULL;
|
||||
indexAttribute = 0;
|
||||
hasIndex = 0;
|
||||
|
||||
// Parse provided attributes.
|
||||
for (i=0; i<arrlen(w->tagList); i+=2) {
|
||||
t = w->tagList[i];
|
||||
v = w->tagList[i + 1];
|
||||
|
||||
switch (t) {
|
||||
|
||||
case T_COLOR_ACTIVE:
|
||||
colorActive = (ColorT)v;
|
||||
hasColorActive = 1;
|
||||
break;
|
||||
|
||||
case T_COLOR_BACKGROUND:
|
||||
colorBackground = (ColorT)v;
|
||||
hasColorBackground = 1;
|
||||
break;
|
||||
|
||||
case T_COLOR_FOREGROUND:
|
||||
colorForeground = (ColorT)v;
|
||||
hasColorForeground = 1;
|
||||
break;
|
||||
|
||||
case T_CLICK:
|
||||
click = (widgetCallback)v;
|
||||
break;
|
||||
|
||||
case T_FILENAME:
|
||||
filename = (char *)v;
|
||||
break;
|
||||
|
||||
case T_GROUP:
|
||||
group = v;
|
||||
break;
|
||||
|
||||
case T_HEIGHT:
|
||||
pos.h = v;
|
||||
break;
|
||||
|
||||
case T_INDEX:
|
||||
indexAttribute = v;
|
||||
hasIndex = 1;
|
||||
break;
|
||||
|
||||
case T_ITEM:
|
||||
arrput(items, (char *)v);
|
||||
break;
|
||||
|
||||
case T_LENGTH:
|
||||
length = v;
|
||||
break;
|
||||
|
||||
case T_MAXIMUM:
|
||||
maximum = v;
|
||||
break;
|
||||
|
||||
case T_MINIMUM:
|
||||
minimum = v;
|
||||
break;
|
||||
|
||||
case T_SELECTED:
|
||||
selected = (v != 0 ? 1 : 0);
|
||||
break;
|
||||
|
||||
case T_STEP:
|
||||
step = v;
|
||||
break;
|
||||
|
||||
case T_TITLE:
|
||||
title = (char *)v;
|
||||
break;
|
||||
|
||||
case T_USER_DATA:
|
||||
userdata = (void *)v;
|
||||
break;
|
||||
|
||||
case T_VALUE:
|
||||
valueInt = v;
|
||||
valueString = (void *)v;
|
||||
hasValue = 1;
|
||||
break;
|
||||
|
||||
case T_WIDTH:
|
||||
pos.w = v;
|
||||
break;
|
||||
|
||||
case T_X:
|
||||
pos.x = v;
|
||||
break;
|
||||
|
||||
case T_Y:
|
||||
pos.y = v;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Clear taglist after processing.
|
||||
while (arrlen(w->tagList) > 0) {
|
||||
arrpop(w->tagList);
|
||||
}
|
||||
arrfree(w->tagList);
|
||||
|
||||
// Find our widget object and parent.
|
||||
widget = *w->widget;
|
||||
if (w->parent == NULL) {
|
||||
parent = NULL;
|
||||
} else {
|
||||
parent = *w->parent;
|
||||
}
|
||||
|
||||
// Create the widget.
|
||||
switch (w->type) {
|
||||
|
||||
case T_BUTTON:
|
||||
widget = W(buttonNew(pos.x, pos.y, title, click));
|
||||
break;
|
||||
|
||||
case T_CHECKBOX:
|
||||
widget = W(checkboxNew(pos.x, pos.y, title));
|
||||
if (hasValue) checkboxValueSet((CheckboxT *)widget, valueInt);
|
||||
if (selected >= 0) checkboxValueSet((CheckboxT *)widget, selected);
|
||||
break;
|
||||
|
||||
case T_FRAME:
|
||||
widget = W(frameNew(pos.x, pos.y, pos.w, pos.h, title));
|
||||
break;
|
||||
|
||||
case T_LABEL:
|
||||
widget = W(labelNew(pos.x, pos.y, title));
|
||||
if (hasColorActive) labelColorActiveSet((LabelT *)widget, colorActive);
|
||||
if (hasColorBackground) labelColorBackgroundSet((LabelT *)widget, colorBackground);
|
||||
if (hasColorForeground) labelColorForegroundSet((LabelT *)widget, colorForeground);
|
||||
if (click != NULL) labelClickHandlerSet((LabelT *)widget, click);
|
||||
break;
|
||||
|
||||
case T_LISTBOX:
|
||||
widget = W(listboxNew(pos.x, pos.y, pos.w, pos.h, title));
|
||||
listboxStepSet((ListboxT *)widget, step);
|
||||
for (j=0; j<arrlen(items); j++) {
|
||||
listboxItemAdd((ListboxT *)widget, items[j]);
|
||||
}
|
||||
if (hasValue) listboxValueSet((ListboxT *)widget, valueString);
|
||||
if (hasIndex) listboxIndexSet((ListboxT *)widget, indexAttribute);
|
||||
break;
|
||||
|
||||
case T_PICTURE:
|
||||
widget = W(pictureNew(pos.x, pos.y, filename));
|
||||
if (click != NULL) pictureClickHandlerSet((PictureT *)widget, click);
|
||||
break;
|
||||
|
||||
case T_RADIOBUTTON:
|
||||
widget = W(radioNew(pos.x, pos.y, title, group));
|
||||
if (hasValue && valueInt != 0) radioSelectedSet((RadioT *)widget);
|
||||
if (selected == 1) radioSelectedSet((RadioT *)widget);
|
||||
break;
|
||||
|
||||
case T_TERMINAL:
|
||||
widget = W(terminalNew(pos.x, pos.y, pos.w, pos.h));
|
||||
if (hasColorBackground) terminalBackgroundSet((TerminalT *)widget, colorBackground);
|
||||
if (hasColorForeground) terminalForegroundSet((TerminalT *)widget, colorForeground);
|
||||
if (hasColorBackground || hasColorForeground) terminalScreenClear((TerminalT *)widget);
|
||||
break;
|
||||
|
||||
case T_TEXTBOX:
|
||||
widget = W(textboxNew(pos.x, pos.y, pos.w, title));
|
||||
textboxValueSet((TextboxT *)widget, valueString);
|
||||
if (length > 0) textboxLengthMaxSet((TextboxT *)widget, length);
|
||||
break;
|
||||
|
||||
case T_UPDOWN:
|
||||
widget = W(updownNew(pos.x, pos.y, minimum, maximum, step, title));
|
||||
if (hasValue) updownValueSet((UpdownT *)widget, valueInt);
|
||||
break;
|
||||
|
||||
case T_WINDOW:
|
||||
widget = W(windowNew(pos.x, pos.y, pos.w, pos.h, title));
|
||||
break;
|
||||
}
|
||||
|
||||
guiUserDataSet(widget, userdata);
|
||||
|
||||
// Store everything we did.
|
||||
*w->widget = widget;
|
||||
|
||||
// Attach it.
|
||||
if (parent == NULL) {
|
||||
guiAttach(guiRootGet(), widget);
|
||||
} else {
|
||||
guiAttach(parent, widget);
|
||||
}
|
||||
|
||||
// If we allocated items, release them.
|
||||
if (items != NULL) {
|
||||
arrfree(items);
|
||||
items = NULL;
|
||||
}
|
||||
|
||||
// Free this widget list.
|
||||
free(w);
|
||||
}
|
||||
|
||||
arrfree(_widgetList);
|
||||
_widgetList = NULL;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t tagListWidgetHandle(TagItemT *list, uint32_t index, WidgetT **parent) {
|
||||
TagItemT widgetType = 0;
|
||||
WidgetItemT *wi = (WidgetItemT *)malloc(sizeof(WidgetItemT));
|
||||
|
||||
// Lists at this point consist of:
|
||||
// WidgetType, WidgetObjectPointer, WidgetAttributeTag, WidgetAttributeValue, WidgetAttributeTag, WidgetAttributeValue, ..., WidgetType, T_END, ...
|
||||
|
||||
widgetType = list[index++];
|
||||
wi->type = widgetType; // Save widget type.
|
||||
wi->widget = (WidgetT **)list[index++]; // Save widget object pointer.
|
||||
wi->parent = parent; // Save parent widget.
|
||||
wi->tagList = NULL; // Prepare widget tag item array.
|
||||
|
||||
while (1) {
|
||||
|
||||
// End of widget definition?
|
||||
if (list[index] == widgetType && list[index+1] == T_DONE) {
|
||||
// Skip over widget T_END tag pair.
|
||||
index += 2;
|
||||
// Save this widget data.
|
||||
arrput(_widgetList, wi);
|
||||
break;
|
||||
}
|
||||
|
||||
// Start of nested widget?
|
||||
if (list[index] > T_META_START_OF_WIDGETS && list[index] < T_META_END_OF_WIDGETS) {
|
||||
index = tagListWidgetHandle(list, index, wi->widget);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Save this tag item pair for later.
|
||||
arrput(wi->tagList, list[index++]);
|
||||
arrput(wi->tagList, list[index++]);
|
||||
|
||||
} // while
|
||||
|
||||
return index;
|
||||
}
|
88
client/src/system/taglist.h
Normal file
88
client/src/system/taglist.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Kangaroo Punch MultiPlayer Game Server Mark II
|
||||
* Copyright (C) 2020-2021 Scott Duensing
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TAGLIST_H
|
||||
#define TAGLIST_H
|
||||
|
||||
|
||||
#include "os.h"
|
||||
|
||||
|
||||
#ifdef BITS64
|
||||
typedef uint64_t TagItemT;
|
||||
#else
|
||||
typedef uint32_t TagItemT;
|
||||
#endif
|
||||
|
||||
#define O(x) ((TagItemT)&x) // Widget Objects
|
||||
#define P(x) ((TagItemT)x) // Pointers
|
||||
|
||||
|
||||
enum TagItemsE {
|
||||
T_END = 0,
|
||||
T_START,
|
||||
T_DONE,
|
||||
|
||||
T_META_START_OF_WIDGETS,
|
||||
|
||||
T_BUTTON, // 4
|
||||
T_CHECKBOX,
|
||||
T_FRAME,
|
||||
T_LABEL,
|
||||
T_LISTBOX,
|
||||
T_PICTURE,
|
||||
T_RADIOBUTTON,
|
||||
T_TERMINAL,
|
||||
T_TEXTBOX,
|
||||
T_UPDOWN,
|
||||
T_WINDOW,
|
||||
|
||||
T_META_END_OF_WIDGETS,
|
||||
T_META_START_OF_ATTRIBUTES,
|
||||
|
||||
T_CLICK, // 17
|
||||
T_COLOR_ACTIVE,
|
||||
T_COLOR_BACKGROUND,
|
||||
T_COLOR_FOREGROUND,
|
||||
T_FILENAME,
|
||||
T_GROUP,
|
||||
T_HEIGHT,
|
||||
T_INDEX,
|
||||
T_ITEM,
|
||||
T_LENGTH,
|
||||
T_MAXIMUM,
|
||||
T_MINIMUM,
|
||||
T_SELECTED,
|
||||
T_STEP,
|
||||
T_TITLE,
|
||||
T_USER_DATA,
|
||||
T_VALUE,
|
||||
T_WIDTH,
|
||||
T_X,
|
||||
T_Y,
|
||||
|
||||
T_META_END_OF_ATTRIBUTES
|
||||
};
|
||||
|
||||
|
||||
uint8_t tagListRun(TagItemT *list);
|
||||
|
||||
|
||||
#endif // TAGLIST_H
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#define MINICORO_IMPL
|
||||
#define MCO_USE_ASM
|
||||
//#define MCO_DEFAULT_STACK_SIZE 114688 // Default is 57344
|
||||
#include "minicoro/minicoro.h"
|
||||
|
||||
|
||||
|
@ -95,7 +96,7 @@ void taskRun(void) {
|
|||
|
||||
} // while tasks exist
|
||||
|
||||
//arrfree(_taskList);
|
||||
arrfree(_taskList);
|
||||
_taskList = NULL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue