void GUI_SetSelected(guiObject_t *obj) { if (obj && obj != objSELECTED) { if (objSELECTED) OBJ_SET_DIRTY(objSELECTED, 1); objSELECTED = obj; if(select_notify) select_notify(obj); OBJ_SET_DIRTY(obj, 1); } }
void GUI_SetHidden(struct guiObject *obj, u8 state) { if((!!state) == (!! OBJ_IS_HIDDEN(obj))) return; OBJ_SET_HIDDEN(obj, state); OBJ_SET_DIRTY(obj, 1); }
u8 GUI_TouchKeyboard(struct guiObject *obj, struct touch *coords, s8 press_type) { struct guiKeyboard *keyboard = (struct guiKeyboard *)obj; if (coords && ! press_type && (! keyboard->lastchar || (keyboard->flags & FLAG_BUTTON))) { char c = keyboard_cmd(KB_COMPARE_AND_PRESS, keyboard, coords); keyboard->flags &= ~FLAG_BUTTON; keyboard->lastchar = c; } else if (press_type == -1 && keyboard->lastchar && ! (keyboard->flags & FLAG_BUTTON)) { //Key Release if (keyboard->lastchar == '\x06') { //DONE keyboard->lastchar = '\0'; if (keyboard->CallBack) keyboard->CallBack(obj, keyboard->cb_data); //After DONE it is possible that obj and keyboard are invalid return 1; } else if (keyboard->lastchar == '\x09') { //CAPS keyboard->flags ^= FLAG_CAPS; keyboard_cmd(KB_DRAW, keyboard, NULL); } else if (keyboard->lastchar == '\x01' || keyboard->lastchar == '\x02') { //Numpad keyboard->type = keyboard->type == KEYBOARD_ALPHA ? KEYBOARD_SPECIAL : KEYBOARD_ALPHA; OBJ_SET_DIRTY(obj, 1); } else { keyboard_cmd(KB_RELEASE, keyboard, NULL); kb_update_string(keyboard, keyboard->lastchar); } keyboard->lastchar = '\0'; } else if (press_type == 1 && keyboard->lastchar == '\x08') { //DEL Long Press erases whole string keyboard->text[0] = '\0'; _kb_draw_text(keyboard->text); } return 1; }
void GUI_SetSelectable(guiObject_t *obj, u8 selectable) { OBJ_SET_SELECTABLE(obj, selectable); if(objSELECTED == obj && ! selectable) { objSELECTED = NULL; OBJ_SET_DIRTY(obj, 1); } }
void GUI_HandleInput(int source, int value) { if(objSELECTED && objSELECTED->Type == TextSelect) { guiTextSelect_t *select = (guiTextSelect_t *)objSELECTED; if (select->InputValueCB) { select->InputValueCB(objSELECTED, source, value, select->cb_data); OBJ_SET_DIRTY(objSELECTED, 1); } } }
void GUI_ButtonEnable(struct guiObject *obj, u8 enable) { struct guiButton *button = (struct guiButton *)obj; int is_enabled = button->flags & FLAG_ENABLE; enable = enable ? FLAG_ENABLE : 0; if (enable ^ is_enabled) { button->flags = (button->flags & ~FLAG_ENABLE) | enable; OBJ_SET_DIRTY(obj, 1); } }
static unsigned press_cb(u32 button, unsigned flags, void *data) { struct guiObject *obj = (struct guiObject *)data; struct guiKeyboard *keyboard = (struct guiKeyboard *)obj; (void)data; if (flags & BUTTON_PRESS || flags & BUTTON_LONGPRESS) { if ( flags & BUTTON_LONGPRESS && CHAN_ButtonIsPressed(button, BUT_ENTER) && keyboard->lastchar == '\x08') { //DEL Long Press erases whole string keyboard->text[0] = '\0'; _kb_draw_text(keyboard->text); } else if (CHAN_ButtonIsPressed(button, BUT_EXIT)) { // allow user to press the EXT key to discard changes if (keyboard->CallBack) { if (keyboard->cb_data != NULL) { int *result = (int *) keyboard->cb_data; *result = 0; } BUTTON_UnregisterCallback(&keyboard->action); keyboard->CallBack(obj, keyboard->cb_data ); } //After DONE it is possible that obj and keyboard are invalid } else if (CHAN_ButtonIsPressed(button, BUT_RIGHT)) { navigate_item(keyboard, 1 , 0); } else if (CHAN_ButtonIsPressed(button, BUT_LEFT)) { navigate_item(keyboard, -1, 0); } else if (CHAN_ButtonIsPressed(button, BUT_UP)) { navigate_item(keyboard, 0 , -1); } else if (CHAN_ButtonIsPressed(button, BUT_DOWN)) { navigate_item(keyboard, 0, 1); } else if (CHAN_ButtonIsPressed(button, BUT_ENTER)) { if (keyboard->lastchar == '\x09') { //CAPS keyboard->flags ^= FLAG_CAPS; keyboard_cmd(KB_DRAW, keyboard, NULL); } else if (keyboard->lastchar == '\x01' || keyboard->lastchar == '\x02') { //Numpad keyboard->type = keyboard->type == KEYBOARD_ALPHA ? KEYBOARD_SPECIAL : KEYBOARD_ALPHA; OBJ_SET_DIRTY(obj, 1); } else if (keyboard->lastchar == '\x06') { //DONE if (keyboard->CallBack) { if (keyboard->cb_data != NULL) { int *result = (int *) keyboard->cb_data; if (*result <= 0) // to avoid loosing the channel number when renaming virtual channels on b/w-screens *result = 1; } BUTTON_UnregisterCallback(&keyboard->action); keyboard->CallBack(obj, keyboard->cb_data ); } //After DONE it is possible that obj and keyboard are invalid } else { kb_update_string(keyboard, keyboard->lastchar); } } return 1; } return 1; }
void GUI_DrawObjects(void) { struct guiObject *obj = objHEAD; while(obj) { if(! OBJ_IS_HIDDEN(obj)) { GUI_DrawObject(obj); } else { OBJ_SET_DIRTY(obj, 0); } obj = obj->next; } }
void GUI_HideObjects(struct guiObject *headObj, struct guiObject *modalObj) { struct guiObject *obj; //Only start drawing from headObj(scrollable) or 1st modal if either is set obj = headObj ? headObj : modalObj ? modalObj : objHEAD; while(obj) { if(OBJ_IS_HIDDEN(obj) && OBJ_IS_DIRTY(obj)) { GUI_DrawBackground(obj->box.x, obj->box.y, obj->box.width, obj->box.height); OBJ_SET_DIRTY(obj, 0); } obj = obj->next; } }
void GUI_ChangeImage(struct guiImage *image, const char *file, u16 x_off, u16 y_off) { guiObject_t *obj = (guiObject_t *)image; //Use a CRC for comparison because the filename may change without the pointer changing u32 crc = Crc(file, strlen(file)); if (image->file != file || image->crc != crc || image->x_off != x_off || image->y_off != y_off) { image->crc = crc; image->file = file; image->x_off = x_off; image->y_off = y_off; OBJ_SET_TRANSPARENT(obj, LCD_ImageIsTransparent(file)); OBJ_SET_DIRTY(obj, 1); } }
void connect_object(struct guiObject *obj) { if (objHEAD == NULL) { objHEAD = obj; } else { struct guiObject *ptr = objHEAD; while(ptr->next) ptr = ptr->next; ptr->next = obj; } OBJ_SET_USED(obj, 1); OBJ_SET_DIRTY(obj, 1); obj->next = NULL; }
u8 GUI_TouchXYGraph(struct guiObject *obj, struct touch *coords, u8 long_press) { struct guiXYGraph *graph = (struct guiXYGraph *)obj; (void)long_press; if (graph->touch_cb) { s32 x, y; x = (s32)(coords->x - obj->box.x) * (1 + graph->max_x - graph->min_x) / obj->box.width + graph->min_x; y = (s32)(obj->box.height -1 - (coords->y - obj->box.y)) * (1 + graph->max_y - graph->min_y) / obj->box.height + graph->min_y; if(graph->touch_cb(x, y, graph->cb_data)) { OBJ_SET_DIRTY(obj, 1); return 1; } } return 0; }
int GUI_TouchButton(struct guiObject *obj, int press_type) { //press_type: 1=long_press, -1=release struct guiButton *button = (struct guiButton *)obj; if (press_type == 0) { button->flags &= ~FLAG_LONGPRESS; } else if (press_type == 1) { button->flags |= FLAG_LONGPRESS; return 0; } OBJ_SET_DIRTY(objTOUCHED, 1); if (press_type == -1) { if(button->CallBack) { button->CallBack(objTOUCHED, button->cb_data); //The object may have been destroyed by now, the obj may be invalid } } return 1; }
void GUI_DrawObject(struct guiObject *obj) { #ifdef DEBUG_DRAW switch (obj->Type) { case UnknownGUI: printf("Draw Unknown: "); break; case CheckBox: printf("Draw Checkbox:"); break; case Dropdown: printf("Draw Dropdown:"); break; case Button: printf("Draw Button: "); break; case Label: printf("Draw Label: "); break; case Image: printf("Draw Image: "); break; case Dialog: printf("Draw Dialog: "); break; case XYGraph: printf("Draw XYGraph: "); break; case BarGraph: printf("Draw BarGraph:"); break; case TextSelect: printf("Draw TextSel: "); break; case Keyboard: printf("Draw Keyboard:"); break; case Scrollbar: printf("Draw ScrlBar: "); break; case Scrollable: printf("Draw Scrlable:"); break; case Rect: printf("Draw Rect: "); break; } printf(" ptr: %08x Selected: %s\n", obj, obj == objSELECTED ? "true" : "false"); #endif switch (obj->Type) { case UnknownGUI: break; case CheckBox: break; case Dropdown: break; case Button: GUI_DrawButton(obj); break; case Label: GUI_DrawLabel(obj); break; case Image: GUI_DrawImage(obj); break; case Dialog: GUI_DrawDialog(obj); break; case XYGraph: GUI_DrawXYGraph(obj); break; case BarGraph: GUI_DrawBarGraph(obj); break; case TextSelect: GUI_DrawTextSelect(obj); break; case Keyboard: GUI_DrawKeyboard(obj); break; case Scrollbar: GUI_DrawScrollbar(obj); break; case Scrollable: GUI_DrawScrollable(obj); break; case Rect: GUI_DrawRect(obj); break; } if (obj == objSELECTED && obj->Type != Scrollable) _gui_hilite_selected(obj); OBJ_SET_DIRTY(obj, 0); }
void _GUI_ChangeImage(struct guiImage *image, const char *file, u16 x_off, u16 y_off, u8 replace) { guiObject_t *obj = (guiObject_t *)image; //Use a CRC for comparison because the filename may change without the pointer changing u32 crc = Crc(file, strlen(file)); if (image->file != file || image->crc != crc || image->x_off != x_off || image->y_off != y_off) { if (replace) { // draw background where the old picture was bigger struct guiBox *box = &obj->box; u16 w, h; LCD_ImageDimensions(file, &w, &h); if (h < box->height) GUI_DrawBackground(box->x, box->y + h, box->width, box->height - h); // remove lower left part of old image if (w < box->width) GUI_DrawBackground(box->x + w, box->y, box->width - w, h < box->height ? h : box->height); // remove upper right part of old image box->width = w; box->height = h; } image->crc = crc; image->file = file; image->x_off = x_off; image->y_off = y_off; OBJ_SET_TRANSPARENT(obj, LCD_ImageIsTransparent(file)); OBJ_SET_DIRTY(obj, 1); } }
void _GUI_Redraw(struct guiObject *obj) { OBJ_SET_DIRTY(obj, 1); }
unsigned handle_buttons(u32 button, unsigned flags, void *data) { (void)data; //When modal, we capture all button presses int modalActive = GUI_IsModal() ? 1 : 0; if(USE_4BUTTON_MODE) { // IN 4 button mode, up/down can also act as left/right for TextSelect if (objACTIVE) { if (CHAN_ButtonIsPressed(button, BUT_UP)) { button = CHAN_ButtonMask(BUT_LEFT); } else if (CHAN_ButtonIsPressed(button, BUT_DOWN)) { button = CHAN_ButtonMask(BUT_RIGHT); } else if (CHAN_ButtonIsPressed(button, BUT_ENTER)) { if (flags & BUTTON_RELEASE) objACTIVE = NULL; } else if (CHAN_ButtonIsPressed(button, BUT_EXIT)) { if (flags & BUTTON_RELEASE) objACTIVE = NULL; return 1; } } else { if (objSELECTED && CHAN_ButtonIsPressed(button, BUT_ENTER) && objSELECTED->Type == TextSelect) { if (flags & BUTTON_RELEASE) { objACTIVE = objSELECTED; } return 1; } } } //printf("Button: %08x Flags: %08x Active: %08x\n", button, flags, objACTIVE); if (CHAN_ButtonIsPressed(button, BUT_LEFT) || CHAN_ButtonIsPressed(button, BUT_RIGHT) || CHAN_ButtonIsPressed(button, BUT_ENTER)) { // Widgets can only handle Left, Right and Enter if (objSELECTED) return GUI_ObjButton(objSELECTED, button, flags) || modalActive; return modalActive; } if (flags & (BUTTON_LONGPRESS | BUTTON_RELEASE)) { if ((flags & BUTTON_HAD_LONGPRESS) & (flags & BUTTON_RELEASE)) { //ignore long-press release return modalActive; } else if (CHAN_ButtonIsPressed(button, BUT_DOWN) || CHAN_ButtonIsPressed(button, BUT_UP)) { struct guiObject *obj = (CHAN_ButtonIsPressed(button, BUT_DOWN) || ! objSELECTED) ? GUI_GetNextSelectable(objSELECTED) : GUI_GetPrevSelectable(objSELECTED); if (obj && obj != objSELECTED) { GUI_SetSelected(obj); } } else if (! (flags & BUTTON_LONGPRESS) && objSELECTED && CHAN_ButtonIsPressed(button, BUT_EXIT)) { if (objDIALOG) { //Why doesn't the dialog handle its own buttons? DialogClose(objDIALOG, 0); } else { OBJ_SET_DIRTY(objSELECTED, 1); objSELECTED = NULL; if (select_notify) select_notify(objSELECTED); } } } else if (! objSELECTED && CHAN_ButtonIsPressed(button, BUT_EXIT)) { // We need to tell the button handler that we will handle this press // But we ignore an EXIT if there is nothing selected return modalActive; } return 1; }
u8 GUI_TouchTextSelect(struct guiObject *obj, struct touch *coords, s8 press_type) { struct guiBox box = obj->box; struct guiTextSelect *select = (struct guiTextSelect *)obj; if (press_type < 0) { if(! select->state) { return 0; } else if(select->state & 0x80) { select->state = 0; OBJ_SET_DIRTY(obj, 1); return 1; } else if(select->state == 0x01) { select->state = 0; OBJ_SET_DIRTY(obj, 1); select->ValueCB(obj, -1, select->cb_data); return 1; } else if(select->state == 0x02) { select->state = 0; OBJ_SET_DIRTY(obj, 1); select->ValueCB(obj, 1, select->cb_data); return 1; } else if(select->state == 0x04) { select->state = 0; OBJ_SET_DIRTY(obj, 1); select->SelectCB(obj, select->cb_data); return 1; } printf("Error: Should not get here\n"); return 0; } box.width = ARROW_WIDTH; // only used for RTC config in Devo12 #if HAS_RTC if (select->type == TEXTSELECT_VERT_64) { box.height = ARROW_HEIGHT; box.x = obj->box.x + (obj->box.width - ARROW_WIDTH) / 2; box.y = obj->box.y + obj->box.height - ARROW_HEIGHT; } #endif if (select->enable & 0x01) { if (coords_in_box(&box, coords)) { if (! press_type) { if (! select->state) { select->state = 0x01; OBJ_SET_DIRTY(obj, 1); } } else if (select->ValueCB) { OBJ_SET_DIRTY(obj, 1); select->ValueCB(obj, -2, select->cb_data); select->state |= 0x80; } return 1; } // only used for RTC config in Devo12 #if HAS_RTC if (select->type == TEXTSELECT_VERT_64) { box.y = obj->box.y; } else #endif box.x = obj->box.x + obj->box.width - ARROW_WIDTH; if (coords_in_box(&box, coords)) { if (! press_type) { if (! select->state) { select->state = 0x02; OBJ_SET_DIRTY(obj, 1); } } else if (select->ValueCB) { OBJ_SET_DIRTY(obj, 1); select->ValueCB(obj, 2, select->cb_data); select->state |= 0x80; } return 1; } } if (! press_type && ! select->state && select->SelectCB && (select->enable & 0x02)) { OBJ_SET_DIRTY(obj, 1); select->state = 0x04; return 1; } return 0; }