first version of the generic gui for the tracer

This commit is contained in:
Cedric Roux
2016-04-11 11:18:26 +02:00
parent ee6789cdde
commit 2bb04f0105
18 changed files with 1737 additions and 1 deletions
+216
View File
@@ -0,0 +1,216 @@
#include "gui.h"
#include "gui_defs.h"
#include "x.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
static void default_repack(gui *gui, widget *_this);
static void default_allocate(
gui *gui, widget *_this, int x, int y, int width, int height);
static void default_add_child(
gui *_gui, widget *_this, widget *child, int position);
static void default_hints(gui *g, widget *this, int *width, int *height);
static void toplevel_list_append(struct gui *g, struct widget *e)
{
struct widget_list *new;
new = calloc(1, sizeof(struct widget_list));
if (new == NULL) OOM;
new->item = e;
if (g->toplevel == NULL) {
g->toplevel = new;
new->last = new;
return;
}
g->toplevel->last->next = new;
g->toplevel->last = new;
}
widget *new_widget(struct gui *g, enum widget_type type, int size)
{
struct widget *ret;
//glock(g);
ret = calloc(1, size);
if (ret == NULL) OOM;
ret->repack = default_repack;
ret->add_child = default_add_child;
ret->allocate = default_allocate;
ret->hints = default_hints;
/* there is no default paint, on purpose */
ret->type = type;
ret->id = g->next_id;
g->next_id++;
ret->width = 0;
ret->height = 0;
/* add toplevel windows to g->toplevel */
if (type == TOPLEVEL_WINDOW)
toplevel_list_append(g, ret);
//gunlock(g);
return ret;
}
/*************************************************************************/
/* internal functions */
/*************************************************************************/
void widget_add_child_internal(
gui *_gui, widget *parent, widget *child, int position)
{
struct widget *p = parent;
struct widget *c = child;
struct widget_list *new;
struct widget_list *prev, *cur;
int i;
new = calloc(1, sizeof(struct widget_list));
if (new == NULL) OOM;
new->item = c;
c->parent = p;
prev = NULL;
cur = p->children;
for (i = 0; position < 0 || i < position; i++) {
if (cur == NULL) break;
prev = cur;
cur = cur->next;
}
/* TODO: warn/err if i != position+1? */
if (prev == NULL) {
/* new is at head */
new->next = p->children;
if (p->children != NULL) new->last = p->children->last;
else new->last = new;
p->children = new;
goto repack;
}
if (cur == NULL) {
/* new is at tail */
prev->next = new;
p->children->last = new;
goto repack;
}
/* new is between two existing items */
prev->next = new;
new->next = cur;
repack:
send_event(_gui, REPACK, p->id);
}
/*************************************************************************/
/* default functions */
/*************************************************************************/
static void default_repack(gui *gui, widget *_this)
{
struct widget *this = _this;
return this->parent->repack(gui, this->parent);
}
static void default_add_child(
gui *_gui, widget *_this, widget *child, int position)
{
struct widget *this = _this;
WARN("cannot add child to widget %s\n", widget_name(this->type));
}
static void default_allocate(
gui *gui, widget *_this, int x, int y, int width, int height)
{
struct widget *this = _this;
this->x = x;
this->y = y;
this->width = width;
this->height = height;
}
static void default_hints(gui *g, widget *this, int *width, int *height)
{
*width = 1;
*height = 1;
}
/*************************************************************************/
/* utils functions */
/*************************************************************************/
void widget_add_child(gui *_gui, widget *parent, widget *child, int position)
{
struct widget *this = parent;
glock(_gui);
this->add_child(_gui, parent, child, position);
gunlock(_gui);
}
static const char *names[] = {
"TOPLEVEL_WINDOW", "CONTAINER", "TEXT_LIST", "XY_PLOT", "BUTTON", "LABEL"
};
const char *widget_name(enum widget_type type)
{
switch (type) {
default: break;
case TOPLEVEL_WINDOW:
case CONTAINER:
case TEXT_LIST:
case XY_PLOT:
case BUTTON:
case LABEL:
return names[type];
}
return "UNKNOWN (error)";
}
/*************************************************************************/
/* find a widget */
/*************************************************************************/
/* TODO: optimize traversal and also use a cache */
struct widget *_find_widget(struct widget *c, int id)
{
struct widget_list *l;
struct widget *ret;
if (c == NULL) return NULL;
if (c->id == id) return c;
l = c->children;
while (l) {
ret = _find_widget(l->item, id);
if (ret != NULL) return ret;
l = l->next;
}
return NULL;
}
struct widget *find_widget(struct gui *g, int id)
{
struct widget_list *l;
struct widget *ret;
l = g->toplevel;
while (l) {
ret = _find_widget(l->item, id);
if (ret != NULL) return ret;
l = l->next;
}
return NULL;
}