/* * Roo/E, the Kangaroo Punch Portable GUI Toolkit * Copyright (C) 2022 Scott Duensing * * http://kangaroopunch.com * * * This file is part of Roo/E. * * Roo/E is free software: you can redistribute it and/or modify it under the * terms of the GNU Affero General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) * any later version. * * Roo/E 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 Affero General Public License * along with Roo/E. If not, see . * */ #include "../wmwindow.h" #include "array.h" #include "radio.h" uint8_t __MAGIC_RADIO = 0; static void radioClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data); static void radioDestroy(struct WidgetS *widget, ...); static void radioPaint(struct WidgetS *widget, ...); static void radioClick(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data) { RadioT *r = (RadioT *)widget; if (event == CLICK_LEFT_UP) { // Select this radio button. radioValueSet(r, 1); // Call the actual click event if it exists. if (r->handler) r->handler(widget, x, y, event, data); // Repaint. widgetDirtySet(widget, 1); } } void radioClickSet(RadioT *radio, ClickHandlerT handler, void *data) { radio->handler = handler; radio->base.data = data; } RadioT *radioCreate(char *label, uint8_t group, uint8_t value, ...) { RadioT *r = NULL; uint16_t width; uint16_t height; FontT *f = __guiFontVGA8x16; NEW(RadioT, r); memset(r, 0, sizeof(RadioT)); r->group = group; r->value = value; r->label = labelCreate(LABEL_ALIGN_LEFT, f, label); if (!r->label) { DEL(r); return NULL; } // Radio button is (height - 3) square. We skip two pixels on the bottom and one on the top to look okay with decender characters. height = fontHeightGet(f); width = fontWidthCharactersGet(label) * fontWidthGet(f) + (height * 3); widgetBaseSet(W(r), __MAGIC_RADIO, width, height); return r; } static void radioDestroy(struct WidgetS *widget, ...) { RadioT *r = (RadioT *)widget; // Do not destroy label here - the parent owns it at this point. DEL(r); } static void radioPaint(struct WidgetS *widget, ...) { RadioT *r = (RadioT *)widget; int16_t w; int16_t h; int16_t y; int16_t x; int16_t d; int16_t i; int16_t change; ColorT temp; ColorT top; ColorT bottom; ColorT fill; if (widgetDirtyGet(widget)) { widgetDirtySet(widget, 0); // Work out some coordinates. h = fontHeightGet(r->label->font) - 2; w = h * 1.5; x = r->base.r.x + (h * 0.5); // X center coordinate. change = r->base.r.y + (h * 0.5); // Where, vertically, we start drawing the bottom of the diamond. d = 1; // Direction of increment. i = 0; // X increment. // Set up colors. if (r->value) { fill = GUI_DARKGRAY; top = GUI_BLACK; bottom = GUI_WHITE; } else { fill = GUI_WHITE; top = GUI_WHITE; bottom = GUI_BLACK; } // Paint radio button. for (y=r->base.r.y + 1; y<=r->base.r.y + h - 1; y++) { surfaceLineH(x - i, x + i, y, fill); surfacePixelSet(x - i, y, top); surfacePixelSet(x + i, y, top); if (y == change) { d = -d; temp = top; top = bottom; bottom = temp; } i += d; } // Finish initializing. if (!r->attached) { r->attached = 1; widgetAdd(r->base.parent, r->base.r.x + w, r->base.r.y, W(r->label)); } } } RegisterT *radioRegister(uint8_t magic) { static RegisterT reg = { "Radio", radioClick, radioDestroy, radioPaint, NULL // No unregister handler. }; // One-time widget startup code. __MAGIC_RADIO = magic; return ® } uint8_t radioValueGet(RadioT *radio) { return radio->value; } void radioValueSet(RadioT *radio, uint8_t value) { int16_t i; WidgetT *p; RadioT *r; radio->value = (value != 0); p = radio->base.parent; if (radio->value) { // We were selected, deselect other radio buttons in this group. for (i=0; ichildren); i++) { // Is this a radio button? Is it not us? if (p->children[i]->magic == __MAGIC_RADIO && p->children[i] != W(radio)) { r = (RadioT *)p->children[i]; // Is it currently selected? if (r->value && r->group == radio->group) { // Clear it and redraw. r->value = 0; widgetDirtySet(W(r), 1); break; } } } } else { // We were cleared. Select another radio button in this group. for (i=0; ichildren); i++) { // Is this a radio button? Is it not us? if (p->children[i]->magic == __MAGIC_RADIO && p->children[i] != W(radio)) { r = (RadioT *)p->children[i]; if (r->group == radio->group) { // Select it and redraw. r->value = 1; widgetDirtySet(W(r), 1); break; } } } } // Repaint. widgetDirtySet(W(radio), 1); }