188 lines
4.3 KiB
C
188 lines
4.3 KiB
C
#include "mgos.h"
|
|
#include "widget.h"
|
|
#include "frozen/frozen.h"
|
|
#include "common/queue.h"
|
|
|
|
static void widget_event_timer(void *arg) {
|
|
struct widget_t *widget = (struct widget_t *) arg;
|
|
if (!widget)
|
|
return;
|
|
if (widget->handler)
|
|
widget->handler(EV_WIDGET_TIMER, widget, NULL);
|
|
}
|
|
|
|
void widget_destroy(struct widget_t **widget) {
|
|
if (!*widget)
|
|
return;
|
|
if ((*widget)->handler)
|
|
(*widget)->handler(EV_WIDGET_DESTROY, *widget, NULL);
|
|
|
|
if ((*widget)->_timer_id)
|
|
mgos_clear_timer((*widget)->_timer_id);
|
|
|
|
if ((*widget)->user_data)
|
|
free((*widget)->user_data);
|
|
|
|
if ((*widget)->name)
|
|
free((*widget)->name);
|
|
|
|
if ((*widget)->label)
|
|
free((*widget)->label);
|
|
|
|
if ((*widget)->img)
|
|
free((*widget)->img);
|
|
|
|
free(*widget);
|
|
*widget=NULL;
|
|
}
|
|
|
|
struct widget_t *widget_create(char *name, uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
|
|
struct widget_t *widget;
|
|
|
|
widget = (struct widget_t *) calloc(1, sizeof(*widget));
|
|
if (!widget)
|
|
return NULL;
|
|
|
|
widget->name=strdup(name);
|
|
widget->x=x;
|
|
widget->y=y;
|
|
widget->w=w;
|
|
widget->h=h;
|
|
|
|
widget->type=WIDGET_TYPE_NONE;
|
|
widget->label=NULL;
|
|
widget->img=NULL;
|
|
widget->user_data = NULL;
|
|
widget->handler = NULL;
|
|
widget->timer_msec = 0;
|
|
widget->_timer_id = 0;
|
|
widget->create_called = false;
|
|
|
|
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 *name = NULL;
|
|
char *label = NULL;
|
|
char *img = NULL;
|
|
char *screen = NULL;
|
|
|
|
if (json_scanf(json, strlen(json), "{name:%Q,x:%d,y:%d,w:%d,h:%d}", &name, &x, &y, &w, &h) != 5) {
|
|
LOG(LL_ERROR, ("Incomplete JSON: require 'x', 'y', 'w', 'h' and 'name' fields"));
|
|
return NULL;
|
|
}
|
|
widget = widget_create(name, x, y, w, h);
|
|
free(name);
|
|
|
|
json_scanf(json, strlen(json), "{type:%d,label:%Q,img:%Q}", &type, &label, &img);
|
|
widget->type=type;
|
|
widget->label=label;
|
|
widget->img=img;
|
|
|
|
// Load widget-specific attributes
|
|
if (type == WIDGET_TYPE_LOADSCREEN) {
|
|
if (json_scanf(json, strlen(json), "{screen:%Q}", &screen) != 1) {
|
|
LOG(LL_WARN, ("Widget '%s' is of type LOADSCREEN but does not have attribute 'screen'", widget->name));
|
|
} else {
|
|
if (widget->user_data) free(widget->user_data);
|
|
widget->user_data = screen;
|
|
}
|
|
} else if (type == WIDGET_TYPE_MQTT_BUTTON) {
|
|
char *mqtt = NULL;
|
|
if (json_scanf(json, strlen(json), "{mqtt:%Q}", &mqtt) != 1) {
|
|
LOG(LL_WARN, ("Widget '%s' is of type MQTT_BUTTON but does not have attribute 'mqtt'", widget->name));
|
|
} else {
|
|
if (widget->user_data) free(widget->user_data);
|
|
widget->user_data=mqtt;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void widget_set_handler(struct widget_t *w, widget_event_fn handler) {
|
|
if (!w)
|
|
return;
|
|
w->handler = handler;
|
|
if (!w->create_called && w->handler)
|
|
handler(EV_WIDGET_CREATE, w, NULL);
|
|
|
|
return;
|
|
}
|
|
|
|
void widget_delete_handler(struct widget_t *w) {
|
|
if (!w)
|
|
return;
|
|
w->handler = NULL;
|
|
return;
|
|
}
|
|
|
|
void widget_set_timer(struct widget_t *w, uint32_t timer_msec) {
|
|
if (!w)
|
|
return;
|
|
if (w->_timer_id)
|
|
mgos_clear_timer(w->_timer_id);
|
|
|
|
w->timer_msec=timer_msec;
|
|
if (timer_msec == 0)
|
|
w->_timer_id = 0;
|
|
else
|
|
w->_timer_id = mgos_set_timer(timer_msec, MGOS_TIMER_REPEAT, widget_event_timer, w);
|
|
|
|
return;
|
|
}
|
|
|
|
void widget_delete_timer(struct widget_t *w) {
|
|
if (!w)
|
|
return;
|
|
|
|
widget_set_timer(w, 0);
|
|
return;
|
|
}
|
|
|
|
void widget_ev_to_str(int ev, char *s, int slen) {
|
|
switch(ev) {
|
|
case EV_WIDGET_CREATE:
|
|
strncpy(s, "CREATE", slen);
|
|
break;
|
|
case EV_WIDGET_DRAW:
|
|
strncpy(s, "DRAW", slen);
|
|
break;
|
|
case EV_WIDGET_REDRAW:
|
|
strncpy(s, "REDRAW", slen);
|
|
break;
|
|
case EV_WIDGET_TIMER:
|
|
strncpy(s, "TIMER", slen);
|
|
break;
|
|
case EV_WIDGET_TOUCH_UP:
|
|
strncpy(s, "TOUCH_UP", slen);
|
|
break;
|
|
case EV_WIDGET_TOUCH_DOWN:
|
|
strncpy(s, "TOUCH_DOWN", slen);
|
|
break;
|
|
case EV_WIDGET_DESTROY:
|
|
strncpy(s, "DESTROY", slen);
|
|
break;
|
|
default: // EV_WIDGET_NONE
|
|
snprintf(s, slen, "EV%d", ev);
|
|
break;
|
|
}
|
|
}
|