Add screen.[ch] and unit tests

This commit is contained in:
Pim van Pelt
2017-11-26 14:18:43 +01:00
parent 79bb900def
commit 3e2e9d4e5b
11 changed files with 344 additions and 46 deletions

121
src/screen.c Normal file
View File

@ -0,0 +1,121 @@
#include "screen.h"
struct screen_t *screen_create(char *name, uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
struct screen_t *screen = NULL;
screen = (struct screen_t *) calloc(1, sizeof(*screen));
if (!screen)
return NULL;
screen->x=x;
screen->y=y;
screen->w=w;
screen->h=h;
if (name)
screen->name=strdup(name);
SLIST_INIT(&screen->widget_entries);
return screen;
}
struct screen_t *screen_create_from_file(char *fn) {
char *json;
void *h = NULL;
// struct json_token key;
struct json_token val;
int idx;
struct screen_t *screen = NULL;
struct widget_t *widget = NULL;
int screen_x, screen_y, screen_w, screen_h;
char *screen_name = NULL;
json = json_fread(fn);
if (!json) {
LOG(LL_ERROR, ("Could not read file %s", fn));
goto exit;
}
if (json_scanf(json, strlen(json), "{x:%d,y:%d,w:%d,h:%d,name:%Q}", &screen_x, &screen_y, &screen_w, &screen_h, &screen_name) != 5) {
LOG(LL_ERROR, ("%s: Incomplete JSON: require 'x', 'y', 'w', 'h' and 'name' fields", fn));
screen=NULL; goto exit;
}
screen = screen_create(screen_name, screen_x, screen_y, screen_w, screen_h);
/*
// Traverse Object
while ((h = json_next_key(json, strlen(json), h, ".", &key, &val)) != NULL) {
printf("[%.*s] -> [%.*s]\n", key.len, key.ptr, val.len, val.ptr);
}
*/
// Traverse Array
while ((h = json_next_elem(json, strlen(json), h, ".widgets", &idx, &val)) != NULL) {
// printf("[%d]: [%.*s]\n", idx, val.len, val.ptr);
if (val.len>0 && val.ptr) {
widget = widget_create_from_json(val.ptr);
if (!screen_widget_add(screen, widget)) {
LOG(LL_ERROR, ("Could not add widget to screen"));
}
}
}
exit:
if (json) free(json);
if (screen_name) free(screen_name);
return screen;
}
void screen_destroy(struct screen_t **s) {
free(*s);
if ((*s)->name) free ((*s)->name);
*s = NULL;
}
bool screen_widget_add(struct screen_t *s, struct widget_t *w) {
struct widget_list_t *wl;
wl = (struct widget_list_t *) calloc(1, sizeof(*wl));
if (!wl) {
return false;
}
wl->widget = w;
SLIST_INSERT_HEAD(&s->widget_entries, wl, entries);
return true;
}
struct widget_t *screen_widget_add_from_file(struct screen_t *s, char *fn) {
struct widget_t *w;
w = widget_create_from_file(fn);
if (!w)
return NULL;
screen_widget_add(s, w);
return w;
}
bool screen_widget_destroy(struct screen_t *s, struct widget_t **w) {
struct widget_list_t *wl;
if (!s)
return false;
SLIST_FOREACH(wl, &s->widget_entries, entries) {
if (wl->widget == *w) {
SLIST_REMOVE(&s->widget_entries, wl, widget_list_t, entries);
widget_destroy(w);
}
}
return true;
}
uint16_t screen_get_num_widgets(struct screen_t *s) {
struct widget_list_t *wl;
uint16_t num = 0;
if (!s)
return 0;
SLIST_FOREACH(wl, &s->widget_entries, entries)
num++;
return num;
}

View File

