/* ChibiOS/RT - Copyright (C) 2012 Joel Bodenmann aka Tectu This file is part of ChibiOS/GFX. ChibiOS/GFX 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. ChibiOS/GFX 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 . */ #include "gui.h" static struct guiNode_t *firstGUI = NULL; uint16_t x, y; // global touchpad coordinates static uint8_t addElement(struct guiNode_t *newNode) { struct guiNode_t *new; if(firstGUI == NULL) { firstGUI = chHeapAlloc(NULL, sizeof(struct guiNode_t)); if(firstGUI == NULL) return 0; *firstGUI = *newNode; firstGUI->next = NULL; } else { new = firstGUI; while(new->next != NULL) new = new->next; new->next = chHeapAlloc(NULL, sizeof(struct guiNode_t)); if(new->next == NULL) return 0; new = new->next; *new = *newNode; new->next = NULL; } return 1; } static uint8_t deleteElement(char *label) { struct guiNode_t *pointer, *pointer1; if(firstGUI != NULL) { if(strcmp(firstGUI->label, label) == 0) { pointer = firstGUI->next; chHeapFree(firstGUI); firstGUI = pointer; } else { pointer = firstGUI; while(pointer->next != NULL) { pointer1 = pointer->next; if(strcmp(firstGUI->label, label) == 0) { pointer->next = pointer1->next; chHeapFree(pointer1); break; } pointer = pointer1; } } return 1; // successful } return 0; // not successful } void guiPrintElements(BaseSequentialStream *chp) { struct guiNode_t *pointer = firstGUI; chprintf(chp, "\r\n\nguiNodes:\r\n\n"); while(pointer != NULL) { chprintf(chp, "x0: %d\r\n", pointer->x0); chprintf(chp, "y0: %d\r\n", pointer->y0); chprintf(chp, "x1: %d\r\n", pointer->x1); chprintf(chp, "y1: %d\r\n", pointer->y1); chprintf(chp, "label: %s\r\n", pointer->label); chprintf(chp, "active: %d\r\n", *(pointer->active)); chprintf(chp, "state: %d\r\n", *(pointer->state)); chprintf(chp, "*next: 0x%x\r\n", pointer->next); chprintf(chp, "\r\n\n"); pointer = pointer->next; } } static inline void buttonUpdate(struct guiNode_t *node) { if(x >= node->x0 && x <= node->x1 && y >= node->y0 && y <= node->y1) { *(node->state) = 1; } else { *(node->state) = 0; } } static inline void sliderUpdate(struct guiNode_t *node) { uint16_t length = 1; if(node->orientation == horizontal) length = node->x1 - node->x0; else if(node->orientation == vertical) length = node->y1 - node->y0; if(node->mode == modePassive) { node->percentage = *(node->state); } else if(node->mode == modeActive) { if(x >= node->x0 && x <= node->x1 && y >= node->y0 && y <= node->y1) { if(node->orientation == horizontal) { node->percentage = (((x - node->x0) * 100) / length); } else if(node->orientation == vertical) { node->percentage = (((y - node->y0) * 100) / length); } } *(node->state) = node->percentage; } // a bit of safety here if(node->percentage > 100) node->percentage = 100; if(node->orientation == horizontal) { node->value = ((((node->x1)-(node->x0)) * node->percentage) / 100); if(node->oldValue > node->value || node->value == 0) lcdFillArea(node->x0+1, node->y0+1, node->x1, node->y1, node->bkColor); else lcdDrawRect(node->x0+1, node->y0+1, node->x0+node->value, node->y1, filled, node->valueColor); } else if(node->orientation == vertical) { node->value = ((((node->y1)-(node->y0)) * node->percentage) / 100); if(node->oldValue > node->value || node->value == 0) lcdFillArea(node->x0+1, node->y0+1, node->x1, node->y1, node->bkColor); else lcdDrawRect(node->x0+1, node->y0+1, node->x1, node->y0+node->value, filled, node->valueColor); } node->oldValue = node->value; } static inline void wheelUpdate(struct guiNode_t *node) { (void)node; } static inline void keymatrixUpdate(struct guiNode_t *node) { (void)node; } static void guiThread(const uint16_t interval) { struct guiNode_t *node; chRegSetThreadName("GUI"); while(TRUE) { for(node = firstGUI; node; node = node->next) { // check if GUI element is set active if(*(node->active) == active) { x = tpReadX(); y = tpReadY(); switch(node->type) { case button: buttonUpdate(node); break; case slider: sliderUpdate(node); break; case wheel: wheelUpdate(node); break; case keymatrix: keymatrixUpdate(node); break; } } } chThdSleepMilliseconds(interval); } } Thread *guiInit(uint16_t interval, tprio_t priority) { Thread *tp = NULL; tp = chThdCreateFromHeap(NULL, THD_WA_SIZE(512), priority, guiThread, interval); return tp; } uint8_t guiDeleteElement(char *label) { return deleteElement(label); } uint8_t guiDrawButton(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, char *str, font_t font, uint16_t fontColor, uint16_t buttonColor, uint16_t shadow, char *label, uint8_t *active, uint8_t *state) { struct guiNode_t *newNode; uint16_t i; newNode = chHeapAlloc(NULL, sizeof(struct guiNode_t)); if(newNode == NULL) return 0; newNode->type = button; newNode->label = label; newNode->x0 = x0; newNode->y0 = y0; newNode->x1 = x1; newNode->y1 = y1; newNode->shadow = shadow; newNode->active = active; newNode->state = state; if(addElement(newNode) != 1) return 0; lcdDrawRectString(x0, y0, x1, y1, str, font, fontColor, buttonColor); if(shadow != 0) { for(i = 0; i < shadow; i++) { lcdDrawLine(x0+shadow, y1+i, x1+shadow-1, y1+i, Black); lcdDrawLine(x1+i, y0+shadow, x1+i, y1+shadow-1, Black); } } chHeapFree(newNode); return 1; } uint8_t guiDrawSlider(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t orientation, uint8_t mode, uint16_t frameColor, uint16_t bkColor, uint16_t valueColor, char *label, uint8_t *active, uint8_t *value) { struct guiNode_t *newNode; newNode = chHeapAlloc(NULL, sizeof(struct guiNode_t)); if(newNode == NULL) return 0; newNode->type = slider; newNode->label = label; newNode->x0 = x0; newNode->y0 = y0; newNode->x1 = x1; newNode->y1 = y1; newNode->mode = mode; newNode->bkColor = bkColor; newNode->valueColor = valueColor; newNode->state = value; newNode->active = active; newNode->orientation = orientation; newNode->percentage = 0; if(addElement(newNode) != 1) return 0; (void)bkColor; (void)valueColor; // lcdDraw functions lcdDrawRect(x0, y0, x1, y1, frame, frameColor); chHeapFree(newNode); return 1; } uint8_t guiDrawWheel(uint16_t x0, uint16_t y0, uint16_t radius1, uint16_t radius2, uint16_t bkColor, uint16_t valueColor, char *label, uint8_t *active, uint8_t *value) { struct guiNode_t *newNode; newNode = chHeapAlloc(NULL, sizeof(struct guiNode_t)); if(newNode == NULL) return 0; newNode->type = wheel; newNode->label = label; newNode->x0 = x0; newNode->y0 = y0; newNode->r1 = radius1; newNode->r2 = radius2; newNode->active = active; newNode->state = value; if(addElement(newNode) != 1) return 0; (void)bkColor; (void)valueColor; // lcdDraw functions chHeapFree(newNode); return 1; } uint8_t guiDrawKeymatrix(uint16_t x0, uint16_t y0, uint16_t size, uint16_t space, uint16_t shadow, uint16_t buttonColor, uint16_t fontColor, font_t font, char *label, uint8_t *active, uint8_t *value) { struct guiNode_t *newNode; newNode = chHeapAlloc(NULL, sizeof(struct guiNode_t)); if(newNode == NULL) return 0; newNode->type = keymatrix; newNode->label = label; newNode->x0 = x0; newNode->y0 = y0; newNode->shadow = shadow; newNode->active = active; newNode->state = value; if(addElement(newNode) != 1) return 0; // lcdDraw functions (void)size; (void)space; (void)buttonColor; (void)fontColor; (void)font; chHeapFree(newNode); return 1; }