@ -3,11 +3,6 @@
#include "frozen/frozen.h"
#include "common/queue.h"
struct widget_list_t {
struct widget_t *widget;
SLIST_ENTRY(widget_list_t) entries;
};
SLIST_HEAD(widget_list, widget_list_t) s_widgets;
static void widget_event_timer(void *arg) {
@ -18,46 +13,38 @@ static void widget_event_timer(void *arg) {
widget->handler(EV_WIDGET_TIMER, widget, NULL);
}
static void widget_destroy(struct widget_t *widget) {
if (!widget)
void widget_destroy(struct widget_t **widget) {
if (!*widget)
return;
if (widget->handler)
widget->handler(EV_WIDGET_DESTROY, widget, NULL);
if ((*widget)->handler)
(*widget)->handler(EV_WIDGET_DESTROY, *widget, NULL);
if (widget->timer_msec)
mgos_clear_timer(widget->_timer_id);
if (widget->user_data)
free(widget->user_data);
free(widget);
if ((*widget)->timer_msec)
mgos_clear_timer((*widget)->_timer_id);
if ((*widget)->user_data)
free((*widget)->user_data);
free(*widget);
*widget=NULL;
}
struct widget_t *widget_add(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t timer_msec, widget_event_fn handler, void *user_data) {
struct widget_t *widget;
struct widget_list_t *wl;
widget = (struct widget_t *) calloc(1, sizeof(*widget));
if (!widget)
return NULL;
widget->x=x;
widget->y=y;
widget->w=w;
widget->h=h;
widget->timer_msec=timer_msec;
widget->handler=handler;
widget->user_data=user_data;
if (timer_msec > 0)
widget->_timer_id = mgos_set_timer(timer_msec, MGOS_TIMER_REPEAT, widget_event_timer, widget);
wl = (struct widget_list_t *) calloc(1, sizeof(*wl));
if (!wl) {
widget_destroy(widget);
return NULL;
}
widget = widget_create(x, y, w, h, timer_msec, handler, user_data);
if (!widget) {
free(wl);
return NULL;
}
wl->widget = widget;
SLIST_INSERT_HEAD(&s_widgets, wl, entries);
if (handler)
handler(EV_WIDGET_CREATE, widget, NULL);
return widget;
}
@ -82,7 +69,7 @@ void widget_remove(struct widget_t *widget) {
SLIST_FOREACH(wl, &s_widgets, entries) {
if (wl->widget == widget) {
SLIST_REMOVE(&s_widgets, wl, widget_list_t, entries);
widget_destroy(widget);
widget_destroy(&widget);
}
}
}
@ -119,3 +106,55 @@ exit:
(void) handler;
(void) user_data;
}
struct widget_t *widget_create(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t timer_msec, widget_event_fn handler, void *user_data) {
struct widget_t *widget;
widget = (struct widget_t *) calloc(1, sizeof(*widget));
if (!widget)
return NULL;
widget->x=x;
widget->y=y;
widget->w=w;
widget->h=h;
widget->timer_msec=timer_msec;
widget->handler=handler;
widget->user_data=user_data;
if (timer_msec > 0)
widget->_timer_id = mgos_set_timer(timer_msec, MGOS_TIMER_REPEAT, widget_event_timer, widget);
if (handler)
handler(EV_WIDGET_CREATE, widget, NULL);
return widget;
}
struct widget_t *widget_create_from_json(const char *json) {
struct widget_t *widget=NULL;
int x, y, w, h;
int type = 0;
char *label = NULL;
char *icon = NULL;
if (json_scanf(json, strlen(json), "{x:%d,y:%d,w:%d,h:%d}", &x, &y, &w, &h) != 4) {
LOG(LL_ERROR, ("Incomplete JSON: require 'x', 'y', 'w', 'h' fields"));
return NULL;
}
json_scanf(json, strlen(json), "{type:%d,label:%Q,icon:%Q}", &type, &label, &icon);
widget = widget_create(x, y, w, h, 0, NULL, NULL);
return widget;
}
struct widget_t *widget_create_from_file(const char *fn) {
char *json;
struct widget_t *widget=NULL;
if (!(json = json_fread(fn))) {
LOG(LL_ERROR, ("%s: Could not json_fread()", fn));
return NULL;
}
widget = widget_create_from_json(json);
free(json);
return widget;
}